diff options
Diffstat (limited to 'src/cmd/cgo/out.go')
-rw-r--r-- | src/cmd/cgo/out.go | 96 |
1 files changed, 46 insertions, 50 deletions
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index ede8f57d8..4a5fa6a73 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -20,20 +20,11 @@ import ( // writeDefs creates output files to be compiled by 6g, 6c, and gcc. // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) func (p *Package) writeDefs() { - // The path for the shared object is slash-free so that ELF loaders - // will treat it as a relative path. We rewrite slashes to underscores. - sopath := "cgo_" + strings.Map(slashToUnderscore, p.PackagePath) - soprefix := "" - if os.Getenv("GOOS") == "darwin" { - // OS X requires its own prefix for a relative path - soprefix = "@rpath/" - } - - fgo2 := creat("_cgo_gotypes.go") - fc := creat("_cgo_defun.c") - fm := creat("_cgo_main.c") + fgo2 := creat("_obj/_cgo_gotypes.go") + fc := creat("_obj/_cgo_defun.c") + fm := creat("_obj/_cgo_main.c") - fflg := creat("_cgo_flags") + fflg := creat("_obj/_cgo_flags") for k, v := range p.CgoFlags { fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, v) } @@ -94,7 +85,7 @@ func (p *Package) writeDefs() { for _, n := range p.Name { if n.FuncType != nil { - p.writeDefsFunc(fc, fgo2, n, soprefix, sopath) + p.writeDefsFunc(fc, fgo2, n) } } @@ -172,7 +163,7 @@ func (p *Package) structType(n *Name) (string, int64) { off += pad } qual := "" - if t.C[len(t.C)-1] == '*' { + if c := t.C.String(); c[len(c)-1] == '*' { qual = "const " } fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) @@ -189,13 +180,12 @@ func (p *Package) structType(n *Name) (string, int64) { } if off == 0 { fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct - off++ } fmt.Fprintf(&buf, "\t}") return buf.String(), off } -func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name, soprefix, sopath string) { +func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { name := n.Go gtype := n.FuncType.Go if n.AddError { @@ -234,6 +224,9 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name, soprefix, sopath str fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle) fmt.Fprintf(fc, "\n") fmt.Fprintf(fc, "void\n") + if argSize == 0 { + argSize++ + } fmt.Fprintf(fc, "·%s(struct{uint8 x[%d];}p)\n", n.Mangle, argSize) fmt.Fprintf(fc, "{\n") fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle) @@ -271,8 +264,8 @@ func (p *Package) writeOutput(f *File, srcfile string) { base = base[0 : len(base)-3] } base = strings.Map(slashToUnderscore, base) - fgo1 := creat(base + ".cgo1.go") - fgcc := creat(base + ".cgo2.c") + fgo1 := creat("_obj/" + base + ".cgo1.go") + fgcc := creat("_obj/" + base + ".cgo2.c") p.GoFiles = append(p.GoFiles, base+".cgo1.go") p.GccFiles = append(p.GccFiles, base+".cgo2.c") @@ -340,7 +333,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { // Write out the various stubs we need to support functions exported // from Go so that they are callable from C. func (p *Package) writeExports(fgo2, fc, fm *os.File) { - fgcc := creat("_cgo_export.c") + fgcc := creat("_obj/_cgo_export.c") fgcch := creat("_cgo_export.h") fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") @@ -401,7 +394,6 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { } if ctype == "struct {\n" { ctype += "\t\tchar unused;\n" // avoid empty struct - off++ } ctype += "\t}" @@ -411,7 +403,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { if fntype.Results == nil || len(fntype.Results.List) == 0 { gccResult = "void" } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { - gccResult = p.cgoType(fntype.Results.List[0].Type).C + gccResult = p.cgoType(fntype.Results.List[0].Type).C.String() } else { fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName) @@ -426,7 +418,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { // Build the wrapper function compiled by gcc. s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) if fn.Recv != nil { - s += p.cgoType(fn.Recv.List[0].Type).C + s += p.cgoType(fn.Recv.List[0].Type).C.String() s += " recv" } forFieldList(fntype.Params, @@ -453,7 +445,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { func(i int, atype ast.Expr) { fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) }) - fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, (int) sizeof a);\n", cPrefix, exp.ExpName) + fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off) if gccResult != "void" { if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { fmt.Fprintf(fgcc, "\treturn a.r0;\n") @@ -542,24 +534,28 @@ func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) { } } +func c(repr string, args ...interface{}) *TypeRepr { + return &TypeRepr{repr, args} +} + // Map predeclared Go types to Type. var goTypes = map[string]*Type{ - "int": &Type{Size: 4, Align: 4, C: "int"}, - "uint": &Type{Size: 4, Align: 4, C: "uint"}, - "int8": &Type{Size: 1, Align: 1, C: "schar"}, - "uint8": &Type{Size: 1, Align: 1, C: "uchar"}, - "int16": &Type{Size: 2, Align: 2, C: "short"}, - "uint16": &Type{Size: 2, Align: 2, C: "ushort"}, - "int32": &Type{Size: 4, Align: 4, C: "int"}, - "uint32": &Type{Size: 4, Align: 4, C: "uint"}, - "int64": &Type{Size: 8, Align: 8, C: "int64"}, - "uint64": &Type{Size: 8, Align: 8, C: "uint64"}, - "float": &Type{Size: 4, Align: 4, C: "float"}, - "float32": &Type{Size: 4, Align: 4, C: "float"}, - "float64": &Type{Size: 8, Align: 8, C: "double"}, - "complex": &Type{Size: 8, Align: 8, C: "__complex float"}, - "complex64": &Type{Size: 8, Align: 8, C: "__complex float"}, - "complex128": &Type{Size: 16, Align: 16, C: "__complex double"}, + "int": &Type{Size: 4, Align: 4, C: c("int")}, + "uint": &Type{Size: 4, Align: 4, C: c("uint")}, + "int8": &Type{Size: 1, Align: 1, C: c("schar")}, + "uint8": &Type{Size: 1, Align: 1, C: c("uchar")}, + "int16": &Type{Size: 2, Align: 2, C: c("short")}, + "uint16": &Type{Size: 2, Align: 2, C: c("ushort")}, + "int32": &Type{Size: 4, Align: 4, C: c("int")}, + "uint32": &Type{Size: 4, Align: 4, C: c("uint")}, + "int64": &Type{Size: 8, Align: 8, C: c("int64")}, + "uint64": &Type{Size: 8, Align: 8, C: c("uint64")}, + "float": &Type{Size: 4, Align: 4, C: c("float")}, + "float32": &Type{Size: 4, Align: 4, C: c("float")}, + "float64": &Type{Size: 8, Align: 8, C: c("double")}, + "complex": &Type{Size: 8, Align: 8, C: c("__complex float")}, + "complex64": &Type{Size: 8, Align: 8, C: c("__complex float")}, + "complex128": &Type{Size: 16, Align: 16, C: c("__complex double")}, } // Map an ast type to a Type. @@ -567,21 +563,21 @@ func (p *Package) cgoType(e ast.Expr) *Type { switch t := e.(type) { case *ast.StarExpr: x := p.cgoType(t.X) - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: x.C + "*"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)} case *ast.ArrayType: if t.Len == nil { - return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: "GoSlice"} + return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: c("GoSlice")} } case *ast.StructType: // TODO case *ast.FuncType: - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "void*"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} case *ast.InterfaceType: - return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: "GoInterface"} + return &Type{Size: 3 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} case *ast.MapType: - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "GoMap"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")} case *ast.ChanType: - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "GoChan"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")} case *ast.Ident: // Look up the type in the top level declarations. // TODO: Handle types defined within a function. @@ -606,10 +602,10 @@ func (p *Package) cgoType(e ast.Expr) *Type { } } if t.Name == "uintptr" { - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "uintptr"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")} } if t.Name == "string" { - return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: "GoString"} + return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")} } if r, ok := goTypes[t.Name]; ok { if r.Align > p.PtrSize { @@ -620,11 +616,11 @@ func (p *Package) cgoType(e ast.Expr) *Type { case *ast.SelectorExpr: id, ok := t.X.(*ast.Ident) if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" { - return &Type{Size: p.PtrSize, Align: p.PtrSize, C: "void*"} + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} } } error(e.Pos(), "unrecognized Go type %T", e) - return &Type{Size: 4, Align: 4, C: "int"} + return &Type{Size: 4, Align: 4, C: c("int")} } const gccProlog = ` |