func (tm *TypeMap) interfaceRuntimeType(tstr string, i *types.Interface) (global, ptr llvm.Value) { rtype := tm.makeRtype(i, reflect.Interface) interfaceType := llvm.ConstNull(tm.runtimeInterfaceType) global, ptr = tm.makeRuntimeTypeGlobal(interfaceType) tm.types.record(tstr, global, ptr) interfaceType = llvm.ConstInsertValue(interfaceType, rtype, []uint32{0}) methodset := i.MethodSet() imethods := make([]llvm.Value, methodset.Len()) for index := 0; index < methodset.Len(); index++ { method := methodset.At(index).Obj() imethod := llvm.ConstNull(tm.runtimeImethod) name := tm.globalStringPtr(method.Name()) name = llvm.ConstBitCast(name, tm.runtimeImethod.StructElementTypes()[0]) //pkgpath := tm.globalStringPtr(tm.functions.objectdata[method].Package.Path()) //pkgpath = llvm.ConstBitCast(name, tm.runtimeImethod.StructElementTypes()[1]) mtyp := tm.ToRuntime(method.Type()) imethod = llvm.ConstInsertValue(imethod, name, []uint32{0}) //imethod = llvm.ConstInsertValue(imethod, pkgpath, []uint32{1}) imethod = llvm.ConstInsertValue(imethod, mtyp, []uint32{2}) imethods[index] = imethod } imethodsSliceType := tm.runtimeInterfaceType.StructElementTypes()[1] imethodsSlice := tm.makeSlice(imethods, imethodsSliceType) interfaceType = llvm.ConstInsertValue(interfaceType, imethodsSlice, []uint32{1}) global.SetInitializer(interfaceType) return global, ptr }
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 (tm *TypeMap) interfaceRuntimeType(i *types.Interface) (global, ptr llvm.Value) { rtype := tm.makeRtype(i, reflect.Interface) interfaceType := llvm.ConstNull(tm.runtime.interfaceType.llvm) global, ptr = tm.makeRuntimeTypeGlobal(interfaceType, typeString(i)) tm.types.Set(i, runtimeTypeInfo{global, ptr}) interfaceType = llvm.ConstInsertValue(interfaceType, rtype, []uint32{0}) methodset := tm.MethodSet(i) imethods := make([]llvm.Value, methodset.Len()) for index := 0; index < methodset.Len(); index++ { method := methodset.At(index).Obj() imethod := llvm.ConstNull(tm.runtime.imethod.llvm) name := tm.globalStringPtr(method.Name()) name = llvm.ConstBitCast(name, tm.runtime.imethod.llvm.StructElementTypes()[0]) mtyp := tm.ToRuntime(method.Type()) imethod = llvm.ConstInsertValue(imethod, name, []uint32{0}) if !ast.IsExported(method.Name()) { pkgpath := tm.globalStringPtr(method.Pkg().Path()) pkgpath = llvm.ConstBitCast(pkgpath, tm.runtime.imethod.llvm.StructElementTypes()[1]) imethod = llvm.ConstInsertValue(imethod, pkgpath, []uint32{1}) } imethod = llvm.ConstInsertValue(imethod, mtyp, []uint32{2}) imethods[index] = imethod } imethodsSliceType := tm.runtime.interfaceType.llvm.StructElementTypes()[1] imethodsSlice := tm.makeSlice(imethods, imethodsSliceType) interfaceType = llvm.ConstInsertValue(interfaceType, imethodsSlice, []uint32{1}) global.SetInitializer(interfaceType) return global, ptr }
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) { commonType := tm.makeCommonType(p, reflect.Map) ptrType := llvm.ConstNull(tm.runtimePtrType) ptrType = llvm.ConstInsertValue(ptrType, commonType, []uint32{0}) ptrType = llvm.ConstInsertValue(ptrType, tm.ToRuntime(p.Base), []uint32{1}) return tm.makeRuntimeTypeGlobal(ptrType) }
func (tm *TypeMap) nameRuntimeType(n *types.Name) (global, ptr llvm.Value) { global, ptr = tm.makeRuntimeType(n.Underlying) globalInit := global.Initializer() // Locate the common type. underlyingRuntimeType := llvm.ConstExtractValue(globalInit, []uint32{1}) commonType := underlyingRuntimeType if _, ok := n.Underlying.(*types.Basic); !ok { commonType = llvm.ConstExtractValue(commonType, []uint32{0}) } // Insert the uncommon type. uncommonTypeInit := llvm.ConstNull(tm.runtimeUncommonType) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) commonType = llvm.ConstInsertValue(commonType, uncommonType, []uint32{8}) // Update the global's initialiser. if _, ok := n.Underlying.(*types.Basic); !ok { underlyingRuntimeType = llvm.ConstInsertValue(underlyingRuntimeType, commonType, []uint32{0}) } else { underlyingRuntimeType = commonType } globalInit = llvm.ConstInsertValue(globalInit, underlyingRuntimeType, []uint32{1}) global.SetName("__llgo.reflect." + n.Obj.Name) return global, ptr }
func (tm *TypeMap) nameRuntimeType(n *types.Named) (global, ptr llvm.Value) { name := typeString(n) path := "runtime" if pkg := n.Obj().Pkg(); pkg != nil { path = pkg.Path() } if path != tm.pkgpath { // We're not compiling the package from whence the type came, // so we'll just create a pointer to it here. global := llvm.AddGlobal(tm.module, tm.runtime.rtype.llvm, typeSymbol(name)) global.SetInitializer(llvm.ConstNull(tm.runtime.rtype.llvm)) global.SetLinkage(llvm.CommonLinkage) return global, global } // If the underlying type is Basic, then we always create // a new global. Otherwise, we clone the value returned // from toRuntime in case it is cached and reused. underlying := n.Underlying() if basic, ok := underlying.(*types.Basic); ok { global, ptr = tm.basicRuntimeType(basic, true) global.SetName(typeSymbol(name)) } else { global, ptr = tm.toRuntime(underlying) clone := llvm.AddGlobal(tm.module, global.Type().ElementType(), typeSymbol(name)) clone.SetInitializer(global.Initializer()) global = clone ptr = llvm.ConstBitCast(global, llvm.PointerType(tm.runtime.rtype.llvm, 0)) } global.SetLinkage(llvm.ExternalLinkage) // Locate the rtype. underlyingRuntimeType := global.Initializer() rtype := underlyingRuntimeType if rtype.Type() != tm.runtime.rtype.llvm { rtype = llvm.ConstExtractValue(rtype, []uint32{0}) } // Insert the uncommon type. uncommonTypeInit := tm.uncommonType(n, nil) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9}) // Replace the rtype's string representation with the one from // uncommonType. XXX should we have the package name prepended? Probably. namePtr := llvm.ConstExtractValue(uncommonTypeInit, []uint32{0}) rtype = llvm.ConstInsertValue(rtype, namePtr, []uint32{8}) // Update the global's initialiser. Note that we take a copy // of the underlying type; we're not updating a shared type. if underlyingRuntimeType.Type() != tm.runtime.rtype.llvm { underlyingRuntimeType = llvm.ConstInsertValue(underlyingRuntimeType, rtype, []uint32{0}) } else { underlyingRuntimeType = rtype } global.SetInitializer(underlyingRuntimeType) return global, ptr }
func (tm *TypeMap) mapRuntimeType(m *types.Map) (global, ptr llvm.Value) { rtype := tm.makeRtype(m, reflect.Map) mapType := llvm.ConstNull(tm.runtime.mapType.llvm) mapType = llvm.ConstInsertValue(mapType, rtype, []uint32{0}) mapType = llvm.ConstInsertValue(mapType, tm.ToRuntime(m.Key()), []uint32{1}) mapType = llvm.ConstInsertValue(mapType, tm.ToRuntime(m.Elem()), []uint32{2}) return tm.makeRuntimeTypeGlobal(mapType, typeString(m)) }
func (tm *TypeMap) mapRuntimeType(m *types.Map) (global, ptr llvm.Value) { commonType := tm.makeCommonType(m, reflect.Map) mapType := llvm.ConstNull(tm.runtimeMapType) mapType = llvm.ConstInsertValue(mapType, commonType, []uint32{0}) mapType = llvm.ConstInsertValue(mapType, tm.ToRuntime(m.Key), []uint32{1}) mapType = llvm.ConstInsertValue(mapType, tm.ToRuntime(m.Elt), []uint32{2}) return tm.makeRuntimeTypeGlobal(mapType) }
func (tm *TypeMap) sliceRuntimeType(s *types.Slice) (global, ptr llvm.Value) { commonType := tm.makeCommonType(s, reflect.Slice) elemRuntimeType := tm.ToRuntime(s.Elt) sliceType := llvm.ConstNull(tm.runtimeSliceType) sliceType = llvm.ConstInsertValue(sliceType, commonType, []uint32{0}) sliceType = llvm.ConstInsertValue(sliceType, elemRuntimeType, []uint32{1}) return tm.makeRuntimeTypeGlobal(sliceType) }
func (tm *TypeMap) sliceRuntimeType(tstr string, s *types.Slice) (global, ptr llvm.Value) { rtype := tm.makeRtype(s, reflect.Slice) sliceType := llvm.ConstNull(tm.runtimeSliceType) global, ptr = tm.makeRuntimeTypeGlobal(sliceType) sliceType = llvm.ConstInsertValue(sliceType, rtype, []uint32{0}) elemRuntimeType := tm.ToRuntime(s.Elem()) sliceType = llvm.ConstInsertValue(sliceType, elemRuntimeType, []uint32{1}) global.SetInitializer(sliceType) return global, ptr }
func (tm *TypeMap) uncommonType(n *types.Named, ptr bool) llvm.Value { uncommonTypeInit := llvm.ConstNull(tm.runtimeUncommonType) namePtr := tm.globalStringPtr(n.Obj().Name()) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, namePtr, []uint32{0}) _, path := tm.qualifiedName(n) pkgpathPtr := tm.globalStringPtr(path) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, pkgpathPtr, []uint32{1}) methodset := tm.functions.methods(n) methodfuncs := methodset.nonptr if ptr { methodfuncs = methodset.ptr } // Store methods. methods := make([]llvm.Value, len(methodfuncs)) for i, mfunc := range methodfuncs { ftyp := mfunc.Type().(*types.Signature) method := llvm.ConstNull(tm.runtimeMethod) name := tm.globalStringPtr(mfunc.Name()) name = llvm.ConstBitCast(name, tm.runtimeMethod.StructElementTypes()[0]) // name method = llvm.ConstInsertValue(method, name, []uint32{0}) // pkgPath method = llvm.ConstInsertValue(method, pkgpathPtr, []uint32{1}) // mtyp (method type, no receiver) { ftyp := types.NewSignature(nil, nil, ftyp.Params(), ftyp.Results(), ftyp.IsVariadic()) mtyp := tm.ToRuntime(ftyp) method = llvm.ConstInsertValue(method, mtyp, []uint32{2}) } // typ (function type, with receiver) typ := tm.ToRuntime(ftyp) method = llvm.ConstInsertValue(method, typ, []uint32{3}) // tfn (standard method/function pointer for plain method calls) tfn := tm.resolver.Resolve(tm.functions.objectdata[mfunc].Ident).LLVMValue() tfn = llvm.ConstExtractValue(tfn, []uint32{0}) tfn = llvm.ConstPtrToInt(tfn, tm.target.IntPtrType()) // ifn (single-word receiver function pointer for interface calls) ifn := tfn if !ptr && tm.Sizeof(ftyp.Recv().Type()) > int64(tm.target.PointerSize()) { mfunc := methodset.lookup(mfunc.Name(), true) ifn = tm.resolver.Resolve(tm.functions.objectdata[mfunc].Ident).LLVMValue() ifn = llvm.ConstExtractValue(ifn, []uint32{0}) ifn = llvm.ConstPtrToInt(ifn, tm.target.IntPtrType()) } method = llvm.ConstInsertValue(method, ifn, []uint32{4}) method = llvm.ConstInsertValue(method, tfn, []uint32{5}) methods[i] = method } methodsSliceType := tm.runtimeUncommonType.StructElementTypes()[2] methodsSlice := tm.makeSlice(methods, methodsSliceType) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, methodsSlice, []uint32{2}) return uncommonTypeInit }
func (tm *TypeMap) nameRuntimeType(n *types.Named) (global, ptr llvm.Value) { var path string if data, ok := tm.functions.objectdata[n.Obj()]; ok { path = pkgpath(data.Package) } if path == "" { // Set to "runtime", so the builtin types have a home. path = "runtime" } globalname := "__llgo.type." + path + "." + n.Obj().Name() if path != tm.pkgpath { // We're not compiling the package from whence the type came, // so we'll just create a pointer to it here. global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname) global.SetInitializer(llvm.ConstNull(tm.runtimeType)) global.SetLinkage(llvm.CommonLinkage) return global, global } underlying := n.Underlying() if name, ok := underlying.(*types.Named); ok { underlying = name.Underlying() } global, ptr = tm.toRuntime(underlying) // Locate the rtype. underlyingRuntimeType := global.Initializer() rtype := underlyingRuntimeType if rtype.Type() != tm.runtimeType { rtype = llvm.ConstExtractValue(rtype, []uint32{0}) } // Insert the uncommon type. uncommonTypeInit := tm.uncommonType(n, false) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9}) // Replace the rtype's string representation with the one from // uncommonType. XXX should we have the package name prepended? Probably. namePtr := llvm.ConstExtractValue(uncommonTypeInit, []uint32{0}) rtype = llvm.ConstInsertValue(rtype, namePtr, []uint32{8}) // Update the global's initialiser. Note that we take a copy // of the underlying type; we're not updating a shared type. if underlyingRuntimeType.Type() != tm.runtimeType { underlyingRuntimeType = llvm.ConstInsertValue(underlyingRuntimeType, rtype, []uint32{0}) } else { underlyingRuntimeType = rtype } global.SetName(globalname) global.SetInitializer(underlyingRuntimeType) return global, ptr }
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 (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) mapRuntimeType(m *types.Map) llvm.Value { result := llvm.AddGlobal(tm.module, tm.runtimeMapType, "") elementTypes := tm.runtimeCommonType.StructElementTypes() ptr := llvm.ConstBitCast(result, elementTypes[9]) commonType := tm.makeCommonType(m, reflect.Map) commonType = llvm.ConstInsertValue(commonType, ptr, []uint32{9}) init := llvm.ConstNull(tm.runtimeMapType) init = llvm.ConstInsertValue(init, commonType, []uint32{0}) result.SetInitializer(init) // TODO set key, elem return result }
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) structRuntimeType(s *types.Struct) llvm.Value { result := llvm.AddGlobal(tm.module, tm.runtimeStructType, "") elementTypes := tm.runtimeCommonType.StructElementTypes() ptr := llvm.ConstBitCast(result, elementTypes[9]) commonType := tm.makeCommonType(s, reflect.Struct) commonType = llvm.ConstInsertValue(commonType, ptr, []uint32{9}) init := llvm.ConstNull(tm.runtimeStructType) init = llvm.ConstInsertValue(init, commonType, []uint32{0}) result.SetInitializer(init) // TODO set fields //panic("unimplemented") return result }
func (tm *TypeMap) mapRuntimeType(m *types.Map) (global, ptr llvm.Value) { commonType := tm.makeCommonType(m, reflect.Map) mapType := llvm.ConstNull(tm.runtimeMapType) mapType = llvm.ConstInsertValue(mapType, commonType, []uint32{0}) // TODO set key, elem return tm.makeRuntimeTypeGlobal(mapType) }
func (tm *TypeMap) structRuntimeType(s *types.Struct) (global, ptr llvm.Value) { commonType := tm.makeCommonType(s, reflect.Struct) structType := llvm.ConstNull(tm.runtimeStructType) structType = llvm.ConstInsertValue(structType, commonType, []uint32{0}) // TODO set fields return tm.makeRuntimeTypeGlobal(structType) }
func (tm *TypeMap) structRuntimeType(tstr string, s *types.Struct) (global, ptr llvm.Value) { rtype := tm.makeRtype(s, reflect.Struct) structType := llvm.ConstNull(tm.runtimeStructType) structType = llvm.ConstInsertValue(structType, rtype, []uint32{0}) global, ptr = tm.makeRuntimeTypeGlobal(structType) // TODO set fields, reset initialiser return }
func (tm *TypeMap) interfaceRuntimeType(i *types.Interface) (global, ptr llvm.Value) { commonType := tm.makeCommonType(i, reflect.Interface) interfaceType := llvm.ConstNull(tm.runtimeInterfaceType) interfaceType = llvm.ConstInsertValue(interfaceType, commonType, []uint32{0}) // TODO set methods //interfaceType = llvm.ConstInsertValue(interfaceType, methods, []uint32{1}) return tm.makeRuntimeTypeGlobal(interfaceType) }
func (tm *TypeMap) nameRuntimeType(n *types.Name) llvm.Value { underlyingRuntimeType := tm.ToRuntime(n.Underlying).Initializer() result := llvm.AddGlobal(tm.module, underlyingRuntimeType.Type(), "") result.SetName("__llgo.reflect." + n.Obj.Name) elementTypes := tm.runtimeCommonType.StructElementTypes() ptr := llvm.ConstBitCast(result, elementTypes[9]) commonType := llvm.ConstInsertValue(underlyingRuntimeType, ptr, []uint32{9}) uncommonTypeInit := llvm.ConstNull(tm.runtimeUncommonType) // TODO uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) commonType = llvm.ConstInsertValue(commonType, uncommonType, []uint32{8}) // TODO set string, uncommonType. result.SetInitializer(commonType) return result }
func (tm *TypeMap) chanRuntimeType(c *types.Chan) (global, ptr llvm.Value) { rtype := tm.makeRtype(c, reflect.Chan) chanType := llvm.ConstNull(tm.runtimeChanType) chanType = llvm.ConstInsertValue(chanType, rtype, []uint32{0}) chanType = llvm.ConstInsertValue(chanType, tm.ToRuntime(c.Elem()), []uint32{1}) // go/ast and reflect disagree on values for direction. var dir reflect.ChanDir if c.Dir()&ast.SEND != 0 { dir = reflect.SendDir } if c.Dir()&ast.RECV != 0 { dir |= reflect.RecvDir } uintptrdir := llvm.ConstInt(tm.target.IntPtrType(), uint64(dir), false) chanType = llvm.ConstInsertValue(chanType, uintptrdir, []uint32{2}) return tm.makeRuntimeTypeGlobal(chanType) }
func (tm *TypeMap) makeSlice(values []llvm.Value, slicetyp llvm.Type) llvm.Value { ptrtyp := slicetyp.StructElementTypes()[0] var globalptr llvm.Value if len(values) > 0 { array := llvm.ConstArray(ptrtyp.ElementType(), values) globalptr = llvm.AddGlobal(tm.module, array.Type(), "") globalptr.SetInitializer(array) globalptr = llvm.ConstBitCast(globalptr, ptrtyp) } else { globalptr = llvm.ConstNull(ptrtyp) } len_ := llvm.ConstInt(tm.inttype, uint64(len(values)), false) slice := llvm.ConstNull(slicetyp) slice = llvm.ConstInsertValue(slice, globalptr, []uint32{0}) slice = llvm.ConstInsertValue(slice, len_, []uint32{1}) slice = llvm.ConstInsertValue(slice, len_, []uint32{2}) return slice }
func (tm *TypeMap) basicRuntimeType(b *types.Basic) llvm.Value { commonType := tm.makeCommonType(b, reflect.Kind(b.Kind)) result := llvm.AddGlobal(tm.module, commonType.Type(), "") elementTypes := tm.runtimeCommonType.StructElementTypes() ptr := llvm.ConstBitCast(result, elementTypes[9]) commonType = llvm.ConstInsertValue(commonType, ptr, []uint32{9}) result.SetInitializer(commonType) return result }
func (tm *TypeMap) funcRuntimeType(f *types.Signature) (global, ptr llvm.Value) { rtype := tm.makeRtype(f, reflect.Func) funcType := llvm.ConstNull(tm.runtime.funcType.llvm) global, ptr = tm.makeRuntimeTypeGlobal(funcType, typeString(f)) tm.types.Set(f, runtimeTypeInfo{global, ptr}) funcType = llvm.ConstInsertValue(funcType, rtype, []uint32{0}) // dotdotdot if f.Variadic() { variadic := llvm.ConstInt(llvm.Int1Type(), 1, false) funcType = llvm.ConstInsertValue(funcType, variadic, []uint32{1}) } // in intypes := tm.rtypeSlice(f.Params()) funcType = llvm.ConstInsertValue(funcType, intypes, []uint32{2}) // out outtypes := tm.rtypeSlice(f.Results()) funcType = llvm.ConstInsertValue(funcType, outtypes, []uint32{3}) global.SetInitializer(funcType) return global, ptr }
func (c *compiler) makeFunc(ident *ast.Ident, ftyp *types.Signature) *LLVMValue { fname := ident.String() if ftyp.Recv() == nil && fname == "init" { // Make "init" functions anonymous. fname = "" } else { var pkgname string if recv := ftyp.Recv(); recv != nil { var recvname string switch recvtyp := recv.Type().(type) { case *types.Pointer: if named, ok := recvtyp.Elem().(*types.Named); ok { obj := named.Obj() recvname = "*" + obj.Name() pkgname = obj.Pkg().Path() } case *types.Named: named := recvtyp obj := named.Obj() recvname = obj.Name() pkgname = obj.Pkg().Path() } if recvname != "" { fname = fmt.Sprintf("%s.%s", recvname, fname) } else { // If the receiver is an unnamed struct, we're // synthesising a method for an unnamed struct // type. There's no meaningful name to give the // function, so leave it up to LLVM. fname = "" } } else { obj := c.typeinfo.Objects[ident] pkgname = obj.Pkg().Path() } if fname != "" { fname = pkgname + "." + fname } } // gcimporter may produce multiple AST objects for the same function. llvmftyp := c.types.ToLLVM(ftyp) var fn llvm.Value if fname != "" { fn = c.module.Module.NamedFunction(fname) } if fn.IsNil() { llvmfptrtyp := llvmftyp.StructElementTypes()[0].ElementType() fn = llvm.AddFunction(c.module.Module, fname, llvmfptrtyp) } fn = llvm.ConstInsertValue(llvm.ConstNull(llvmftyp), fn, []uint32{0}) return c.NewValue(fn, ftyp) }
func (tm *TypeMap) chanRuntimeType(c *types.Chan) (global, ptr llvm.Value) { rtype := tm.makeRtype(c, reflect.Chan) chanType := llvm.ConstNull(tm.runtime.chanType.llvm) chanType = llvm.ConstInsertValue(chanType, rtype, []uint32{0}) chanType = llvm.ConstInsertValue(chanType, tm.ToRuntime(c.Elem()), []uint32{1}) // go/ast and reflect disagree on values for direction. var dir reflect.ChanDir switch c.Dir() { case types.SendOnly: dir = reflect.SendDir case types.RecvOnly: dir = reflect.RecvDir case types.SendRecv: dir = reflect.SendDir | reflect.RecvDir } uintptrdir := llvm.ConstInt(tm.target.IntPtrType(), uint64(dir), false) chanType = llvm.ConstInsertValue(chanType, uintptrdir, []uint32{2}) return tm.makeRuntimeTypeGlobal(chanType, typeString(c)) }
func (tm *TypeMap) makeRuntimeTypeGlobal(v llvm.Value) (global, ptr llvm.Value) { runtimeTypeValue := llvm.ConstNull(tm.runtimeType) initType := llvm.StructType([]llvm.Type{tm.runtimeType, v.Type()}, false) global = llvm.AddGlobal(tm.module, initType, "") ptr = llvm.ConstBitCast(global, llvm.PointerType(tm.runtimeType, 0)) // Set ptrToThis in v's commonType. if v.Type() == tm.runtimeCommonType { v = llvm.ConstInsertValue(v, ptr, []uint32{9}) } else { commonType := llvm.ConstExtractValue(v, []uint32{0}) commonType = llvm.ConstInsertValue(commonType, ptr, []uint32{9}) v = llvm.ConstInsertValue(v, commonType, []uint32{0}) } init := llvm.Undef(initType) //runtimeTypeValue = llvm.ConstInsertValue() TODO init = llvm.ConstInsertValue(init, runtimeTypeValue, []uint32{0}) init = llvm.ConstInsertValue(init, v, []uint32{1}) global.SetInitializer(init) return }
func (tm *TypeMap) makeCommonType(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. lt := tm.ToLLVM(t) typ := llvm.ConstNull(tm.runtimeCommonType) elementTypes := tm.runtimeCommonType.StructElementTypes() // Size. size := llvm.SizeOf(lt) if size.Type().IntTypeWidth() > elementTypes[0].IntTypeWidth() { size = llvm.ConstTrunc(size, elementTypes[0]) } typ = llvm.ConstInsertValue(typ, size, []uint32{0}) // TODO hash // TODO padding // Alignment. align := llvm.ConstTrunc(llvm.AlignOf(lt), llvm.Int8Type()) 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}) // TODO string return typ }