func (p *exporter) signature(sig *types.Signature) { // We need the receiver information (T vs *T) // for methods associated with named types. // We do not record interface receiver types in the // export data because 1) the importer can derive them // from the interface type and 2) they create cycles // in the type graph. if recv := sig.Recv(); recv != nil { if _, ok := recv.Type().Underlying().(*types.Interface); !ok { // 1-element tuple p.int(1) p.param(recv) } else { // 0-element tuple p.int(0) } } else { // 0-element tuple p.int(0) } p.tuple(sig.Params()) p.tuple(sig.Results()) if sig.Variadic() { p.int(1) } else { p.int(0) } }
func (d *DIBuilder) descriptorSignature(t *types.Signature, name string) llvm.Value { // If there's a receiver change the receiver to an // additional (first) parameter, and take the value of // the resulting signature instead. if recv := t.Recv(); recv != nil { params := t.Params() paramvars := make([]*types.Var, int(params.Len()+1)) paramvars[0] = recv for i := 0; i < int(params.Len()); i++ { paramvars[i+1] = params.At(i) } params = types.NewTuple(paramvars...) t := types.NewSignature(nil, nil, params, t.Results(), t.Variadic()) return d.typeDebugDescriptor(t, name) } if dt, ok := d.types.At(t).(llvm.Value); ok { return dt } var returnType llvm.Value results := t.Results() switch n := results.Len(); n { case 0: returnType = d.DIType(nil) // void case 1: returnType = d.DIType(results.At(0).Type()) default: fields := make([]*types.Var, results.Len()) for i := range fields { f := results.At(i) // Structs may not have multiple fields // with the same name, excepting "_". if f.Name() == "" { f = types.NewVar(f.Pos(), f.Pkg(), "_", f.Type()) } fields[i] = f } returnType = d.typeDebugDescriptor(types.NewStruct(fields, nil), "") } var paramTypes []llvm.Value params := t.Params() if params != nil && params.Len() > 0 { paramTypes = make([]llvm.Value, params.Len()+1) paramTypes[0] = returnType for i := range paramTypes[1:] { paramTypes[i+1] = d.DIType(params.At(i).Type()) } } else { paramTypes = []llvm.Value{returnType} } // TODO(axw) get position of type definition for File field return d.builder.CreateSubroutineType(llvm.DISubroutineType{ Parameters: paramTypes, }) }
// FuncHasQuery returns the offset of the string parameter named "query", or // none if no such parameter exists. func FuncHasQuery(s *types.Signature) (offset int, ok bool) { params := s.Params() for i := 0; i < params.Len(); i++ { v := params.At(i) if v.Name() == "query" && v.Type() == stringType { return i, true } } return 0, false }
func newSignatureFrom(pkg *Package, sig *types.Signature) *Signature { var recv *Var if sig.Recv() != nil { recv = newVarFrom(pkg, sig.Recv()) } return &Signature{ ret: newVarsFrom(pkg, sig.Results()), args: newVarsFrom(pkg, sig.Params()), recv: recv, } }
func (f *Finder) call(sig *types.Signature, args []ast.Expr) { if len(args) == 0 { return } // Ellipsis call? e.g. f(x, y, z...) if _, ok := args[len(args)-1].(*ast.Ellipsis); ok { for i, arg := range args { // The final arg is a slice, and so is the final param. f.assign(sig.Params().At(i).Type(), f.expr(arg)) } return } var argtypes []types.Type // Gather the effective actual parameter types. if tuple, ok := f.info.Types[args[0]].Type.(*types.Tuple); ok { // f(g()) call where g has multiple results? f.expr(args[0]) // unpack the tuple for i := 0; i < tuple.Len(); i++ { argtypes = append(argtypes, tuple.At(i).Type()) } } else { for _, arg := range args { argtypes = append(argtypes, f.expr(arg)) } } // Assign the actuals to the formals. if !sig.Variadic() { for i, argtype := range argtypes { f.assign(sig.Params().At(i).Type(), argtype) } } else { // The first n-1 parameters are assigned normally. nnormals := sig.Params().Len() - 1 for i, argtype := range argtypes[:nnormals] { f.assign(sig.Params().At(i).Type(), argtype) } // Remaining args are assigned to elements of varargs slice. tElem := sig.Params().At(nnormals).Type().(*types.Slice).Elem() for i := nnormals; i < len(argtypes); i++ { f.assign(tElem, argtypes[i]) } } }
func (tm *llvmTypeMap) getSignatureInfo(sig *types.Signature) functionTypeInfo { var args, results []types.Type if sig.Recv() != nil { recvtype := sig.Recv().Type() if _, ok := recvtype.Underlying().(*types.Pointer); !ok && recvtype != types.Typ[types.UnsafePointer] { recvtype = types.NewPointer(recvtype) } args = []types.Type{recvtype} } for i := 0; i != sig.Params().Len(); i++ { args = append(args, sig.Params().At(i).Type()) } for i := 0; i != sig.Results().Len(); i++ { results = append(results, sig.Results().At(i).Type()) } return tm.getFunctionTypeInfo(args, results) }
func (p *printer) writeSignatureInternal(this *types.Package, sig *types.Signature, visited []types.Type) { p.writeTuple(this, sig.Params(), sig.Variadic(), visited) res := sig.Results() n := res.Len() if n == 0 { // no result return } p.print(" ") if n == 1 && res.At(0).Name() == "" { // single unnamed result p.writeTypeInternal(this, res.At(0).Type(), visited) return } // multiple or named result(s) p.writeTuple(this, res, false, visited) }
func parseMethodType(t *types.Signature) (ptype, rtype types.Type, err error) { mp := t.Params() if mp.Len() != 1 && mp.Len() != 2 { return nil, nil, errgo.New("wrong argument count") } ptype0 := mp.At(mp.Len() - 1).Type() ptype1, ok := ptype0.(*types.Pointer) if !ok { return nil, nil, errgo.New("parameter is not a pointer") } ptype = ptype1.Elem() if _, ok := ptype.Underlying().(*types.Struct); !ok { return nil, nil, errgo.Newf("parameter is %s, not a pointer to struct", ptype1.Elem()) } rp := t.Results() if rp.Len() > 2 { return nil, nil, errgo.New("wrong result count") } if rp.Len() == 2 { rtype = rp.At(0).Type() } return ptype, rtype, nil }
func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, ellipsis, clone bool) []string { if len(argExprs) == 1 { if tuple, isTuple := c.p.TypeOf(argExprs[0]).(*types.Tuple); isTuple { tupleVar := c.newVariable("_tuple") c.Printf("%s = %s;", tupleVar, c.translateExpr(argExprs[0])) argExprs = make([]ast.Expr, tuple.Len()) for i := range argExprs { argExprs[i] = c.newIdent(c.formatExpr("%s[%d]", tupleVar, i).String(), tuple.At(i).Type()) } } } paramsLen := sig.Params().Len() var varargType *types.Slice if sig.Variadic() && !ellipsis { varargType = sig.Params().At(paramsLen - 1).Type().(*types.Slice) } preserveOrder := false for i := 1; i < len(argExprs); i++ { preserveOrder = preserveOrder || c.Blocking[argExprs[i]] } args := make([]string, len(argExprs)) for i, argExpr := range argExprs { var argType types.Type switch { case varargType != nil && i >= paramsLen-1: argType = varargType.Elem() default: argType = sig.Params().At(i).Type() } var arg string switch { case clone: arg = c.translateImplicitConversionWithCloning(argExpr, argType).String() default: arg = c.translateImplicitConversion(argExpr, argType).String() } if preserveOrder && c.p.Types[argExpr].Value == nil { argVar := c.newVariable("_arg") c.Printf("%s = %s;", argVar, arg) arg = argVar } args[i] = arg } if varargType != nil { return append(args[:paramsLen-1], fmt.Sprintf("new %s([%s])", c.typeName(varargType), strings.Join(args[paramsLen-1:], ", "))) } return args }
func changeRecv(s *types.Signature, recv *types.Var) *types.Signature { return types.NewSignature(recv, s.Params(), s.Results(), s.Variadic()) }