func (c *compiler) evalCallArgs(ftype *types.Signature, args []ast.Expr) []Value { var argValues []Value if len(args) == 0 { return argValues } arg0 := args[0] if _, ok := c.types.expr[arg0].Type.(*types.Tuple); ok { // f(g(...)), where g is multi-value return argValues = c.destructureExpr(args[0]) } else { argValues = make([]Value, len(args)) for i, x := range args { var paramtyp types.Type params := ftype.Params() if ftype.IsVariadic() && i >= int(params.Len()-1) { paramtyp = params.At(int(params.Len() - 1)).Type() } else { paramtyp = params.At(i).Type() } c.convertUntyped(x, paramtyp) argValues[i] = c.VisitExpr(x) } } return argValues }
func (c *compiler) makeFunc(ident *ast.Ident, ftyp *types.Signature) *LLVMValue { fname := ident.String() if ftyp.Recv() == nil && fname == "init" { // Make "init" functions anonymous. fname = "" } else { var pkgname string if recv := ftyp.Recv(); recv != nil { var recvname string switch recvtyp := recv.Type().(type) { case *types.Pointer: if named, ok := recvtyp.Elem().(*types.Named); ok { obj := named.Obj() recvname = "*" + obj.Name() pkgname = obj.Pkg().Path() } case *types.Named: named := recvtyp obj := named.Obj() recvname = obj.Name() pkgname = obj.Pkg().Path() } if recvname != "" { fname = fmt.Sprintf("%s.%s", recvname, fname) } else { // If the receiver is an unnamed struct, we're // synthesising a method for an unnamed struct // type. There's no meaningful name to give the // function, so leave it up to LLVM. fname = "" } } else { obj := c.typeinfo.Objects[ident] pkgname = obj.Pkg().Path() } if fname != "" { fname = pkgname + "." + fname } } // gcimporter may produce multiple AST objects for the same function. llvmftyp := c.types.ToLLVM(ftyp) var fn llvm.Value if fname != "" { fn = c.module.Module.NamedFunction(fname) } if fn.IsNil() { llvmfptrtyp := llvmftyp.StructElementTypes()[0].ElementType() fn = llvm.AddFunction(c.module.Module, fname, llvmfptrtyp) } fn = llvm.ConstInsertValue(llvm.ConstNull(llvmftyp), fn, []uint32{0}) return c.NewValue(fn, ftyp) }
// writeSignature writes to buf the signature sig in declaration syntax. func writeSignature(buf *bytes.Buffer, pkg *types.Package, name string, sig *types.Signature, params []*Parameter) { buf.WriteString("func ") if recv := sig.Recv(); recv != nil { buf.WriteString("(") if n := params[0].Name(); n != "" { buf.WriteString(n) buf.WriteString(" ") } buf.WriteString(relType(params[0].Type(), pkg)) buf.WriteString(") ") } buf.WriteString(name) types.WriteSignature(buf, pkg, sig) }
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 (tm *TypeMap) funcRuntimeType(f *types.Signature) (global, ptr llvm.Value) { rtype := tm.makeRtype(f, reflect.Func) funcType := llvm.ConstNull(tm.runtimeFuncType) funcType = llvm.ConstInsertValue(funcType, rtype, []uint32{0}) // dotdotdot if f.IsVariadic() { variadic := llvm.ConstInt(llvm.Int1Type(), 1, false) funcType = llvm.ConstInsertValue(funcType, variadic, []uint32{1}) } // TODO in //funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{2}) // TODO out //funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{3}) return tm.makeRuntimeTypeGlobal(funcType) }
// changeRecv returns sig with Recv prepended to Params(). func changeRecv(sig *types.Signature) *types.Signature { params := sig.Params() n := params.Len() p2 := make([]*types.Var, n+1) p2[0] = sig.Recv() for i := 0; i < n; i++ { p2[i+1] = params.At(i) } return types.NewSignature(nil, nil, types.NewTuple(p2...), sig.Results(), sig.IsVariadic()) }
func (c *compiler) evalCallArgs(ftype *types.Signature, args []ast.Expr, dotdotdot bool) []Value { var argValues []Value if len(args) == 0 { return argValues } var argtypes []types.Type if t, ok := c.typeinfo.Types[args[0]].(*types.Tuple); ok { argtypes = make([]types.Type, t.Len()) } else { argtypes = make([]types.Type, len(args)) } params := ftype.Params() for i := range argtypes { if ftype.IsVariadic() && i >= int(params.Len()-1) { argtypes[i] = params.At(int(params.Len() - 1)).Type() argtypes[i] = argtypes[i].(*types.Slice).Elem() } else { argtypes[i] = params.At(i).Type() } } if len(argtypes) > len(args) { // f(g(...)), where g is multi-value return argValues = c.destructureExpr(args[0]) } else { argValues = make([]Value, len(args)) for i, x := range args { c.convertUntyped(x, argtypes[i]) argValues[i] = c.VisitExpr(x) } } for i, v := range argValues { if !dotdotdot || i < int(params.Len()-1) { argValues[i] = v.Convert(argtypes[i]) } } return argValues }
func (cdd *CDD) signature(sig *types.Signature, recv bool, pnames int) (res results, params string) { params = "(" res = cdd.results(sig.Results()) if r := sig.Recv(); r != nil && recv { typ, dim, acds := cdd.TypeStr(r.Type()) res.acds = append(res.acds, acds...) var pname string switch pnames { case numNames: pname = "_0" case orgNames: pname = cdd.NameStr(r, true) } if pname == "" { params += typ + dimFuncPtr("", dim) } else { params += typ + " " + dimFuncPtr(pname, dim) } if sig.Params() != nil { params += ", " } } if p := sig.Params(); p != nil { for i, n := 0, p.Len(); i < n; i++ { if i != 0 { params += ", " } v := p.At(i) typ, dim, acds := cdd.TypeStr(v.Type()) res.acds = append(res.acds, acds...) var pname string switch pnames { case numNames: pname = "_" + strconv.Itoa(i+1) case orgNames: pname = cdd.NameStr(v, true) if pname == "_$" { pname = "unused" + cdd.gtc.uniqueId() } } if pname == "" { params += typ + dimFuncPtr("", dim) } else { params += typ + " " + dimFuncPtr(pname, dim) } } } params += ")" return }
func (c *funcContext) translateArgs(sig *types.Signature, args []ast.Expr, ellipsis bool) []string { params := make([]string, sig.Params().Len()) for i := range params { if sig.Variadic() && i == len(params)-1 && !ellipsis { varargType := sig.Params().At(i).Type().(*types.Slice) varargs := make([]string, len(args)-i) for j, arg := range args[i:] { varargs[j] = c.translateImplicitConversionWithCloning(arg, varargType.Elem()).String() } params[i] = fmt.Sprintf("new %s([%s])", c.typeName(varargType), strings.Join(varargs, ", ")) break } argType := sig.Params().At(i).Type() params[i] = c.translateImplicitConversionWithCloning(args[i], argType).String() } return params }
func (c *PkgContext) translateArgs(sig *types.Signature, args []ast.Expr, ellipsis bool) string { params := make([]string, sig.Params().Len()) for i := range params { if sig.IsVariadic() && i == len(params)-1 && !ellipsis { varargType := sig.Params().At(i).Type().(*types.Slice) varargs := make([]string, len(args)-i) for j, arg := range args[i:] { varargs[j] = c.translateExprToType(arg, varargType.Elem()) } params[i] = fmt.Sprintf("new %s(%s)", c.typeName(varargType), createListComposite(varargType.Elem(), varargs)) break } argType := sig.Params().At(i).Type() params[i] = c.translateExprToType(args[i], argType) } return strings.Join(params, ", ") }
func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) { w.writeParams(buf, sig.Params(), sig.IsVariadic()) switch res := sig.Results(); res.Len() { case 0: // nothing to do case 1: buf.WriteByte(' ') w.writeType(buf, res.At(0).Type()) default: buf.WriteByte(' ') w.writeParams(buf, res, false) } }
// writeSignature writes to w the signature sig in declaration syntax. // Derived from types.Signature.String(). // func writeSignature(w io.Writer, name string, sig *types.Signature, params []*Parameter) { io.WriteString(w, "func ") if recv := sig.Recv(); recv != nil { io.WriteString(w, "(") if n := params[0].Name(); n != "" { io.WriteString(w, n) io.WriteString(w, " ") } io.WriteString(w, params[0].Type().String()) io.WriteString(w, ") ") params = params[1:] } io.WriteString(w, name) io.WriteString(w, "(") for i, v := range params { if i > 0 { io.WriteString(w, ", ") } io.WriteString(w, v.Name()) io.WriteString(w, " ") if sig.IsVariadic() && i == len(params)-1 { io.WriteString(w, "...") io.WriteString(w, v.Type().Underlying().(*types.Slice).Elem().String()) } else { io.WriteString(w, v.Type().String()) } } io.WriteString(w, ")") if n := sig.Results().Len(); n > 0 { io.WriteString(w, " ") r := sig.Results() if n == 1 && r.At(0).Name() == "" { io.WriteString(w, r.At(0).Type().String()) } else { io.WriteString(w, r.String()) } } }
func (p *exporter) signature(sig *types.Signature) { // TODO(gri) We only need to record the receiver type // for interface methods if we flatten them // out. If we track embedded types instead, // the information is already present. // We do need the receiver information (T vs *T) // for methods associated with named types. if recv := sig.Recv(); recv != nil { // 1-element tuple p.int(1) p.param(recv) } 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 (v funcTypeVisitor) Visit(node ast.Node) ast.Visitor { var sig *types.Signature var noderecv *ast.FieldList var astfunc *ast.FuncType switch node := node.(type) { case *ast.FuncDecl: sig = v.objects[node.Name].Type().(*types.Signature) astfunc = node.Type noderecv = node.Recv case *ast.FuncLit: sig = v.exprtypes[node].Type.(*types.Signature) astfunc = node.Type default: return v } // go/types creates a separate types.Var for // internal and external usage. We need to // associate them at the object data level. paramIdents := fieldlistIdents(astfunc.Params) resultIdents := fieldlistIdents(astfunc.Results) if recv := sig.Recv(); recv != nil { id := fieldlistIdents(noderecv)[0] if obj, ok := v.objects[id]; ok { v.objectdata[recv] = v.objectdata[obj] } } for i, id := range paramIdents { if obj, ok := v.objects[id]; ok { v.objectdata[sig.Params().At(i)] = v.objectdata[obj] } } for i, id := range resultIdents { if obj, ok := v.objects[id]; ok { v.objectdata[sig.Results().At(i)] = v.objectdata[obj] } } return v }
func (tm *TypeMap) funcRuntimeType(f *types.Signature) (global, ptr llvm.Value) { rtype := tm.makeRtype(f, reflect.Func) funcType := llvm.ConstNull(tm.runtime.funcType.llvm) global, ptr = tm.makeRuntimeTypeGlobal(funcType, typeString(f)) tm.types.Set(f, runtimeTypeInfo{global, ptr}) funcType = llvm.ConstInsertValue(funcType, rtype, []uint32{0}) // dotdotdot if f.Variadic() { variadic := llvm.ConstInt(llvm.Int1Type(), 1, false) funcType = llvm.ConstInsertValue(funcType, variadic, []uint32{1}) } // in intypes := tm.rtypeSlice(f.Params()) funcType = llvm.ConstInsertValue(funcType, intypes, []uint32{2}) // out outtypes := tm.rtypeSlice(f.Results()) funcType = llvm.ConstInsertValue(funcType, outtypes, []uint32{3}) global.SetInitializer(funcType) return global, ptr }
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 (ts *TypeStringer) writeSignature(buf *bytes.Buffer, sig *types.Signature, unique bool) { if recv := sig.Recv(); recv != nil { if _, ok := recv.Type().Underlying().(*types.Interface); !ok { ts.writeType(buf, recv.Type(), unique) buf.WriteByte(' ') } } ts.writeParams(buf, sig.Params(), sig.IsVariadic(), unique) if sig.Results().Len() == 0 { // no result return } buf.WriteByte(' ') if sig.Results().Len() == 1 { // single unnamed result ts.writeType(buf, sig.Results().At(0).Type(), unique) return } // multiple or named result(s) ts.writeParams(buf, sig.Results(), false, unique) }
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 (ts *TypeStringer) writeSignature(buf *bytes.Buffer, sig *types.Signature) { if recv := sig.Recv(); recv != nil { ts.writeType(buf, recv.Type()) buf.WriteByte(' ') } ts.writeParams(buf, sig.Params(), sig.IsVariadic()) if sig.Results().Len() == 0 { // no result return } buf.WriteByte(' ') if sig.Results().Len() == 1 { // single unnamed result ts.writeType(buf, sig.Results().At(0).Type()) return } // multiple or named result(s) ts.writeParams(buf, sig.Results(), false) }
func (tm *LLVMTypeMap) funcLLVMType(tstr string, f *types.Signature) llvm.Type { typ, ok := tm.types[tstr] if !ok { // If there's a receiver change the receiver to an // additional (first) parameter, and take the value of // the resulting signature instead. var param_types []llvm.Type if recv := f.Recv(); recv != nil { params := f.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...) f := types.NewSignature(nil, params, f.Results(), f.IsVariadic()) return tm.ToLLVM(f) } typ = llvm.GlobalContext().StructCreateNamed("") tm.types[tstr] = typ params := f.Params() nparams := int(params.Len()) for i := 0; i < nparams; i++ { typ := params.At(i).Type() if f.IsVariadic() && i == nparams-1 { typ = types.NewSlice(typ) } llvmtyp := tm.ToLLVM(typ) param_types = append(param_types, llvmtyp) } var return_type llvm.Type results := f.Results() switch nresults := int(results.Len()); nresults { case 0: return_type = llvm.VoidType() case 1: return_type = tm.ToLLVM(results.At(0).Type()) default: elements := make([]llvm.Type, nresults) for i := range elements { result := results.At(i) elements[i] = tm.ToLLVM(result.Type()) } return_type = llvm.StructType(elements, false) } fntyp := llvm.FunctionType(return_type, param_types, false) fnptrtyp := llvm.PointerType(fntyp, 0) i8ptr := llvm.PointerType(llvm.Int8Type(), 0) elements := []llvm.Type{fnptrtyp, i8ptr} // func, closure typ.StructSetBody(elements, false) } return typ }
func (tm *llvmTypeMap) funcLLVMType(f *types.Signature, name string) llvm.Type { // If there's a receiver change the receiver to an // additional (first) parameter, and take the value of // the resulting signature instead. if recv := f.Recv(); recv != nil { params := f.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...) f := types.NewSignature(nil, nil, params, f.Results(), f.Variadic()) return tm.toLLVM(f, name) } if typ, ok := tm.types.At(f).(llvm.Type); ok { return typ } typ := llvm.GlobalContext().StructCreateNamed(name) tm.types.Set(f, typ) params := f.Params() param_types := make([]llvm.Type, params.Len()) for i := range param_types { llvmtyp := tm.ToLLVM(params.At(i).Type()) param_types[i] = llvmtyp } var return_type llvm.Type results := f.Results() switch nresults := int(results.Len()); nresults { case 0: return_type = llvm.VoidType() case 1: return_type = tm.ToLLVM(results.At(0).Type()) default: elements := make([]llvm.Type, nresults) for i := range elements { result := results.At(i) elements[i] = tm.ToLLVM(result.Type()) } return_type = llvm.StructType(elements, false) } fntyp := llvm.FunctionType(return_type, param_types, false) fnptrtyp := llvm.PointerType(fntyp, 0) i8ptr := llvm.PointerType(llvm.Int8Type(), 0) elements := []llvm.Type{fnptrtyp, i8ptr} // func, closure typ.StructSetBody(elements, false) return typ }
func (m *TypeMap) descriptorSignature(t *types.Signature, name string) TypeDebugDescriptor { // 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 m.typeDebugDescriptor(t, name) } if dt, ok := m.m.At(t).(TypeDebugDescriptor); ok { return dt } var returnType DebugDescriptor var paramTypes []DebugDescriptor if results := t.Results(); results.Len() == 1 { returnType = m.TypeDebugDescriptor(results.At(0).Type()) } else if results != nil { fields := make([]DebugDescriptor, results.Len()) for i := range fields { fields[i] = m.TypeDebugDescriptor(results.At(i).Type()) } returnType = NewStructCompositeType(fields) } if params := t.Params(); params != nil && params.Len() > 0 { paramTypes = make([]DebugDescriptor, params.Len()) for i := range paramTypes { paramTypes[i] = m.TypeDebugDescriptor(params.At(i).Type()) } } ct := NewStructCompositeType([]DebugDescriptor{ NewSubroutineCompositeType(returnType, paramTypes), m.TypeDebugDescriptor(types.NewPointer(types.Typ[types.Uint8])), }) ct.Name = name m.m.Set(t, ct) return ct }
func changeRecv(s *types.Signature, recv *types.Var) *types.Signature { return types.NewSignature(nil, recv, s.Params(), s.Results(), s.Variadic()) }
func (c *PkgContext) translateFunctionBody(stmts []ast.Stmt, sig *types.Signature) { c.funcVarNames = nil body := c.CatchOutput(func() { var resultNames []ast.Expr if sig != nil && sig.Results().Len() != 0 && sig.Results().At(0).Name() != "" { resultNames = make([]ast.Expr, sig.Results().Len()) for i := 0; i < sig.Results().Len(); i++ { result := sig.Results().At(i) name := result.Name() if result.Name() == "_" { name = "result" } id := ast.NewIdent(name) c.info.Types[id] = result.Type() c.info.Objects[id] = result c.Printf("%s = %s;", c.translateExpr(id), c.zeroValue(result.Type())) resultNames[i] = id } } if sig != nil { s := c.functionSig defer func() { c.functionSig = s }() c.functionSig = sig } r := c.resultNames defer func() { c.resultNames = r }() c.resultNames = resultNames p := c.postLoopStmt defer func() { c.postLoopStmt = p }() c.postLoopStmt = make(map[string]ast.Stmt) v := HasDeferVisitor{} ast.Walk(&v, &ast.BlockStmt{List: stmts}) switch v.hasDefer { case true: c.Printf("var Go$deferred = [];") c.Printf("try {") c.Indent(func() { c.translateStmtList(stmts) }) c.Printf("} catch(Go$err) {") c.Indent(func() { c.Printf("if (Go$err.constructor !== Go$Panic) { Go$err = Go$wrapJavaScriptError(Go$err); }") c.Printf("Go$errorStack.push({ frame: Go$getStackDepth(), error: Go$err });") if sig != nil && sig.Results().Len() != 0 && resultNames == nil { zeros := make([]string, sig.Results().Len()) for i := range zeros { zeros[i] = c.zeroValue(sig.Results().At(i).Type()) } c.Printf("return %s;", strings.Join(zeros, ", ")) } }) c.Printf("} finally {") c.Indent(func() { c.Printf("Go$callDeferred(Go$deferred);") if resultNames != nil { c.translateStmt(&ast.ReturnStmt{}, "") } }) c.Printf("}") case false: c.translateStmtList(stmts) } }) if len(c.funcVarNames) != 0 { c.Printf("var %s;", strings.Join(c.funcVarNames, ", ")) } c.Write(body) }