// interfaceMethod returns a function and receiver pointer for the specified // interface and method pair. func (fr *frame) interfaceMethod(lliface llvm.Value, ifacety types.Type, method *types.Func) (fn, recv *govalue) { llitab := fr.builder.CreateExtractValue(lliface, 0, "") recv = newValue(fr.builder.CreateExtractValue(lliface, 1, ""), types.Typ[types.UnsafePointer]) methodset := fr.types.MethodSet(ifacety) // TODO(axw) cache ordered method index index := -1 for i, m := range orderedMethodSet(methodset) { if m.Obj() == method { index = i break } } if index == -1 { panic("could not find method index") } llitab = fr.builder.CreateBitCast(llitab, llvm.PointerType(llvm.PointerType(llvm.Int8Type(), 0), 0), "") // Skip runtime type pointer. llifnptr := fr.builder.CreateGEP(llitab, []llvm.Value{ llvm.ConstInt(llvm.Int32Type(), uint64(index+1), false), }, "") llifn := fr.builder.CreateLoad(llifnptr, "") // Replace receiver type with unsafe.Pointer. recvparam := types.NewParam(0, nil, "", types.Typ[types.UnsafePointer]) sig := method.Type().(*types.Signature) sig = types.NewSignature(nil, recvparam, sig.Params(), sig.Results(), sig.Variadic()) fn = newValue(llifn, sig) return }
// ResultList = Type | ParamList . func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { switch p.tok { case '<': return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseType(pkg))) case '(': params, _ := p.parseParamList(pkg) return params default: return nil } }
// Param = Name ["..."] Type . func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) { name := p.parseName() if p.tok == '.' { p.next() p.expect('.') p.expect('.') isVariadic = true } typ := p.parseType(pkg) if isVariadic { typ = types.NewSlice(typ) } param = types.NewParam(token.NoPos, pkg, name, typ) return }
// newVar creates a 'var' for use in a types.Tuple. func newVar(name string, typ types.Type) *types.Var { return types.NewParam(token.NoPos, nil, name, typ) }