summaryrefslogtreecommitdiff
path: root/src/cmd/cgo/out.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cgo/out.go')
-rw-r--r--src/cmd/cgo/out.go96
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 = `