Beispiel #1
0
// makeLiteralSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeLiteralSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(c.types.inttype, uint64(len(v)), false)
	eltType := c.types.ToLLVM(elttyp)
	arrayType := llvm.ArrayType(eltType, len(v))
	mem := c.createMalloc(llvm.SizeOf(arrayType))
	mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
	for i, value := range v {
		indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.NewSlice(elttyp)
	struct_ := llvm.Undef(c.types.ToLLVM(slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
	return struct_
}
Beispiel #2
0
func (tm *TypeMap) arrayLLVMType(a *types.Array) llvm.Type {
	return llvm.ArrayType(tm.ToLLVM(a.Elt), int(a.Len))
}
Beispiel #3
0
func (c *compiler) VisitCompositeLit(lit *ast.CompositeLit) Value {
	typ := c.types.expr[lit]
	var valuemap map[interface{}]Value
	var valuelist []Value
	_, isstruct := types.Underlying(typ).(*types.Struct)
	if lit.Elts != nil {
		for _, elt := range lit.Elts {
			var value Value
			if kv, iskv := elt.(*ast.KeyValueExpr); iskv {
				value = c.VisitExpr(kv.Value)
				if valuemap == nil {
					valuemap = make(map[interface{}]Value)
				}
				var key interface{}
				if isstruct {
					key = kv.Key.(*ast.Ident).Name
				} else {
					key = c.VisitExpr(kv.Key)
				}
				valuemap[key] = value
			} else {
				value = c.VisitExpr(elt)
				valuelist = append(valuelist, value)
			}
		}
	}

	// For array/slice types, convert key:value to contiguous
	// values initialiser.
	switch types.Underlying(typ).(type) {
	case *types.Array, *types.Slice:
		if len(valuemap) > 0 {
			maxi := int64(-1)
			for key, _ := range valuemap {
				i := key.(ConstValue).Int64()
				if i < 0 {
					panic("array index must be non-negative integer constant")
				} else if i > maxi {
					maxi = i
				}
			}
			valuelist = make([]Value, maxi+1)
			for key, value := range valuemap {
				i := key.(ConstValue).Int64()
				valuelist[i] = value
			}
		}
	}

	origtyp := typ
	switch typ := types.Underlying(typ).(type) {
	case *types.Array:
		elttype := typ.Elt
		llvmelttype := c.types.ToLLVM(elttype)
		llvmvalues := make([]llvm.Value, typ.Len)
		for i := range llvmvalues {
			var value Value
			if i < len(valuelist) {
				value = valuelist[i]
			}
			if value == nil {
				llvmvalues[i] = llvm.ConstNull(llvmelttype)
			} else if _, ok := value.(ConstValue); ok || value.LLVMValue().IsConstant() {
				llvmvalues[i] = value.Convert(elttype).LLVMValue()
			} else {
				llvmvalues[i] = llvm.Undef(llvmelttype)
			}
		}
		array := llvm.ConstArray(llvmelttype, llvmvalues)
		for i, value := range valuelist {
			if llvmvalues[i].IsUndef() {
				value := value.Convert(elttype).LLVMValue()
				array = c.builder.CreateInsertValue(array, value, i, "")
			}
		}
		return c.NewLLVMValue(array, origtyp)

	case *types.Slice:
		ptr := c.createTypeMalloc(c.types.ToLLVM(typ))

		eltType := c.types.ToLLVM(typ.Elt)
		arrayType := llvm.ArrayType(eltType, len(valuelist))
		valuesPtr := c.createMalloc(llvm.SizeOf(arrayType))
		valuesPtr = c.builder.CreateIntToPtr(valuesPtr, llvm.PointerType(eltType, 0), "")

		//valuesPtr = c.builder.CreateBitCast(valuesPtr, llvm.PointerType(valuesPtr.Type(), 0), "")
		// TODO check result of mallocs
		length := llvm.ConstInt(llvm.Int32Type(), uint64(len(valuelist)), false)
		c.builder.CreateStore(valuesPtr, c.builder.CreateStructGEP(ptr, 0, "")) // data
		c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 1, ""))    // len
		c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 2, ""))    // cap
		null := llvm.ConstNull(c.types.ToLLVM(typ.Elt))
		for i, value := range valuelist {
			index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false)
			valuePtr := c.builder.CreateGEP(valuesPtr, []llvm.Value{index}, "")
			if value == nil {
				c.builder.CreateStore(null, valuePtr)
			} else {
				c.builder.CreateStore(value.Convert(typ.Elt).LLVMValue(), valuePtr)
			}
		}
		m := c.NewLLVMValue(ptr, &types.Pointer{Base: origtyp})
		return m.makePointee()

	case *types.Struct:
		values := valuelist
		llvmtyp := c.types.ToLLVM(typ)
		ptr := c.createTypeMalloc(llvmtyp)

		bzero := c.NamedFunction("runtime.bzero", "func f(unsafe.Pointer, uintptr)")
		ptrintval := c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
		args := []llvm.Value{ptrintval, llvm.SizeOf(llvmtyp)}
		c.builder.CreateCall(bzero, args, "")

		if valuemap != nil {
			for key, value := range valuemap {
				fieldName := key.(string)
				index := typ.FieldIndices[fieldName]
				for len(values) <= int(index) {
					values = append(values, nil)
				}
				values[index] = value
			}
		}
		for i, value := range values {
			if value != nil {
				elttype := typ.Fields[i].Type.(types.Type)
				llvm_value := value.Convert(elttype).LLVMValue()
				ptr := c.builder.CreateStructGEP(ptr, i, "")
				c.builder.CreateStore(llvm_value, ptr)
			}
		}
		m := c.NewLLVMValue(ptr, &types.Pointer{Base: origtyp})
		return m.makePointee()

	case *types.Map:
		value := llvm.ConstNull(c.types.ToLLVM(typ))
		// TODO initialise map
		return c.NewLLVMValue(value, origtyp)
	}
	panic(fmt.Sprint("Unhandled type kind: ", typ))
}
Beispiel #4
0
func (tm *llvmTypeMap) arrayLLVMType(a *types.Array) llvm.Type {
	return llvm.ArrayType(tm.ToLLVM(a.Elem()), int(a.Len()))
}
Beispiel #5
0
func (c *compiler) VisitCompositeLit(lit *ast.CompositeLit) (v *LLVMValue) {
	typ := c.types.expr[lit].Type
	var valuemap map[interface{}]Value
	var valuelist []Value

	if ptr, ok := typ.(*types.Pointer); ok {
		typ = ptr.Elem()
		defer func() {
			v = v.pointer
		}()
	}

	var isstruct, isarray, isslice, ismap bool
	switch typ.Underlying().(type) {
	case *types.Struct:
		isstruct = true
	case *types.Array:
		isarray = true
	case *types.Slice:
		isslice = true
	case *types.Map:
		ismap = true
	default:
		panic(fmt.Errorf("Unhandled type: %s", typ))
	}

	if lit.Elts != nil {
		for i, elt := range lit.Elts {
			if kv, iskv := elt.(*ast.KeyValueExpr); iskv {
				if valuemap == nil {
					valuemap = make(map[interface{}]Value)
				}
				var key interface{}
				var elttyp types.Type
				switch {
				case isstruct:
					name := kv.Key.(*ast.Ident).Name
					key = name
					typ := typ.Underlying().(*types.Struct)
					elttyp = typ.Field(fieldIndex(typ, name)).Type
				case isarray:
					key = c.types.expr[kv.Key].Value
					typ := typ.Underlying().(*types.Array)
					elttyp = typ.Elem()
				case isslice:
					key = c.types.expr[kv.Key].Value
					typ := typ.Underlying().(*types.Slice)
					elttyp = typ.Elem()
				case ismap:
					key = c.VisitExpr(kv.Key)
					typ := typ.Underlying().(*types.Map)
					elttyp = typ.Elem()
				default:
					panic("unreachable")
				}
				c.convertUntyped(kv.Value, elttyp)
				valuemap[key] = c.VisitExpr(kv.Value)
			} else {
				switch {
				case isstruct:
					typ := typ.Underlying().(*types.Struct)
					c.convertUntyped(elt, typ.Field(i).Type)
				case isarray:
					typ := typ.Underlying().(*types.Array)
					c.convertUntyped(elt, typ.Elem())
				case isslice:
					typ := typ.Underlying().(*types.Slice)
					c.convertUntyped(elt, typ.Elem())
				}
				value := c.VisitExpr(elt)
				valuelist = append(valuelist, value)
			}
		}
	}

	// For array/slice types, convert key:value to contiguous
	// values initialiser.
	switch typ.Underlying().(type) {
	case *types.Array, *types.Slice:
		if len(valuemap) > 0 {
			var maxkey uint64
			for key, _ := range valuemap {
				key, _ := exact.Uint64Val(key.(exact.Value))
				if key > maxkey {
					maxkey = key
				}
			}
			valuelist = make([]Value, maxkey+1)
			for key, value := range valuemap {
				key, _ := exact.Uint64Val(key.(exact.Value))
				valuelist[key] = value
			}
		}
	}

	origtyp := typ
	switch typ := typ.Underlying().(type) {
	case *types.Array:
		elttype := typ.Elem()
		llvmelttype := c.types.ToLLVM(elttype)
		llvmvalues := make([]llvm.Value, typ.Len())
		for i := range llvmvalues {
			var value Value
			if i < len(valuelist) {
				value = valuelist[i]
			}
			if value == nil {
				llvmvalues[i] = llvm.ConstNull(llvmelttype)
			} else if value.LLVMValue().IsConstant() {
				llvmvalues[i] = value.Convert(elttype).LLVMValue()
			} else {
				llvmvalues[i] = llvm.Undef(llvmelttype)
			}
		}
		array := llvm.ConstArray(llvmelttype, llvmvalues)
		for i, value := range valuelist {
			if llvmvalues[i].IsUndef() {
				value := value.Convert(elttype).LLVMValue()
				array = c.builder.CreateInsertValue(array, value, i, "")
			}
		}
		return c.NewValue(array, origtyp)

	case *types.Slice:
		ptr := c.createTypeMalloc(c.types.ToLLVM(typ))

		eltType := c.types.ToLLVM(typ.Elem())
		arrayType := llvm.ArrayType(eltType, len(valuelist))
		valuesPtr := c.createMalloc(llvm.SizeOf(arrayType))
		valuesPtr = c.builder.CreateIntToPtr(valuesPtr, llvm.PointerType(eltType, 0), "")

		//valuesPtr = c.builder.CreateBitCast(valuesPtr, llvm.PointerType(valuesPtr.Type(), 0), "")
		length := llvm.ConstInt(c.types.inttype, uint64(len(valuelist)), false)
		c.builder.CreateStore(valuesPtr, c.builder.CreateStructGEP(ptr, 0, "")) // data
		c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 1, ""))    // len
		c.builder.CreateStore(length, c.builder.CreateStructGEP(ptr, 2, ""))    // cap
		null := llvm.ConstNull(c.types.ToLLVM(typ.Elem()))
		for i, value := range valuelist {
			index := llvm.ConstInt(llvm.Int32Type(), uint64(i), false)
			valuePtr := c.builder.CreateGEP(valuesPtr, []llvm.Value{index}, "")
			if value == nil {
				c.builder.CreateStore(null, valuePtr)
			} else {
				c.builder.CreateStore(value.Convert(typ.Elem()).LLVMValue(), valuePtr)
			}
		}
		m := c.NewValue(ptr, types.NewPointer(origtyp))
		return m.makePointee()

	case *types.Struct:
		values := valuelist
		llvmtyp := c.types.ToLLVM(typ)
		ptr := c.createTypeMalloc(llvmtyp)

		if valuemap != nil {
			for key, value := range valuemap {
				index := fieldIndex(typ, key.(string))
				for len(values) <= index {
					values = append(values, nil)
				}
				values[index] = value
			}
		}
		for i, value := range values {
			if value != nil {
				elttype := typ.Field(i).Type
				llvm_value := value.Convert(elttype).LLVMValue()
				ptr := c.builder.CreateStructGEP(ptr, i, "")
				c.builder.CreateStore(llvm_value, ptr)
			}
		}
		m := c.NewValue(ptr, types.NewPointer(origtyp))
		return m.makePointee()

	case *types.Map:
		value := llvm.ConstNull(c.types.ToLLVM(typ))
		// TODO initialise map
		return c.NewValue(value, origtyp)
	}
	panic(fmt.Sprint("Unhandled type kind: ", typ))
}