]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] cmd/cgo: generate only Go source files
authorRuss Cox <rsc@golang.org>
Tue, 11 Nov 2014 06:23:19 +0000 (01:23 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 11 Nov 2014 06:23:19 +0000 (01:23 -0500)
[This CL is part of the removal of C code from package runtime.
See golang.org/s/dev.cc for an overview.]

We changed cgo to write the actual function wrappers in Go
for Go 1.4. The only code left in C output files was the definitions
for pointers to C data and the #pragma cgo directives.
Write both of those to Go outputs instead, using the new
compiler directives introduced in CL 169360043.

(Still generating C files in gccgo mode.)

LGTM=r
R=r
CC=austin, golang-codereviews, iant, khr
https://golang.org/cl/169330045

src/cmd/cgo/main.go
src/cmd/cgo/out.go

index 17b0cdd167019cb2fa2f8f7df040755a6247074c..884f702c42cc7bba27b3f622197289933aa011fa 100644 (file)
@@ -147,6 +147,7 @@ var fset = token.NewFileSet()
 
 var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
 var dynout = flag.String("dynout", "", "write -dynobj output to this file")
+var dynpackage = flag.String("dynpackage", "main", "set Go package for dynobj output")
 var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
 
 // These flags are for bootstrapping a new Go implementation,
index d92bed9bf014ca9268eb8d970a08c193bd911031..78ecfd3974a0df92534fe76a4334b07176d8eb90 100644 (file)
@@ -13,6 +13,7 @@ import (
        "go/ast"
        "go/printer"
        "go/token"
+       "io"
        "os"
        "sort"
        "strings"
@@ -23,8 +24,15 @@ 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.)
 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 +42,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)
                        }
                }
        }
@@ -88,7 +96,6 @@ func (p *Package) writeDefs() {
        if *gccgo {
                fmt.Fprint(fc, p.cPrologGccgo())
        } else {
-               fmt.Fprint(fc, cProlog)
                fmt.Fprint(fgo2, goProlog)
        }
 
@@ -104,42 +111,42 @@ 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(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]
@@ -169,9 +176,6 @@ func (p *Package) writeDefs() {
                fmt.Fprint(fc, init)
                fmt.Fprintln(fc, "}")
        }
-
-       fgo2.Close()
-       fc.Close()
 }
 
 func dynimport(obj string) {
@@ -184,13 +188,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 +209,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 +230,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 +250,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
        }
@@ -304,7 +310,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(fc, fgo2 io.Writer, n *Name) {
        name := n.Go
        gtype := n.FuncType.Go
        void := gtype.Results == nil || len(gtype.Results.List) == 0
@@ -397,10 +403,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
        }
 
        // 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)
+       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 +418,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")
 
@@ -626,7 +631,7 @@ 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) {
+func (p *Package) writeExports(fgo2, fc, fm io.Writer) {
        fgcc := creat(*objDir + "_cgo_export.c")
        fgcch := creat(*objDir + "_cgo_export.h")
 
@@ -763,15 +768,15 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
                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, "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)
 
@@ -817,7 +822,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
 }
 
 // Write out the C header allowing C code to call exported gccgo functions.
-func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
+func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) {
        fgcc := creat(*objDir + "_cgo_export.c")
        fgcch := creat(*objDir + "_cgo_export.h")
 
@@ -1164,60 +1169,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_errno runtime.cgocall_errno
+func _cgo_runtime_cgocall_errno(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))
 }