summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go
diff options
context:
space:
mode:
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go')
-rw-r--r--llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go331
1 files changed, 208 insertions, 123 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go b/llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go
index d92bed9bf01..90a74419622 100644
--- a/llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go
+++ b/llgo/third_party/gofrontend/libgo/go/cmd/cgo/out.go
@@ -13,6 +13,7 @@ import (
"go/ast"
"go/printer"
"go/token"
+ "io"
"os"
"sort"
"strings"
@@ -20,11 +21,17 @@ import (
var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
-// 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.)
+// writeDefs creates output files to be compiled by gc and gcc.
func (p *Package) writeDefs() {
- fgo2 := creat(*objDir + "_cgo_gotypes.go")
- fc := creat(*objDir + "_cgo_defun.c")
+ var fgo2, fc io.Writer
+ f := creat(*objDir + "_cgo_gotypes.go")
+ defer f.Close()
+ fgo2 = f
+ if *gccgo {
+ f := creat(*objDir + "_cgo_defun.c")
+ defer f.Close()
+ fc = f
+ }
fm := creat(*objDir + "_cgo_main.c")
var gccgoInit bytes.Buffer
@@ -34,7 +41,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
if k == "LDFLAGS" && !*gccgo {
for _, arg := range v {
- fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+ fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
}
}
}
@@ -44,14 +51,17 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fm, "int main() { return 0; }\n")
if *importRuntimeCgo {
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+ fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done() { }\n")
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
} else {
// If we're not importing runtime/cgo, we *are* runtime/cgo,
- // which provides crosscall2. We just need a prototype.
+ // which provides these functions. We just need a prototype.
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
+ fmt.Fprintf(fm, "void _cgo_wait_runtime_init_done();\n")
}
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
+ fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
// Write second Go output: definitions of _C_xxx.
// In a separate file so that the import of "unsafe" does not
@@ -68,6 +78,13 @@ func (p *Package) writeDefs() {
}
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
+ if !*gccgo {
+ fmt.Fprintf(fgo2, "//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse\n")
+ fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n")
+ fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n")
+ fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n")
+ }
+
typedefNames := make([]string, 0, len(typedef))
for name := range typedef {
typedefNames = append(typedefNames, name)
@@ -88,7 +105,6 @@ func (p *Package) writeDefs() {
if *gccgo {
fmt.Fprint(fc, p.cPrologGccgo())
} else {
- fmt.Fprint(fc, cProlog)
fmt.Fprint(fgo2, goProlog)
}
@@ -102,44 +118,44 @@ func (p *Package) writeDefs() {
}
if !cVars[n.C] {
- fmt.Fprintf(fm, "extern char %s[];\n", n.C)
- fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
-
- if !*gccgo {
- fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
+ if *gccgo {
+ fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
+ } else {
+ fmt.Fprintf(fm, "extern char %s[];\n", n.C)
+ fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
+ fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
+ fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
+ fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
}
-
- fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
-
cVars[n.C] = true
}
- var amp string
+
var node ast.Node
if n.Kind == "var" {
- amp = "&"
node = &ast.StarExpr{X: n.Type.Go}
} else if n.Kind == "fpvar" {
node = n.Type.Go
- if *gccgo {
- amp = "&"
- }
} else {
panic(fmt.Errorf("invalid var kind %q", n.Kind))
}
if *gccgo {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
- fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
- } else {
- fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
- fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
+ fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
+ fmt.Fprintf(fc, "\n")
}
- fmt.Fprintf(fc, "\n")
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
conf.Fprint(fgo2, fset, node)
+ if !*gccgo {
+ fmt.Fprintf(fgo2, " = (")
+ conf.Fprint(fgo2, fset, node)
+ fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
+ }
fmt.Fprintf(fgo2, "\n")
}
- fmt.Fprintf(fc, "\n")
+ if *gccgo {
+ fmt.Fprintf(fc, "\n")
+ }
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
@@ -152,14 +168,37 @@ func (p *Package) writeDefs() {
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
if n.FuncType != nil {
- p.writeDefsFunc(fc, fgo2, n)
+ p.writeDefsFunc(fgo2, n)
}
}
+ fgcc := creat(*objDir + "_cgo_export.c")
+ fgcch := creat(*objDir + "_cgo_export.h")
if *gccgo {
- p.writeGccgoExports(fgo2, fc, fm)
+ p.writeGccgoExports(fgo2, fm, fgcc, fgcch)
} else {
- p.writeExports(fgo2, fc, fm)
+ p.writeExports(fgo2, fm, fgcc, fgcch)
+ }
+ if err := fgcc.Close(); err != nil {
+ fatalf("%s", err)
+ }
+ if err := fgcch.Close(); err != nil {
+ fatalf("%s", err)
+ }
+
+ if *exportHeader != "" && len(p.ExpFunc) > 0 {
+ fexp := creat(*exportHeader)
+ fgcch, err := os.Open(*objDir + "_cgo_export.h")
+ if err != nil {
+ fatalf("%s", err)
+ }
+ _, err = io.Copy(fexp, fgcch)
+ if err != nil {
+ fatalf("%s", err)
+ }
+ if err = fexp.Close(); err != nil {
+ fatalf("%s", err)
+ }
}
init := gccgoInit.String()
@@ -169,9 +208,6 @@ func (p *Package) writeDefs() {
fmt.Fprint(fc, init)
fmt.Fprintln(fc, "}")
}
-
- fgo2.Close()
- fc.Close()
}
func dynimport(obj string) {
@@ -184,13 +220,15 @@ func dynimport(obj string) {
stdout = f
}
+ fmt.Fprintf(stdout, "package %s\n", *dynpackage)
+
if f, err := elf.Open(obj); err == nil {
if *dynlinker {
// Emit the cgo_dynamic_linker line.
if sec := f.Section(".interp"); sec != nil {
if data, err := sec.Data(); err == nil && len(data) > 1 {
// skip trailing \0 in data
- fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
+ fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
}
}
}
@@ -203,14 +241,14 @@ func dynimport(obj string) {
if s.Version != "" {
targ += "#" + s.Version
}
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
}
for _, l := range lib {
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@@ -224,14 +262,14 @@ func dynimport(obj string) {
if len(s) > 0 && s[0] == '_' {
s = s[1:]
}
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
}
for _, l := range lib {
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@@ -244,7 +282,7 @@ func dynimport(obj string) {
for _, s := range sym {
ss := strings.Split(s, ":")
name := strings.Split(ss[0], "@")[0]
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
}
return
}
@@ -252,10 +290,10 @@ func dynimport(obj string) {
fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
}
-// Construct a gcc struct matching the 6c argument frame.
+// Construct a gcc struct matching the gc argument frame.
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
// These assumptions are checked by the gccProlog.
-// Also assumes that 6c convention is to word-align the
+// Also assumes that gc convention is to word-align the
// input and output parameters.
func (p *Package) structType(n *Name) (string, int64) {
var buf bytes.Buffer
@@ -304,7 +342,7 @@ func (p *Package) structType(n *Name) (string, int64) {
return buf.String(), off
}
-func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
+func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) {
name := n.Go
gtype := n.FuncType.Go
void := gtype.Results == nil || len(gtype.Results.List) == 0
@@ -396,11 +434,11 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
return
}
- // C wrapper calls into gcc, passing a pointer to the argument frame.
- fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
- fmt.Fprintf(fc, "void %s(void*);\n", cname)
- fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
- fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
+ // Wrapper calls into gcc, passing a pointer to the argument frame.
+ fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
+ fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
+ fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
+ fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
nret := 0
if !void {
@@ -412,7 +450,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
fmt.Fprint(fgo2, "\n")
- fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
@@ -428,16 +465,20 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
if n.AddError {
prefix = "errno := "
}
- fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg)
+ fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg)
if n.AddError {
fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
}
+ fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
+ for i := range d.Type.Params.List {
+ fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
+ }
+ fmt.Fprintf(fgo2, "\t}\n")
fmt.Fprintf(fgo2, "\treturn\n")
fmt.Fprintf(fgo2, "}\n")
}
-// writeOutput creates stubs for a specific source file to be compiled by 6g
-// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
+// writeOutput creates stubs for a specific source file to be compiled by gc
func (p *Package) writeOutput(f *File, srcfile string) {
base := srcfile
if strings.HasSuffix(base, ".go") {
@@ -454,7 +495,7 @@ func (p *Package) writeOutput(f *File, srcfile string) {
fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
conf.Fprint(fgo1, fset, f.AST)
- // While we process the vars and funcs, also write 6c and gcc output.
+ // While we process the vars and funcs, also write gcc output.
// Gcc output starts with the preamble.
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
fmt.Fprintf(fgcc, "%s\n", gccProlog)
@@ -516,7 +557,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
if n.AddError {
fmt.Fprintf(fgcc, "\terrno = 0;\n")
}
- // We're trying to write a gcc struct that matches 6c/8c/5c's layout.
+ // We're trying to write a gcc struct that matches gc's layout.
// Use packed attribute to force no padding in this struct in case
// gcc has different packing requirements.
fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
@@ -612,13 +653,13 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
}
// packedAttribute returns host compiler struct attribute that will be
-// used to match 6c/8c/5c's struct layout. For example, on 386 Windows,
-// gcc wants to 8-align int64s, but 8c does not.
+// used to match gc's struct layout. For example, on 386 Windows,
+// gcc wants to 8-align int64s, but gc does not.
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
-// and http://golang.org/issue/5603.
+// and https://golang.org/issue/5603.
func (p *Package) packedAttribute() string {
s := "__attribute__((__packed__"
- if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
+ if !p.GccIsClang && (goarch == "amd64" || goarch == "386") {
s += ", __gcc_struct__"
}
return s + "))"
@@ -626,23 +667,19 @@ func (p *Package) packedAttribute() string {
// 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(*objDir + "_cgo_export.c")
- fgcch := creat(*objDir + "_cgo_export.h")
-
- fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
- fmt.Fprintf(fgcch, "%s\n", p.Preamble)
- fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
+func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
+ p.writeExportHeader(fgcch)
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
- fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
+ fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
- fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
+ fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int), void *, int);\n")
+ fmt.Fprintf(fgcc, "extern void _cgo_wait_runtime_init_done();\n\n")
for _, exp := range p.ExpFunc {
fn := exp.Func
- // Construct a gcc struct matching the 6c argument and
+ // Construct a gcc struct matching the gc argument and
// result frame. The gcc struct will be compiled with
// __attribute__((packed)) so all padding must be accounted
// for explicitly.
@@ -728,11 +765,16 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
})
s += ")"
+
+ if len(exp.Doc) > 0 {
+ fmt.Fprintf(fgcch, "\n%s", exp.Doc)
+ }
fmt.Fprintf(fgcch, "\nextern %s;\n", s)
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgcc, "\n%s\n", s)
fmt.Fprintf(fgcc, "{\n")
+ fmt.Fprintf(fgcc, "\t_cgo_wait_runtime_init_done();\n")
fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
@@ -758,20 +800,21 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
}
fmt.Fprintf(fgcc, "}\n")
- // Build the wrapper function compiled by 6c/8c
+ // Build the wrapper function compiled by gc.
goname := exp.Func.Name.Name
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
- fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
- fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
- fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
- fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
- fmt.Fprintf(fc, "void\n")
- fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
- fmt.Fprintf(fc, "{\n")
- fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
- fmt.Fprintf(fc, "}\n")
+ fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
+ fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
+ fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
+ fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
+ // The indirect here is converting from a Go function pointer to a C function pointer.
+ fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
+ fmt.Fprintf(fgo2, "}\n")
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
@@ -814,23 +857,20 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, "}\n")
}
}
+
+ fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
}
// Write out the C header allowing C code to call exported gccgo functions.
-func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
- fgcc := creat(*objDir + "_cgo_export.c")
- fgcch := creat(*objDir + "_cgo_export.h")
-
+func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
- fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
- fmt.Fprintf(fgcch, "%s\n", p.Preamble)
- fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
+ p.writeExportHeader(fgcch)
fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
- fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
+ fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
for _, exp := range p.ExpFunc {
fn := exp.Func
@@ -851,6 +891,7 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
})
default:
// Declare a result struct.
+ fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
forFieldList(fntype.Results,
func(i int, atype ast.Expr) {
@@ -880,6 +921,10 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprintf(cdeclBuf, ")")
cParams := cdeclBuf.String()
+ if len(exp.Doc) > 0 {
+ fmt.Fprintf(fgcch, "\n%s", exp.Doc)
+ }
+
// We need to use a name that will be exported by the
// Go code; otherwise gccgo will make it static and we
// will not be able to link against it from the C
@@ -900,6 +945,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "\n")
fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
+ fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
+ fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
fmt.Fprint(fgcc, "\t")
if resultCount > 0 {
fmt.Fprint(fgcc, "return ")
@@ -919,7 +966,8 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgcc, "}\n")
// Dummy declaration for _cgo_main.c
- fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
+ fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
+ fmt.Fprint(fm, "\n")
// For gccgo we use a wrapper function in Go, in order
// to call CgocallBack and CgocallBackDone.
@@ -974,6 +1022,24 @@ func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
fmt.Fprint(fgo2, ")\n")
fmt.Fprint(fgo2, "}\n")
}
+
+ fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
+}
+
+// writeExportHeader writes out the start of the _cgo_export.h file.
+func (p *Package) writeExportHeader(fgcch io.Writer) {
+ fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n")
+ pkg := *importPath
+ if pkg == "" {
+ pkg = p.PackagePath
+ }
+ fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg)
+
+ fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments. */\n\n")
+ fmt.Fprintf(fgcch, "%s\n", p.Preamble)
+ fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments. */\n\n")
+
+ fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
}
// Return the package prefix when using gccgo.
@@ -1164,60 +1230,39 @@ char *CString(_GoString_);
void *_CMalloc(size_t);
`
-const cProlog = `
-#include "runtime.h"
-#include "cgocall.h"
-#include "textflag.h"
-
-#pragma dataflag NOPTR
-static void *cgocall_errno = runtime·cgocall_errno;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
-
-#pragma dataflag NOPTR
-static void *runtime_gostring = runtime·gostring;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostring = &runtime_gostring;
-
-#pragma dataflag NOPTR
-static void *runtime_gostringn = runtime·gostringn;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostringn = &runtime_gostringn;
-
-#pragma dataflag NOPTR
-static void *runtime_gobytes = runtime·gobytes;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gobytes = &runtime_gobytes;
-
-#pragma dataflag NOPTR
-static void *runtime_cmalloc = runtime·cmalloc;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
-
-void ·_Cerrno(void*, int32);
-`
-
const goProlog = `
-var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
-var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
+//go:linkname _cgo_runtime_cgocall runtime.cgocall
+func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
+
+//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
+func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
+
+//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
+func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
`
const goStringDef = `
-var _cgo_runtime_gostring func(*_Ctype_char) string
+//go:linkname _cgo_runtime_gostring runtime.gostring
+func _cgo_runtime_gostring(*_Ctype_char) string
+
func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p)
}
`
const goStringNDef = `
-var _cgo_runtime_gostringn func(*_Ctype_char, int) string
+//go:linkname _cgo_runtime_gostringn runtime.gostringn
+func _cgo_runtime_gostringn(*_Ctype_char, int) string
+
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l))
}
`
const goBytesDef = `
-var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
+//go:linkname _cgo_runtime_gobytes runtime.gobytes
+func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
+
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l))
}
@@ -1310,6 +1355,11 @@ func (p *Package) gccExportHeaderProlog() string {
}
const gccExportHeaderProlog = `
+/* Start of boilerplate cgo prologue. */
+
+#ifndef GO_CGO_PROLOGUE_H
+#define GO_CGO_PROLOGUE_H
+
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
@@ -1326,9 +1376,44 @@ typedef double GoFloat64;
typedef __complex float GoComplex64;
typedef __complex double GoComplex128;
+// static assertion to make sure the file is being used on architecture
+// at least with matching size of GoInt.
+typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];
+
typedef struct { char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
+
+#endif
+
+/* End of boilerplate cgo prologue. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+`
+
+// gccExportHeaderEpilog goes at the end of the generated header file.
+const gccExportHeaderEpilog = `
+#ifdef __cplusplus
+}
+#endif
+`
+
+// gccgoExportFileProlog is written to the _cgo_export.c file when
+// using gccgo.
+// We use weak declarations, and test the addresses, so that this code
+// works with older versions of gccgo.
+const gccgoExportFileProlog = `
+extern _Bool runtime_iscgo __attribute__ ((weak));
+
+static void GoInit(void) __attribute__ ((constructor));
+static void GoInit(void) {
+ if(&runtime_iscgo)
+ runtime_iscgo = 1;
+}
+
+extern void _cgo_wait_runtime_init_done() __attribute__ ((weak));
`
OpenPOWER on IntegriCloud