]> Cypherpunks repositories - gostls13.git/commitdiff
cgo: add support for returning errno with gccgo.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 14 Feb 2012 19:23:45 +0000 (20:23 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Tue, 14 Feb 2012 19:23:45 +0000 (20:23 +0100)
Also eliminate some warnings in builds.

R=golang-dev, fullung, iant, rsc
CC=golang-dev, remy
https://golang.org/cl/5650066

src/cmd/cgo/out.go
src/cmd/go/build.go

index bfbcf50dc72172d2f2bdec4979cda5bb2a6ae409..2a012177b36fb8ef72d72c5d63301fcd7428351b 100644 (file)
@@ -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);
 }
 `
index b8af30e370b61b51db3b3555c77518ad8aa5c960..e76c6fc2f57e7df8f3ebc464e8930b3290bf33a5 100644 (file)
@@ -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
 }