// 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_ }
func (tm *TypeMap) arrayLLVMType(a *types.Array) llvm.Type { return llvm.ArrayType(tm.ToLLVM(a.Elt), int(a.Len)) }
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)) }
func (tm *llvmTypeMap) arrayLLVMType(a *types.Array) llvm.Type { return llvm.ArrayType(tm.ToLLVM(a.Elem()), int(a.Len())) }
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)) }