func (d subrangeDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false), llvm.ConstInt(llvm.Int64Type(), uint64(d.low), true), llvm.ConstInt(llvm.Int64Type(), uint64(d.high), true), }) }
func (c *compiler) VisitLen(expr *ast.CallExpr) Value { value := c.VisitExpr(expr.Args[0]) typ := value.Type() if name, ok := typ.Underlying().(*types.Named); ok { typ = name.Underlying() } var lenvalue llvm.Value switch typ := typ.Underlying().(type) { case *types.Pointer: atyp := typ.Elem().Underlying().(*types.Array) lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false) case *types.Slice: sliceval := value.LLVMValue() lenvalue = c.builder.CreateExtractValue(sliceval, 1, "") case *types.Map: mapval := value.LLVMValue() f := c.NamedFunction("runtime.maplen", "func f(m uintptr) int") lenvalue = c.builder.CreateCall(f, []llvm.Value{mapval}, "") case *types.Array: lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false) case *types.Basic: if isString(typ) { value := value.(*LLVMValue) lenvalue = c.builder.CreateExtractValue(value.LLVMValue(), 1, "") } case *types.Chan: panic("len(chan) unimplemented") } return c.NewValue(lenvalue, types.Typ[types.Int]) }
// makeMapLiteral makes a map with the specified keys and values. func (c *compiler) makeMapLiteral(typ types.Type, keys, values []Value) *LLVMValue { var count, keysptr, valuesptr llvm.Value dyntyp := c.types.ToRuntime(typ) dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "") if len(keys) == 0 { count = llvm.ConstNull(c.types.inttype) keysptr = llvm.ConstNull(c.target.IntPtrType()) valuesptr = keysptr } else { maptyp := typ.Underlying().(*types.Map) keytyp := maptyp.Key() valtyp := maptyp.Elem() count = llvm.ConstInt(c.types.inttype, uint64(len(keys)), false) keysptr = c.builder.CreateArrayAlloca(c.types.ToLLVM(keytyp), count, "") valuesptr = c.builder.CreateArrayAlloca(c.types.ToLLVM(valtyp), count, "") for i := range keys { gepindices := []llvm.Value{llvm.ConstInt(c.types.inttype, uint64(i), false)} key := keys[i].Convert(keytyp).LLVMValue() ptr := c.builder.CreateGEP(keysptr, gepindices, "") c.builder.CreateStore(key, ptr) value := values[i].Convert(valtyp).LLVMValue() ptr = c.builder.CreateGEP(valuesptr, gepindices, "") c.builder.CreateStore(value, ptr) } keysptr = c.builder.CreatePtrToInt(keysptr, c.target.IntPtrType(), "") valuesptr = c.builder.CreatePtrToInt(valuesptr, c.target.IntPtrType(), "") } f := c.NamedFunction("runtime.makemap", "func(t uintptr, n int, keys, values uintptr) uintptr") mapval := c.builder.CreateCall(f, []llvm.Value{dyntyp, count, keysptr, valuesptr}, "") return c.NewValue(mapval, typ) }
// interfaceMethod returns a function pointer for the specified // interface and method pair. func (c *compiler) interfaceMethod(iface *LLVMValue, method *types.Func) *LLVMValue { lliface := iface.LLVMValue() llitab := c.builder.CreateExtractValue(lliface, 0, "") llvalue := c.builder.CreateExtractValue(lliface, 1, "") sig := method.Type().(*types.Signature) methodset := c.types.MethodSet(sig.Recv().Type()) // TODO(axw) cache ordered method index var index int for i := 0; i < methodset.Len(); i++ { if methodset.At(i).Obj() == method { index = i break } } llitab = c.builder.CreateBitCast(llitab, llvm.PointerType(c.runtime.itab.llvm, 0), "") llifn := c.builder.CreateGEP(llitab, []llvm.Value{ llvm.ConstInt(llvm.Int32Type(), 0, false), llvm.ConstInt(llvm.Int32Type(), 5, false), // index of itab.fun }, "") _ = index llifn = c.builder.CreateGEP(llifn, []llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(index), false), }, "") llifn = c.builder.CreateLoad(llifn, "") // Strip receiver. sig = types.NewSignature(nil, nil, sig.Params(), sig.Results(), sig.Variadic()) llfn := llvm.Undef(c.types.ToLLVM(sig)) llifn = c.builder.CreateIntToPtr(llifn, llfn.Type().StructElementTypes()[0], "") llfn = c.builder.CreateInsertValue(llfn, llifn, 0, "") llfn = c.builder.CreateInsertValue(llfn, llvalue, 1, "") return c.NewValue(llfn, sig) }
func (c *compiler) defineMemcpyFunction(fn llvm.Value) { entry := llvm.AddBasicBlock(fn, "entry") c.builder.SetInsertPointAtEnd(entry) dst, src, size := fn.Param(0), fn.Param(1), fn.Param(2) pint8 := llvm.PointerType(llvm.Int8Type(), 0) dst = c.builder.CreateIntToPtr(dst, pint8, "") src = c.builder.CreateIntToPtr(src, pint8, "") sizeType := size.Type() sizeBits := sizeType.IntTypeWidth() memcpyName := "llvm.memcpy.p0i8.p0i8.i" + strconv.Itoa(sizeBits) memcpy := c.module.NamedFunction(memcpyName) if memcpy.IsNil() { paramtypes := []llvm.Type{ pint8, pint8, size.Type(), llvm.Int32Type(), llvm.Int1Type()} memcpyType := llvm.FunctionType(llvm.VoidType(), paramtypes, false) memcpy = llvm.AddFunction(c.module.Module, memcpyName, memcpyType) } args := []llvm.Value{ dst, src, size, llvm.ConstInt(llvm.Int32Type(), 1, false), // single byte alignment llvm.ConstInt(llvm.Int1Type(), 0, false), // not volatile } c.builder.CreateCall(memcpy, args, "") c.builder.CreateRetVoid() }
func (d *debugInfo) setLocation(b llvm.Builder, pos token.Pos) { position := d.Fset.Position(pos) b.SetCurrentDebugLocation(llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(position.Line), true), llvm.ConstInt(llvm.Int32Type(), uint64(position.Column), true), d.MDNode(d.context()), llvm.Value{}, })) }
func (d *BlockDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false), info.mdFileNode(d.File), info.MDNode(d.Context), llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false), llvm.ConstInt(llvm.Int32Type(), uint64(d.Column), false), llvm.ConstInt(llvm.Int32Type(), uint64(d.Id), false), }) }
func (d *LocalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false), info.MDNode(d.Context), llvm.MDString(d.Name), info.mdFileNode(d.File), llvm.ConstInt(llvm.Int32Type(), uint64(d.Line)|(uint64(d.Argument)<<24), false), info.MDNode(d.Type), llvm.ConstNull(llvm.Int32Type()), // flags llvm.ConstNull(llvm.Int32Type()), // optional reference to inline location }) }
func (c *compiler) VisitAppend(expr *ast.CallExpr) Value { s := c.VisitExpr(expr.Args[0]) elemtyp := s.Type().Underlying().(*types.Slice).Elem() if len(expr.Args) == 1 { return s } else if expr.Ellipsis.IsValid() { c.convertUntyped(expr.Args[1], s.Type()) } else { for _, arg := range expr.Args[1:] { c.convertUntyped(arg, elemtyp) } } sliceappend := c.NamedFunction("runtime.sliceappend", "func(t uintptr, dst, src slice) slice") i8slice := sliceappend.Type().ElementType().ReturnType() i8ptr := c.types.ToLLVM(types.NewPointer(types.Typ[types.Int8])) // Coerce first argument into an []int8. a_ := s.LLVMValue() sliceTyp := a_.Type() a := c.coerceSlice(a_, i8slice) var b llvm.Value if expr.Ellipsis.IsValid() { // Pass the provided slice straight through. If it's a string, // convert it to a []byte first. elem := c.VisitExpr(expr.Args[1]).Convert(s.Type()) b = c.coerceSlice(elem.LLVMValue(), i8slice) } else { // Construct a fresh []int8 for the temporary slice. n := llvm.ConstInt(c.types.inttype, uint64(len(expr.Args)-1), false) mem := c.builder.CreateArrayAlloca(c.types.ToLLVM(elemtyp), n, "") for i, arg := range expr.Args[1:] { elem := c.VisitExpr(arg).Convert(elemtyp) indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)} ptr := c.builder.CreateGEP(mem, indices, "") c.builder.CreateStore(elem.LLVMValue(), ptr) } b = llvm.Undef(i8slice) b = c.builder.CreateInsertValue(b, c.builder.CreateBitCast(mem, i8ptr, ""), 0, "") b = c.builder.CreateInsertValue(b, n, 1, "") b = c.builder.CreateInsertValue(b, n, 2, "") } // Call runtime function, then coerce the result. runtimeTyp := c.types.ToRuntime(s.Type()) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, a, b} result := c.builder.CreateCall(sliceappend, args, "") return c.NewValue(c.coerceSlice(result, sliceTyp), s.Type()) }
func (d *GlobalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false), llvm.ConstNull(llvm.Int32Type()), info.MDNode(d.Context), llvm.MDString(d.Name), llvm.MDString(d.DisplayName), llvm.MDNode(nil), info.mdFileNode(d.File), llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false), info.MDNode(d.Type), constInt1(d.Local), constInt1(!d.External), d.Value}) }
func (c *compiler) VisitAppend(expr *ast.CallExpr) Value { // TODO handle ellpisis arg s := c.VisitExpr(expr.Args[0]) elem := c.VisitExpr(expr.Args[1]) sliceappend := c.NamedFunction("runtime.sliceappend", "func f(t uintptr, dst, src slice) slice") i8slice := sliceappend.Type().ElementType().ReturnType() i8ptr := c.types.ToLLVM(&types.Pointer{Base: types.Int8}) // Coerce first argument into an []int8. a_ := s.LLVMValue() sliceTyp := a_.Type() a := c.coerceSlice(a_, i8slice) // Construct a fresh []int8 for the temporary slice. b_ := elem.LLVMValue() one := llvm.ConstInt(llvm.Int32Type(), 1, false) mem := c.builder.CreateAlloca(elem.LLVMValue().Type(), "") c.builder.CreateStore(b_, mem) b := llvm.Undef(i8slice) b = c.builder.CreateInsertValue(b, c.builder.CreateBitCast(mem, i8ptr, ""), 0, "") b = c.builder.CreateInsertValue(b, one, 1, "") b = c.builder.CreateInsertValue(b, one, 2, "") // Call runtime function, then coerce the result. runtimeTyp := c.types.ToRuntime(s.Type()) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, a, b} result := c.builder.CreateCall(sliceappend, args, "") return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), s.Type()) }
func (c *compiler) callCap(arg *LLVMValue) *LLVMValue { var v llvm.Value switch typ := arg.Type().Underlying().(type) { case *types.Array: v = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false) case *types.Pointer: atyp := typ.Elem().Underlying().(*types.Array) v = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false) case *types.Slice: v = c.builder.CreateExtractValue(arg.LLVMValue(), 2, "") case *types.Chan: f := c.runtime.chancap.LLVMValue() v = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "") } return c.NewValue(v, types.Typ[types.Int]) }
// makeSlice allocates a new slice, storing in it the provided elements. func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value { n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false) llvmelttyp := c.types.ToLLVM(elttyp) mem := c.builder.CreateArrayMalloc(llvmelttyp, n, "") 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.Slice{Elt: 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 reorderGlobalConstructors(m llvm.Module) error { ctors := m.NamedGlobal("llvm.global_ctors") if ctors.IsNil() { // No global constructors. return nil } init := ctors.Initializer() arraylength := init.Type().ArrayLength() zeroindex := []uint32{0} // The constructors are ordered within each package, but the packages // are in reverse order. We must go backwards through the constructors, // reassigning priorities. ceiling, npackagectors := -1, -1 for i := arraylength - 1; i >= 0; i-- { indices := []uint32{uint32(i)} ctor := llvm.ConstExtractValue(init, indices) priority := int(llvm.ConstExtractValue(ctor, zeroindex).ZExtValue()) if npackagectors == -1 { ceiling = arraylength - (i + 1) + priority npackagectors = priority } newpriority := ceiling - (npackagectors - priority) newpriorityvalue := llvm.ConstInt(llvm.Int32Type(), uint64(newpriority), false) ctor = llvm.ConstInsertValue(ctor, newpriorityvalue, zeroindex) if priority == 1 { npackagectors = -1 } init = llvm.ConstInsertValue(init, ctor, indices) } ctors.SetInitializer(init) return nil }
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value { n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false) mem := c.builder.CreateArrayMalloc(c.types.ToLLVM(elttyp), n, "") 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.Slice{Elt: elttyp} struct_ := c.builder.CreateAlloca(c.types.ToLLVM(&slicetyp), "") c.builder.CreateStore(mem, c.builder.CreateStructGEP(struct_, 0, "")) c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 1, "")) c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 2, "")) return c.builder.CreateLoad(struct_, "") }
func (c *compiler) slice(x, low, high *LLVMValue) *LLVMValue { if low != nil { low = low.Convert(types.Typ[types.Int]).(*LLVMValue) } else { low = c.NewValue(llvm.ConstNull(c.types.inttype), types.Typ[types.Int]) } if high != nil { high = high.Convert(types.Typ[types.Int]).(*LLVMValue) } else { // all bits set is -1 high = c.NewValue(llvm.ConstAllOnes(c.types.inttype), types.Typ[types.Int]) } switch typ := x.Type().Underlying().(type) { case *types.Pointer: // *array sliceslice := c.runtime.sliceslice.LLVMValue() i8slice := sliceslice.Type().ElementType().ReturnType() sliceValue := llvm.Undef(i8slice) // temporary slice arraytyp := typ.Elem().Underlying().(*types.Array) arrayptr := x.LLVMValue() arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "") arraylen := llvm.ConstInt(c.llvmtypes.inttype, uint64(arraytyp.Len()), false) sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "") sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "") sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "") sliceTyp := types.NewSlice(arraytyp.Elem()) runtimeTyp := c.types.ToRuntime(sliceTyp) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, sliceValue, low.LLVMValue(), high.LLVMValue()} result := c.builder.CreateCall(sliceslice, args, "") llvmSliceTyp := c.types.ToLLVM(sliceTyp) return c.NewValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp) case *types.Slice: sliceslice := c.runtime.sliceslice.LLVMValue() i8slice := sliceslice.Type().ElementType().ReturnType() sliceValue := x.LLVMValue() sliceTyp := sliceValue.Type() sliceValue = c.coerceSlice(sliceValue, i8slice) runtimeTyp := c.types.ToRuntime(x.Type()) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, sliceValue, low.LLVMValue(), high.LLVMValue()} result := c.builder.CreateCall(sliceslice, args, "") return c.NewValue(c.coerceSlice(result, sliceTyp), x.Type()) case *types.Basic: stringslice := c.runtime.stringslice.LLVMValue() llv := x.LLVMValue() args := []llvm.Value{ c.coerceString(llv, stringslice.Type().ElementType().ParamTypes()[0]), low.LLVMValue(), high.LLVMValue(), } result := c.builder.CreateCall(stringslice, args, "") return c.NewValue(c.coerceString(result, llv.Type()), x.Type()) default: panic("unimplemented") } panic("unreachable") }
func (d *CompileUnitDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false), d.Path.path(), llvm.ConstInt(llvm.Int32Type(), uint64(d.Language), false), llvm.MDString(d.Producer), constInt1(d.Optimized), llvm.MDString(d.CompilerFlags), llvm.ConstInt(llvm.Int32Type(), uint64(d.Runtime), false), d.mdNodeList(info, d.EnumTypes), d.mdNodeList(info, d.RetainedTypes), d.mdNodeList(info, d.Subprograms), d.mdNodeList(info, d.GlobalVariables), d.mdNodeList(info, nil), // List of imported entities llvm.MDString(""), // Split debug filename }) }
func (c *compiler) VisitSliceExpr(expr *ast.SliceExpr) Value { // expr.X, expr.Low, expr.High value := c.VisitExpr(expr.X) var low, high llvm.Value if expr.Low != nil { low = c.VisitExpr(expr.Low).Convert(types.Int32).LLVMValue() } else { low = llvm.ConstNull(llvm.Int32Type()) } if expr.High != nil { high = c.VisitExpr(expr.High).Convert(types.Int32).LLVMValue() } else { high = llvm.ConstAllOnes(llvm.Int32Type()) // -1 } if _, ok := types.Underlying(value.Type()).(*types.Pointer); ok { value = value.(*LLVMValue).makePointee() } switch typ := types.Underlying(value.Type()).(type) { case *types.Array: sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice") i8slice := sliceslice.Type().ElementType().ReturnType() sliceValue := llvm.Undef(i8slice) // temporary slice arrayptr := value.(*LLVMValue).pointer.LLVMValue() arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "") arraylen := llvm.ConstInt(llvm.Int32Type(), typ.Len, false) sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "") sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "") sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "") sliceTyp := &types.Slice{Elt: typ.Elt} runtimeTyp := c.types.ToRuntime(sliceTyp) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, sliceValue, low, high} result := c.builder.CreateCall(sliceslice, args, "") llvmSliceTyp := c.types.ToLLVM(sliceTyp) return c.NewLLVMValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp) case *types.Slice: sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice") i8slice := sliceslice.Type().ElementType().ReturnType() sliceValue := value.LLVMValue() sliceTyp := sliceValue.Type() sliceValue = c.coerceSlice(sliceValue, i8slice) runtimeTyp := c.types.ToRuntime(value.Type()) runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "") args := []llvm.Value{runtimeTyp, sliceValue, low, high} result := c.builder.CreateCall(sliceslice, args, "") return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), value.Type()) case *types.Name: // String stringslice := c.NamedFunction("runtime.stringslice", "func f(a string, low, high int32) string") args := []llvm.Value{value.LLVMValue(), low, high} result := c.builder.CreateCall(stringslice, args, "") return c.NewLLVMValue(result, value.Type()) default: panic("unimplemented") } panic("unreachable") }
// 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 (c *compiler) defineMemsetFunction(fn llvm.Value) { entry := llvm.AddBasicBlock(fn, "entry") c.builder.SetInsertPointAtEnd(entry) dst, fill, size := fn.Param(0), fn.Param(1), fn.Param(2) sizeType := size.Type() sizeBits := sizeType.IntTypeWidth() memsetName := "llvm.memset.p0i8.i" + strconv.Itoa(sizeBits) memset := c.NamedFunction(memsetName, "func f(dst *int8, fill byte, size uintptr, align int32, volatile bool)") pint8 := memset.Type().ElementType().ParamTypes()[0] dst = c.builder.CreateIntToPtr(dst, pint8, "") args := []llvm.Value{ dst, fill, size, llvm.ConstInt(llvm.Int32Type(), 1, false), // single byte alignment llvm.ConstInt(llvm.Int1Type(), 0, false), // not volatile } c.builder.CreateCall(memset, args, "") c.builder.CreateRetVoid() }
func (d FileDescriptor) mdNode(info *DebugInfo) llvm.Value { if d == "" { return llvm.Value{} } return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false), d.path(), }) }
// globalStringPtr returns a *string with the specified value. func (tm *TypeMap) globalStringPtr(value string) llvm.Value { strval := llvm.ConstString(value, false) strglobal := llvm.AddGlobal(tm.module, strval.Type(), "") strglobal.SetInitializer(strval) strglobal = llvm.ConstBitCast(strglobal, llvm.PointerType(llvm.Int8Type(), 0)) strlen := llvm.ConstInt(tm.inttype, uint64(len(value)), false) str := llvm.ConstStruct([]llvm.Value{strglobal, strlen}, false) g := llvm.AddGlobal(tm.module, str.Type(), "") g.SetInitializer(str) return g }
func (tm *TypeMap) arrayRuntimeType(a *types.Array) (global, ptr llvm.Value) { commonType := tm.makeCommonType(a, reflect.Array) elemRuntimeType := tm.ToRuntime(a.Elt) sliceRuntimeType := tm.ToRuntime(&types.Slice{Elt: a.Elt}) uintptrlen := llvm.ConstInt(tm.target.IntPtrType(), uint64(a.Len), false) arrayType := llvm.ConstNull(tm.runtimeArrayType) arrayType = llvm.ConstInsertValue(arrayType, commonType, []uint32{0}) arrayType = llvm.ConstInsertValue(arrayType, elemRuntimeType, []uint32{1}) arrayType = llvm.ConstInsertValue(arrayType, sliceRuntimeType, []uint32{2}) arrayType = llvm.ConstInsertValue(arrayType, uintptrlen, []uint32{3}) return tm.makeRuntimeTypeGlobal(arrayType) }
func (tm *TypeMap) arrayRuntimeType(a *types.Array) (global, ptr llvm.Value) { rtype := tm.makeRtype(a, reflect.Array) elemRuntimeType := tm.ToRuntime(a.Elem()) sliceRuntimeType := tm.ToRuntime(types.NewSlice(a.Elem())) uintptrlen := llvm.ConstInt(tm.target.IntPtrType(), uint64(a.Len()), false) arrayType := llvm.ConstNull(tm.runtime.arrayType.llvm) arrayType = llvm.ConstInsertValue(arrayType, rtype, []uint32{0}) arrayType = llvm.ConstInsertValue(arrayType, elemRuntimeType, []uint32{1}) arrayType = llvm.ConstInsertValue(arrayType, sliceRuntimeType, []uint32{2}) arrayType = llvm.ConstInsertValue(arrayType, uintptrlen, []uint32{3}) return tm.makeRuntimeTypeGlobal(arrayType, typeString(a)) }
func (c *compiler) VisitCap(expr *ast.CallExpr) Value { value := c.VisitExpr(expr.Args[0]) typ := value.Type() if name, ok := typ.Underlying().(*types.Named); ok { typ = name.Underlying() } var capvalue llvm.Value switch typ := typ.Underlying().(type) { case *types.Pointer: atyp := typ.Elem().Underlying().(*types.Array) capvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false) case *types.Array: capvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false) case *types.Slice: sliceval := value.LLVMValue() capvalue = c.builder.CreateExtractValue(sliceval, 2, "") case *types.Chan: panic("cap(chan) unimplemented") } return c.NewValue(capvalue, types.Typ[types.Int]) }
func (c *compiler) visitRecover() *LLVMValue { // Functions that call recover must not be inlined, or we // can't tell whether the recover call is valid. fn := c.functions.top() fnptr := c.builder.CreateExtractValue(fn.value, 0, "") fnptr.AddFunctionAttr(llvm.NoInlineAttribute) // We need to tell runtime.recover if it's being called from // an indirectly invoked deferred function or not. var indirect llvm.Value sig := fn.Type().(*types.Signature) if sig.Params().Len() == 0 { indirect = llvm.ConstInt(llvm.Int32Type(), 0, false) } else { indirect = llvm.ConstInt(llvm.Int32Type(), 1, false) } eface := &types.Interface{} err := c.builder.CreateAlloca(c.types.ToLLVM(eface), "") r := c.NamedFunction("runtime.recover", "func f(int32, *interface{})") c.builder.CreateCall(r, []llvm.Value{indirect, err}, "") return c.NewValue(c.builder.CreateLoad(err, ""), eface) }
func (c *compiler) callLen(arg *LLVMValue) *LLVMValue { var lenvalue llvm.Value switch typ := arg.Type().Underlying().(type) { case *types.Array: lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false) case *types.Pointer: atyp := typ.Elem().Underlying().(*types.Array) lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false) case *types.Slice: lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "") case *types.Map: f := c.runtime.maplen.LLVMValue() lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "") case *types.Basic: if isString(typ) { lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "") } case *types.Chan: f := c.runtime.chanlen.LLVMValue() lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "") } return c.NewValue(lenvalue, types.Typ[types.Int]) }
func (d *BasicTypeDescriptor) mdNode(info *DebugInfo) llvm.Value { return llvm.MDNode([]llvm.Value{ llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false), FileDescriptor(d.File).path(), info.MDNode(d.Context), llvm.MDString(d.Name), llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false), llvm.ConstInt(llvm.Int64Type(), d.Size, false), llvm.ConstInt(llvm.Int64Type(), d.Alignment, false), llvm.ConstInt(llvm.Int64Type(), d.Offset, false), llvm.ConstInt(llvm.Int32Type(), uint64(d.Flags), false), llvm.ConstInt(llvm.Int32Type(), uint64(d.TypeEncoding), false)}) }
func (tm *TypeMap) funcRuntimeType(f *types.Signature) (global, ptr llvm.Value) { rtype := tm.makeRtype(f, reflect.Func) funcType := llvm.ConstNull(tm.runtimeFuncType) funcType = llvm.ConstInsertValue(funcType, rtype, []uint32{0}) // dotdotdot if f.IsVariadic() { variadic := llvm.ConstInt(llvm.Int1Type(), 1, false) funcType = llvm.ConstInsertValue(funcType, variadic, []uint32{1}) } // TODO in //funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{2}) // TODO out //funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{3}) return tm.makeRuntimeTypeGlobal(funcType) }
func (tm *TypeMap) makeRtype(t types.Type, k reflect.Kind) llvm.Value { // Not sure if there's an easier way to do this, but if you just // use ConstStruct, you end up getting a different llvm.Type. typ := llvm.ConstNull(tm.runtime.rtype.llvm) elementTypes := tm.runtime.rtype.llvm.StructElementTypes() // Size. size := llvm.ConstInt(elementTypes[0], uint64(tm.Sizeof(t)), false) typ = llvm.ConstInsertValue(typ, size, []uint32{0}) // TODO hash // TODO padding // Alignment. align := llvm.ConstInt(llvm.Int8Type(), uint64(tm.Alignof(t)), false) typ = llvm.ConstInsertValue(typ, align, []uint32{3}) // var typ = llvm.ConstInsertValue(typ, align, []uint32{4}) // field // Kind. kind := llvm.ConstInt(llvm.Int8Type(), uint64(k), false) typ = llvm.ConstInsertValue(typ, kind, []uint32{5}) // Algorithm table. alg := tm.makeAlgorithmTable(t) algptr := llvm.AddGlobal(tm.module, alg.Type(), "") algptr.SetInitializer(alg) algptr = llvm.ConstBitCast(algptr, elementTypes[6]) typ = llvm.ConstInsertValue(typ, algptr, []uint32{6}) // String representation. stringrep := tm.globalStringPtr(t.String()) typ = llvm.ConstInsertValue(typ, stringrep, []uint32{8}) // TODO gc return typ }