func (tm *LLVMTypeMap) pointerLLVMType(p *types.Pointer) llvm.Type { if p.Elem().Underlying() == p { // Recursive pointers must be handled specially, as // LLVM does not permit recursive types except via // named structs. if tm.ptrstandin.IsNil() { ctx := llvm.GlobalContext() unique := ctx.StructCreateNamed("") tm.ptrstandin = llvm.PointerType(unique, 0) } return llvm.PointerType(tm.ptrstandin, 0) } return llvm.PointerType(tm.ToLLVM(p.Elem()), 0) }
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) { // Is the base type a named type from another package? If so, we'll // create a reference to the externally defined symbol. linkage := llvm.LinkOnceAnyLinkage switch elem := p.Elem().(type) { case *types.Basic: if tm.pkgpath != "runtime" { global := llvm.AddGlobal(tm.module, tm.runtime.rtype.llvm, typeSymbol(typeString(p))) global.SetInitializer(llvm.ConstNull(tm.runtime.rtype.llvm)) global.SetLinkage(llvm.CommonLinkage) return global, global } linkage = llvm.ExternalLinkage case *types.Named: path := "runtime" if pkg := elem.Obj().Pkg(); pkg != nil { path = pkg.Path() } if path != tm.pkgpath { global := llvm.AddGlobal(tm.module, tm.runtime.rtype.llvm, typeSymbol(typeString(p))) global.SetInitializer(llvm.ConstNull(tm.runtime.rtype.llvm)) global.SetLinkage(llvm.CommonLinkage) return global, global } linkage = llvm.ExternalLinkage } rtype := tm.makeRtype(p, reflect.Ptr) if n, ok := p.Elem().(*types.Named); ok { uncommonTypeInit := tm.uncommonType(n, p) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9}) } ptrType := llvm.ConstNull(tm.runtime.ptrType.llvm) var baseTypeGlobal llvm.Value if p.Elem().Underlying() == p { // Recursive pointer. ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType, typeString(p)) baseTypeGlobal = global // Update the global with its own pointer in the elem field. ptrType = global.Initializer() ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1}) global.SetInitializer(ptrType) } else { var baseTypePtr llvm.Value baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem()) ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType, typeString(p)) } global.SetLinkage(linkage) // Set ptrToThis in the base type's rtype. baseType := baseTypeGlobal.Initializer() if !baseType.IsNull() { if baseType.Type() == tm.runtime.rtype.llvm { baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10}) } else { rtype := llvm.ConstExtractValue(baseType, []uint32{0}) rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10}) baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0}) } baseTypeGlobal.SetInitializer(baseType) } return global, ptr }
func (tm *llvmTypeMap) pointerLLVMType(p *types.Pointer) llvm.Type { return llvm.PointerType(tm.ToLLVM(p.Elem()), 0) }
func (m *TypeMap) descriptorPointer(t *types.Pointer) TypeDebugDescriptor { return NewPointerDerivedType(m.TypeDebugDescriptor(t.Elem())) }
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) { // Is the base type a named type from another package? If so, we'll // create a reference to the externally defined symbol. var globalname string if n, ok := p.Elem().(*types.Named); ok { // FIXME horrible circular relationship var path string if data, ok := tm.functions.objectdata[n.Obj()]; ok { path = pkgpath(data.Package) } if path == "" { path = "runtime" } globalname = "__llgo.type.*" + path + "." + n.Obj().Name() if path != tm.pkgpath { global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname) global.SetInitializer(llvm.ConstNull(tm.runtimeType)) global.SetLinkage(llvm.CommonLinkage) return global, global } } rtype := tm.makeRtype(p, reflect.Ptr) if n, ok := p.Elem().(*types.Named); ok { uncommonTypeInit := tm.uncommonType(n, true) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9}) } ptrType := llvm.ConstNull(tm.runtimePtrType) var baseTypeGlobal llvm.Value if p.Elem().Underlying() == p { // Recursive pointer. ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType) baseTypeGlobal = global // Update the global with its own pointer in the elem field. ptrType = global.Initializer() ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1}) global.SetInitializer(ptrType) } else { var baseTypePtr llvm.Value baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem()) ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType) } global.SetName(globalname) // Set ptrToThis in the base type's rtype. baseType := baseTypeGlobal.Initializer() if baseType.Type() == tm.runtimeType { baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10}) } else { rtype := llvm.ConstExtractValue(baseType, []uint32{0}) rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10}) baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0}) } baseTypeGlobal.SetInitializer(baseType) return global, ptr }
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) { // Is the base type a named type from another package? If so, we'll // create a reference to the externally defined symbol. var globalname string switch elem := p.Elem().(type) { case *types.Basic: globalname = "__llgo.type.*runtime." + tm.TypeString(elem) if tm.pkgpath != "runtime" { global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname) global.SetInitializer(llvm.ConstNull(tm.runtimeType)) global.SetLinkage(llvm.CommonLinkage) return global, global } case *types.Named: qname, path := tm.qualifiedName(elem) globalname = "__llgo.type.*" + qname if path != tm.pkgpath { global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname) global.SetInitializer(llvm.ConstNull(tm.runtimeType)) global.SetLinkage(llvm.CommonLinkage) return global, global } else if !isGlobalObject(elem.Obj()) { globalname = "" } } rtype := tm.makeRtype(p, reflect.Ptr) if n, ok := p.Elem().(*types.Named); ok { uncommonTypeInit := tm.uncommonType(n, true) uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "") uncommonType.SetInitializer(uncommonTypeInit) rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9}) } ptrType := llvm.ConstNull(tm.runtimePtrType) var baseTypeGlobal llvm.Value if p.Elem().Underlying() == p { // Recursive pointer. ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType) baseTypeGlobal = global // Update the global with its own pointer in the elem field. ptrType = global.Initializer() ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1}) global.SetInitializer(ptrType) } else { var baseTypePtr llvm.Value baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem()) ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0}) ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1}) global, ptr = tm.makeRuntimeTypeGlobal(ptrType) } global.SetName(globalname) // Set ptrToThis in the base type's rtype. baseType := baseTypeGlobal.Initializer() if baseType.Type() == tm.runtimeType { baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10}) } else { rtype := llvm.ConstExtractValue(baseType, []uint32{0}) rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10}) baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0}) } baseTypeGlobal.SetInitializer(baseType) return global, ptr }
// p != nil iff we're generatig the uncommonType for a pointer type. func (tm *TypeMap) uncommonType(n *types.Named, p *types.Pointer) llvm.Value { uncommonTypeInit := llvm.ConstNull(tm.runtime.uncommonType.llvm) namePtr := tm.globalStringPtr(n.Obj().Name()) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, namePtr, []uint32{0}) var path string if pkg := n.Obj().Pkg(); pkg != nil { path = pkg.Path() } pkgpathPtr := tm.globalStringPtr(path) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, pkgpathPtr, []uint32{1}) // If we're dealing with an interface, stop now; // we store interface methods on the interface // type. if _, ok := n.Underlying().(*types.Interface); ok { return uncommonTypeInit } var methodset, pmethodset *types.MethodSet if p != nil { methodset = p.MethodSet() } else { methodset = n.MethodSet() } // Store methods. All methods must be stored, not only exported ones; // this is to allow satisfying of interfaces with non-exported methods. methods := make([]llvm.Value, methodset.Len()) for i := range methods { sel := methodset.At(i) mname := sel.Obj().Name() mfunc := tm.methodResolver.ResolveMethod(sel) ftyp := mfunc.Type().(*types.Signature) method := llvm.ConstNull(tm.runtime.method.llvm) name := tm.globalStringPtr(mname) name = llvm.ConstBitCast(name, tm.runtime.method.llvm.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 := llvm.ConstPtrToInt(mfunc.LLVMValue(), tm.target.IntPtrType()) // ifn (single-word receiver function pointer for interface calls) ifn := tfn if p == nil { if tm.Sizeof(n) > int64(tm.target.PointerSize()) { if pmethodset == nil { pmethodset = types.NewPointer(n).MethodSet() } pmfunc := tm.methodResolver.ResolveMethod(pmethodset.Lookup(sel.Obj().Pkg(), mname)) ifn = llvm.ConstPtrToInt(pmfunc.LLVMValue(), tm.target.IntPtrType()) } else if _, ok := n.Underlying().(*types.Pointer); !ok { // Create a wrapper function that takes an *int8, // and coerces to the receiver type. ifn = tm.interfaceFuncWrapper(mfunc.LLVMValue()) 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.runtime.uncommonType.llvm.StructElementTypes()[2] methodsSlice := tm.makeSlice(methods, methodsSliceType) uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, methodsSlice, []uint32{2}) return uncommonTypeInit }