Beispiel #1
0
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)
	}
}
Beispiel #2
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,
	})
}
Beispiel #3
0
// 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
}
Beispiel #4
0
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,
	}
}
Beispiel #5
0
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])
		}
	}
}
Beispiel #6
0
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)
}
Beispiel #8
0
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
}
Beispiel #9
0
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
}
Beispiel #10
0
func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
	return types.NewSignature(recv, s.Params(), s.Results(), s.Variadic())
}