diff options
Diffstat (limited to 'libgo/go/cmd/cgo/out.go')
-rw-r--r-- | libgo/go/cmd/cgo/out.go | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go index 50e57157793..f44da9c8b12 100644 --- a/libgo/go/cmd/cgo/out.go +++ b/libgo/go/cmd/cgo/out.go @@ -9,11 +9,11 @@ import ( "debug/elf" "debug/macho" "debug/pe" - "debug/xcoff" "fmt" "go/ast" "go/printer" "go/token" + "internal/xcoff" "io" "io/ioutil" "os" @@ -251,7 +251,22 @@ func (p *Package) writeDefs() { init := gccgoInit.String() if init != "" { - fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));") + // The init function does nothing but simple + // assignments, so it won't use much stack space, so + // it's OK to not split the stack. Splitting the stack + // can run into a bug in clang (as of 2018-11-09): + // this is a leaf function, and when clang sees a leaf + // function it won't emit the split stack prologue for + // the function. However, if this function refers to a + // non-split-stack function, which will happen if the + // cgo code refers to a C function not compiled with + // -fsplit-stack, then the linker will think that it + // needs to adjust the split stack prologue, but there + // won't be one. Marking the function explicitly + // no_split_stack works around this problem by telling + // the linker that it's OK if there is no split stack + // prologue. + fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor, no_split_stack));") fmt.Fprintln(fc, "static void init(void) {") fmt.Fprint(fc, init) fmt.Fprintln(fc, "}") @@ -1193,7 +1208,7 @@ func (p *Package) writeExportHeader(fgcch io.Writer) { fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) } -// gccgoUsesNewMangling returns whether gccgo uses the new collision-free +// gccgoUsesNewMangling reports whether gccgo uses the new collision-free // packagepath mangling scheme (see determineGccgoManglingScheme for more // info). func gccgoUsesNewMangling() bool { @@ -1545,6 +1560,7 @@ const builtinProlog = ` /* Define intgo when compiling with GCC. */ typedef ptrdiff_t intgo; +#define GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; intgo n; } _GoString_; typedef struct { char *p; intgo n; intgo c; } _GoBytes_; _GoString_ GoString(char *p); @@ -1555,7 +1571,7 @@ void *CBytes(_GoBytes_); void *_CMalloc(size_t); __attribute__ ((unused)) -static size_t _GoStringLen(_GoString_ s) { return s.n; } +static size_t _GoStringLen(_GoString_ s) { return (size_t)s.n; } __attribute__ ((unused)) static const char *_GoStringPtr(_GoString_ s) { return s.p; } @@ -1796,15 +1812,20 @@ void localCgoCheckResult(Eface val) { // because _cgo_export.h defines GoString as a struct while builtinProlog // defines it as a function. We don't change this to avoid unnecessarily // breaking existing code. +// The test of GO_CGO_GOSTRING_TYPEDEF avoids a duplicate definition +// error if a Go file with a cgo comment #include's the export header +// generated by a different package. const builtinExportProlog = ` -#line 1 "cgo-builtin-prolog" +#line 1 "cgo-builtin-export-prolog" #include <stddef.h> /* for ptrdiff_t below */ #ifndef GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H +#ifndef GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif #endif ` @@ -1813,6 +1834,19 @@ func (p *Package) gccExportHeaderProlog() string { return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1) } +// gccExportHeaderProlog is written to the exported header, after the +// import "C" comment preamble but before the generated declarations +// of exported functions. This permits the generated declarations to +// use the type names that appear in goTypes, above. +// +// The test of GO_CGO_GOSTRING_TYPEDEF avoids a duplicate definition +// error if a Go file with a cgo comment #include's the export header +// generated by a different package. Unfortunately GoString means two +// different things: in this prolog it means a C name for the Go type, +// while in the prolog written into the start of the C code generated +// from a cgo-using Go file it means the C.GoString function. There is +// no way to resolve this conflict, but it also doesn't make much +// difference, as Go code never wants to refer to the latter meaning. const gccExportHeaderProlog = ` /* Start of boilerplate cgo prologue. */ #line 1 "cgo-gcc-export-header-prolog" @@ -1842,7 +1876,9 @@ typedef double _Complex GoComplex128; */ typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1]; +#ifndef GO_CGO_GOSTRING_TYPEDEF typedef _GoString_ GoString; +#endif typedef void *GoMap; typedef void *GoChan; typedef struct { void *t; void *v; } GoInterface; |