diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index bfbcf50dc7..2a012177b3 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -257,23 +257,46 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { Name: ast.NewIdent(n.Mangle), Type: gtype, } - conf.Fprint(fgo2, fset, d) + if *gccgo { - fmt.Fprintf(fgo2, " __asm__(\"%s\")\n", n.C) - } else { - fmt.Fprintf(fgo2, "\n") + // Gccgo style hooks. + // we hook directly into C. gccgo goes not support cgocall yet. + if !n.AddError { + fmt.Fprintf(fgo2, "//extern %s\n", n.C) + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, "\n") + } else { + // write a small wrapper to retrieve errno. + cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) + paramnames := []string(nil) + for i, param := range d.Type.Params.List { + paramName := fmt.Sprintf("p%d", i) + param.Names = []*ast.Ident{ast.NewIdent(paramName)} + paramnames = append(paramnames, paramName) + } + conf.Fprint(fgo2, fset, d) + fmt.Fprintf(fgo2, "{\n") + fmt.Fprintf(fgo2, "\tr := %s(%s)\n", cname, strings.Join(paramnames, ", ")) + fmt.Fprintf(fgo2, "\treturn r, syscall.GetErrno()\n") + fmt.Fprintf(fgo2, "}\n") + // declare the C function. + fmt.Fprintf(fgo2, "//extern %s\n", n.C) + d.Name = ast.NewIdent(cname) + l := d.Type.Results.List + d.Type.Results.List = l[:len(l)-1] + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, "\n") + } + return } + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, "\n") if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" { // The builtins are already defined in the C prolog. return } - // gccgo does not require a wrapper unless an error must be returned. - if *gccgo && !n.AddError { - return - } - var argSize int64 _, argSize = p.structType(n) @@ -355,6 +378,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { } p.Written[name] = true + if *gccgo { + // we don't use wrappers with gccgo. + return + } + ctype, _ := p.structType(n) // Gcc wrapper unpacks the C argument struct @@ -783,7 +811,7 @@ struct __go_string __go_byte_array_to_string(const void* p, int len); struct __go_open_array __go_string_to_byte_array (struct __go_string str); const char *CString(struct __go_string s) { - return strndup(s.__data, s.__length); + return strndup((const char*)s.__data, s.__length); } struct __go_string GoString(char *p) { @@ -796,7 +824,7 @@ struct __go_string GoStringN(char *p, int n) { } Slice GoBytes(char *p, int n) { - struct __go_string s = { p, n }; + struct __go_string s = { (const unsigned char *)p, n }; return __go_string_to_byte_array(s); } ` diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index b8af30e370..e76c6fc2f5 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -1152,8 +1152,6 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, return nil, nil, errors.New("cannot use cgo when compiling for a different operating system") } - outObj = append(outObj, "") // for importObj, at end of function - cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.info.CgoCFLAGS) cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.info.CgoLDFLAGS) @@ -1238,6 +1236,11 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, return nil, nil, err } + if _, ok := buildToolchain.(gccgoToolchain); ok { + // we don't use dynimport when using gccgo. + return outGo, outObj, nil + } + // cgo -dynimport importC := obj + "_cgo_import.c" if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC); err != nil { @@ -1252,8 +1255,8 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows // must be processed before the gcc-generated objects. - // Put it first. We left room above. http://golang.org/issue/2601 - outObj[0] = importObj + // Put it first. http://golang.org/issue/2601 + outObj = append([]string{importObj}, outObj...) return outGo, outObj, nil }