// 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 = tm.MethodSet(p) } else { methodset = tm.MethodSet(n) } // 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.Variadic()) 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 = tm.MethodSet(types.NewPointer(n)) } 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 }