aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/cmd/cgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2015-01-06 23:26:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-06 23:26:02 +0000
commit7d7d64c1ae3c0732b167d2050b101808f078d711 (patch)
tree40ecf33efd29feac369ae050140bc3fefed352e9 /libgo/go/cmd/cgo
parentefcdb22fe3288fbfa4cd8ba9554b3a561c4d6e08 (diff)
downloadgcc-7d7d64c1ae3c0732b167d2050b101808f078d711.zip
gcc-7d7d64c1ae3c0732b167d2050b101808f078d711.tar.gz
gcc-7d7d64c1ae3c0732b167d2050b101808f078d711.tar.bz2
libgo: Add sources for go, cgo, and gofmt commands.
The new commands are not yet built. That will be done separately. Also include a few changes to go/build to support them. From-SVN: r219272
Diffstat (limited to 'libgo/go/cmd/cgo')
-rw-r--r--libgo/go/cmd/cgo/ast.go460
-rw-r--r--libgo/go/cmd/cgo/doc.go748
-rw-r--r--libgo/go/cmd/cgo/gcc.go1728
-rw-r--r--libgo/go/cmd/cgo/godefs.go294
-rw-r--r--libgo/go/cmd/cgo/main.go360
-rw-r--r--libgo/go/cmd/cgo/out.go1299
-rw-r--r--libgo/go/cmd/cgo/util.go84
7 files changed, 4973 insertions, 0 deletions
diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go
new file mode 100644
index 0000000..7757efa
--- /dev/null
+++ b/libgo/go/cmd/cgo/ast.go
@@ -0,0 +1,460 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Parse input AST and prepare Prog structure.
+
+package main
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/scanner"
+ "go/token"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func parse(name string, flags parser.Mode) *ast.File {
+ ast1, err := parser.ParseFile(fset, name, nil, flags)
+ if err != nil {
+ if list, ok := err.(scanner.ErrorList); ok {
+ // If err is a scanner.ErrorList, its String will print just
+ // the first error and then (+n more errors).
+ // Instead, turn it into a new Error that will return
+ // details for all the errors.
+ for _, e := range list {
+ fmt.Fprintln(os.Stderr, e)
+ }
+ os.Exit(2)
+ }
+ fatalf("parsing %s: %s", name, err)
+ }
+ return ast1
+}
+
+func sourceLine(n ast.Node) int {
+ return fset.Position(n.Pos()).Line
+}
+
+// ReadGo populates f with information learned from reading the
+// Go source file with the given file name. It gathers the C preamble
+// attached to the import "C" comment, a list of references to C.xxx,
+// a list of exported functions, and the actual AST, to be rewritten and
+// printed.
+func (f *File) ReadGo(name string) {
+ // Create absolute path for file, so that it will be used in error
+ // messages and recorded in debug line number information.
+ // This matches the rest of the toolchain. See golang.org/issue/5122.
+ if aname, err := filepath.Abs(name); err == nil {
+ name = aname
+ }
+
+ // Two different parses: once with comments, once without.
+ // The printer is not good enough at printing comments in the
+ // right place when we start editing the AST behind its back,
+ // so we use ast1 to look for the doc comments on import "C"
+ // and on exported functions, and we use ast2 for translating
+ // and reprinting.
+ ast1 := parse(name, parser.ParseComments)
+ ast2 := parse(name, 0)
+
+ f.Package = ast1.Name.Name
+ f.Name = make(map[string]*Name)
+
+ // In ast1, find the import "C" line and get any extra C preamble.
+ sawC := false
+ for _, decl := range ast1.Decls {
+ d, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
+ }
+ for _, spec := range d.Specs {
+ s, ok := spec.(*ast.ImportSpec)
+ if !ok || string(s.Path.Value) != `"C"` {
+ continue
+ }
+ sawC = true
+ if s.Name != nil {
+ error_(s.Path.Pos(), `cannot rename import "C"`)
+ }
+ cg := s.Doc
+ if cg == nil && len(d.Specs) == 1 {
+ cg = d.Doc
+ }
+ if cg != nil {
+ f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
+ f.Preamble += commentText(cg) + "\n"
+ }
+ }
+ }
+ if !sawC {
+ error_(token.NoPos, `cannot find import "C"`)
+ }
+
+ // In ast2, strip the import "C" line.
+ w := 0
+ for _, decl := range ast2.Decls {
+ d, ok := decl.(*ast.GenDecl)
+ if !ok {
+ ast2.Decls[w] = decl
+ w++
+ continue
+ }
+ ws := 0
+ for _, spec := range d.Specs {
+ s, ok := spec.(*ast.ImportSpec)
+ if !ok || string(s.Path.Value) != `"C"` {
+ d.Specs[ws] = spec
+ ws++
+ }
+ }
+ if ws == 0 {
+ continue
+ }
+ d.Specs = d.Specs[0:ws]
+ ast2.Decls[w] = d
+ w++
+ }
+ ast2.Decls = ast2.Decls[0:w]
+
+ // Accumulate pointers to uses of C.x.
+ if f.Ref == nil {
+ f.Ref = make([]*Ref, 0, 8)
+ }
+ f.walk(ast2, "prog", (*File).saveRef)
+
+ // Accumulate exported functions.
+ // The comments are only on ast1 but we need to
+ // save the function bodies from ast2.
+ // The first walk fills in ExpFunc, and the
+ // second walk changes the entries to
+ // refer to ast2 instead.
+ f.walk(ast1, "prog", (*File).saveExport)
+ f.walk(ast2, "prog", (*File).saveExport2)
+
+ f.Comments = ast1.Comments
+ f.AST = ast2
+}
+
+// Like ast.CommentGroup's Text method but preserves
+// leading blank lines, so that line numbers line up.
+func commentText(g *ast.CommentGroup) string {
+ if g == nil {
+ return ""
+ }
+ var pieces []string
+ for _, com := range g.List {
+ c := string(com.Text)
+ // Remove comment markers.
+ // The parser has given us exactly the comment text.
+ switch c[1] {
+ case '/':
+ //-style comment (no newline at the end)
+ c = c[2:] + "\n"
+ case '*':
+ /*-style comment */
+ c = c[2 : len(c)-2]
+ }
+ pieces = append(pieces, c)
+ }
+ return strings.Join(pieces, "")
+}
+
+// Save references to C.xxx for later processing.
+func (f *File) saveRef(x interface{}, context string) {
+ n, ok := x.(*ast.Expr)
+ if !ok {
+ return
+ }
+ if sel, ok := (*n).(*ast.SelectorExpr); ok {
+ // For now, assume that the only instance of capital C is
+ // when used as the imported package identifier.
+ // The parser should take care of scoping in the future,
+ // so that we will be able to distinguish a "top-level C"
+ // from a local C.
+ if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
+ if context == "as2" {
+ context = "expr"
+ }
+ if context == "embed-type" {
+ error_(sel.Pos(), "cannot embed C type")
+ }
+ goname := sel.Sel.Name
+ if goname == "errno" {
+ error_(sel.Pos(), "cannot refer to errno directly; see documentation")
+ return
+ }
+ if goname == "_CMalloc" {
+ error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
+ return
+ }
+ if goname == "malloc" {
+ goname = "_CMalloc"
+ }
+ name := f.Name[goname]
+ if name == nil {
+ name = &Name{
+ Go: goname,
+ }
+ f.Name[goname] = name
+ }
+ f.Ref = append(f.Ref, &Ref{
+ Name: name,
+ Expr: n,
+ Context: context,
+ })
+ return
+ }
+ }
+}
+
+// If a function should be exported add it to ExpFunc.
+func (f *File) saveExport(x interface{}, context string) {
+ n, ok := x.(*ast.FuncDecl)
+ if !ok {
+ return
+ }
+
+ if n.Doc == nil {
+ return
+ }
+ for _, c := range n.Doc.List {
+ if !strings.HasPrefix(string(c.Text), "//export ") {
+ continue
+ }
+
+ name := strings.TrimSpace(string(c.Text[9:]))
+ if name == "" {
+ error_(c.Pos(), "export missing name")
+ }
+
+ if name != n.Name.Name {
+ error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
+ }
+
+ f.ExpFunc = append(f.ExpFunc, &ExpFunc{
+ Func: n,
+ ExpName: name,
+ })
+ break
+ }
+}
+
+// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
+func (f *File) saveExport2(x interface{}, context string) {
+ n, ok := x.(*ast.FuncDecl)
+ if !ok {
+ return
+ }
+
+ for _, exp := range f.ExpFunc {
+ if exp.Func.Name.Name == n.Name.Name {
+ exp.Func = n
+ break
+ }
+ }
+}
+
+// walk walks the AST x, calling visit(f, x, context) for each node.
+func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
+ visit(f, x, context)
+ switch n := x.(type) {
+ case *ast.Expr:
+ f.walk(*n, context, visit)
+
+ // everything else just recurs
+ default:
+ error_(token.NoPos, "unexpected type %T in walk", x, visit)
+ panic("unexpected type")
+
+ case nil:
+
+ // These are ordered and grouped to match ../../pkg/go/ast/ast.go
+ case *ast.Field:
+ if len(n.Names) == 0 && context == "field" {
+ f.walk(&n.Type, "embed-type", visit)
+ } else {
+ f.walk(&n.Type, "type", visit)
+ }
+ case *ast.FieldList:
+ for _, field := range n.List {
+ f.walk(field, context, visit)
+ }
+ case *ast.BadExpr:
+ case *ast.Ident:
+ case *ast.Ellipsis:
+ case *ast.BasicLit:
+ case *ast.FuncLit:
+ f.walk(n.Type, "type", visit)
+ f.walk(n.Body, "stmt", visit)
+ case *ast.CompositeLit:
+ f.walk(&n.Type, "type", visit)
+ f.walk(n.Elts, "expr", visit)
+ case *ast.ParenExpr:
+ f.walk(&n.X, context, visit)
+ case *ast.SelectorExpr:
+ f.walk(&n.X, "selector", visit)
+ case *ast.IndexExpr:
+ f.walk(&n.X, "expr", visit)
+ f.walk(&n.Index, "expr", visit)
+ case *ast.SliceExpr:
+ f.walk(&n.X, "expr", visit)
+ if n.Low != nil {
+ f.walk(&n.Low, "expr", visit)
+ }
+ if n.High != nil {
+ f.walk(&n.High, "expr", visit)
+ }
+ case *ast.TypeAssertExpr:
+ f.walk(&n.X, "expr", visit)
+ f.walk(&n.Type, "type", visit)
+ case *ast.CallExpr:
+ if context == "as2" {
+ f.walk(&n.Fun, "call2", visit)
+ } else {
+ f.walk(&n.Fun, "call", visit)
+ }
+ f.walk(n.Args, "expr", visit)
+ case *ast.StarExpr:
+ f.walk(&n.X, context, visit)
+ case *ast.UnaryExpr:
+ f.walk(&n.X, "expr", visit)
+ case *ast.BinaryExpr:
+ f.walk(&n.X, "expr", visit)
+ f.walk(&n.Y, "expr", visit)
+ case *ast.KeyValueExpr:
+ f.walk(&n.Key, "expr", visit)
+ f.walk(&n.Value, "expr", visit)
+
+ case *ast.ArrayType:
+ f.walk(&n.Len, "expr", visit)
+ f.walk(&n.Elt, "type", visit)
+ case *ast.StructType:
+ f.walk(n.Fields, "field", visit)
+ case *ast.FuncType:
+ f.walk(n.Params, "param", visit)
+ if n.Results != nil {
+ f.walk(n.Results, "param", visit)
+ }
+ case *ast.InterfaceType:
+ f.walk(n.Methods, "field", visit)
+ case *ast.MapType:
+ f.walk(&n.Key, "type", visit)
+ f.walk(&n.Value, "type", visit)
+ case *ast.ChanType:
+ f.walk(&n.Value, "type", visit)
+
+ case *ast.BadStmt:
+ case *ast.DeclStmt:
+ f.walk(n.Decl, "decl", visit)
+ case *ast.EmptyStmt:
+ case *ast.LabeledStmt:
+ f.walk(n.Stmt, "stmt", visit)
+ case *ast.ExprStmt:
+ f.walk(&n.X, "expr", visit)
+ case *ast.SendStmt:
+ f.walk(&n.Chan, "expr", visit)
+ f.walk(&n.Value, "expr", visit)
+ case *ast.IncDecStmt:
+ f.walk(&n.X, "expr", visit)
+ case *ast.AssignStmt:
+ f.walk(n.Lhs, "expr", visit)
+ if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
+ f.walk(n.Rhs, "as2", visit)
+ } else {
+ f.walk(n.Rhs, "expr", visit)
+ }
+ case *ast.GoStmt:
+ f.walk(n.Call, "expr", visit)
+ case *ast.DeferStmt:
+ f.walk(n.Call, "expr", visit)
+ case *ast.ReturnStmt:
+ f.walk(n.Results, "expr", visit)
+ case *ast.BranchStmt:
+ case *ast.BlockStmt:
+ f.walk(n.List, context, visit)
+ case *ast.IfStmt:
+ f.walk(n.Init, "stmt", visit)
+ f.walk(&n.Cond, "expr", visit)
+ f.walk(n.Body, "stmt", visit)
+ f.walk(n.Else, "stmt", visit)
+ case *ast.CaseClause:
+ if context == "typeswitch" {
+ context = "type"
+ } else {
+ context = "expr"
+ }
+ f.walk(n.List, context, visit)
+ f.walk(n.Body, "stmt", visit)
+ case *ast.SwitchStmt:
+ f.walk(n.Init, "stmt", visit)
+ f.walk(&n.Tag, "expr", visit)
+ f.walk(n.Body, "switch", visit)
+ case *ast.TypeSwitchStmt:
+ f.walk(n.Init, "stmt", visit)
+ f.walk(n.Assign, "stmt", visit)
+ f.walk(n.Body, "typeswitch", visit)
+ case *ast.CommClause:
+ f.walk(n.Comm, "stmt", visit)
+ f.walk(n.Body, "stmt", visit)
+ case *ast.SelectStmt:
+ f.walk(n.Body, "stmt", visit)
+ case *ast.ForStmt:
+ f.walk(n.Init, "stmt", visit)
+ f.walk(&n.Cond, "expr", visit)
+ f.walk(n.Post, "stmt", visit)
+ f.walk(n.Body, "stmt", visit)
+ case *ast.RangeStmt:
+ f.walk(&n.Key, "expr", visit)
+ f.walk(&n.Value, "expr", visit)
+ f.walk(&n.X, "expr", visit)
+ f.walk(n.Body, "stmt", visit)
+
+ case *ast.ImportSpec:
+ case *ast.ValueSpec:
+ f.walk(&n.Type, "type", visit)
+ f.walk(n.Values, "expr", visit)
+ case *ast.TypeSpec:
+ f.walk(&n.Type, "type", visit)
+
+ case *ast.BadDecl:
+ case *ast.GenDecl:
+ f.walk(n.Specs, "spec", visit)
+ case *ast.FuncDecl:
+ if n.Recv != nil {
+ f.walk(n.Recv, "param", visit)
+ }
+ f.walk(n.Type, "type", visit)
+ if n.Body != nil {
+ f.walk(n.Body, "stmt", visit)
+ }
+
+ case *ast.File:
+ f.walk(n.Decls, "decl", visit)
+
+ case *ast.Package:
+ for _, file := range n.Files {
+ f.walk(file, "file", visit)
+ }
+
+ case []ast.Decl:
+ for _, d := range n {
+ f.walk(d, context, visit)
+ }
+ case []ast.Expr:
+ for i := range n {
+ f.walk(&n[i], context, visit)
+ }
+ case []ast.Stmt:
+ for _, s := range n {
+ f.walk(s, context, visit)
+ }
+ case []ast.Spec:
+ for _, s := range n {
+ f.walk(s, context, visit)
+ }
+ }
+}
diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go
new file mode 100644
index 0000000..69c7ce8
--- /dev/null
+++ b/libgo/go/cmd/cgo/doc.go
@@ -0,0 +1,748 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Cgo enables the creation of Go packages that call C code.
+
+Using cgo with the go command
+
+To use cgo write normal Go code that imports a pseudo-package "C".
+The Go code can then refer to types such as C.size_t, variables such
+as C.stdout, or functions such as C.putchar.
+
+If the import of "C" is immediately preceded by a comment, that
+comment, called the preamble, is used as a header when compiling
+the C parts of the package. For example:
+
+ // #include <stdio.h>
+ // #include <errno.h>
+ import "C"
+
+See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
+"C? Go? Cgo!" for an introduction to using cgo:
+http://golang.org/doc/articles/c_go_cgo.html.
+
+CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo
+directives within these comments to tweak the behavior of the C or C++
+compiler. Values defined in multiple directives are concatenated
+together. The directive can include a list of build constraints limiting its
+effect to systems satisfying one of the constraints
+(see http://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
+For example:
+
+ // #cgo CFLAGS: -DPNG_DEBUG=1
+ // #cgo amd64 386 CFLAGS: -DX86=1
+ // #cgo LDFLAGS: -lpng
+ // #include <png.h>
+ import "C"
+
+Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config
+tool using a '#cgo pkg-config:' directive followed by the package names.
+For example:
+
+ // #cgo pkg-config: png cairo
+ // #include <png.h>
+ import "C"
+
+When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS and
+CGO_LDFLAGS environment variables are added to the flags derived from
+these directives. Package-specific flags should be set using the
+directives, not the environment variables, so that builds work in
+unmodified environments.
+
+All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
+used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
+directives in a package are concatenated and used to compile C++ files in that
+package. All the LDFLAGS directives in any package in the program are
+concatenated and used at link time. All the pkg-config directives are
+concatenated and sent to pkg-config simultaneously to add to each appropriate
+set of command-line flags.
+
+When the Go tool sees that one or more Go files use the special import
+"C", it will look for other non-Go files in the directory and compile
+them as part of the Go package. Any .c, .s, or .S files will be
+compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
+compiled with the C++ compiler. Any .h, .hh, .hpp, or .hxx files will
+not be compiled separately, but, if these header files are changed,
+the C and C++ files will be recompiled. The default C and C++
+compilers may be changed by the CC and CXX environment variables,
+respectively; those environment variables may include command line
+options.
+
+To enable cgo during cross compiling builds, set the CGO_ENABLED
+environment variable to 1 when building the Go tools with make.bash.
+Also, set CC_FOR_TARGET to the C cross compiler for the target. CC will
+be used for compiling for the host.
+
+After the Go tools are built, when running the go command, CC_FOR_TARGET is
+ignored. The value of CC_FOR_TARGET when running make.bash is the default
+compiler. However, you can set the environment variable CC, not CC_FOR_TARGET,
+to control the compiler when running the go tool.
+
+CXX_FOR_TARGET works in a similar way for C++ code.
+
+Go references to C
+
+Within the Go file, C's struct field names that are keywords in Go
+can be accessed by prefixing them with an underscore: if x points at a C
+struct with a field named "type", x._type accesses the field.
+C struct fields that cannot be expressed in Go, such as bit fields
+or misaligned data, are omitted in the Go struct, replaced by
+appropriate padding to reach the next field or the end of the struct.
+
+The standard C numeric types are available under the names
+C.char, C.schar (signed char), C.uchar (unsigned char),
+C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int),
+C.long, C.ulong (unsigned long), C.longlong (long long),
+C.ulonglong (unsigned long long), C.float, C.double.
+The C type void* is represented by Go's unsafe.Pointer.
+
+To access a struct, union, or enum type directly, prefix it with
+struct_, union_, or enum_, as in C.struct_stat.
+
+As Go doesn't have support for C's union type in the general case,
+C's union types are represented as a Go byte array with the same length.
+
+Go structs cannot embed fields with C types.
+
+Cgo translates C types into equivalent unexported Go types.
+Because the translations are unexported, a Go package should not
+expose C types in its exported API: a C type used in one Go package
+is different from the same C type used in another.
+
+Any C function (even void functions) may be called in a multiple
+assignment context to retrieve both the return value (if any) and the
+C errno variable as an error (use _ to skip the result value if the
+function returns void). For example:
+
+ n, err := C.sqrt(-1)
+ _, err := C.voidFunc()
+
+Calling C function pointers is currently not supported, however you can
+declare Go variables which hold C function pointers and pass them
+back and forth between Go and C. C code may call function pointers
+received from Go. For example:
+
+ package main
+
+ // typedef int (*intFunc) ();
+ //
+ // int
+ // bridge_int_func(intFunc f)
+ // {
+ // return f();
+ // }
+ //
+ // int fortytwo()
+ // {
+ // return 42;
+ // }
+ import "C"
+ import "fmt"
+
+ func main() {
+ f := C.intFunc(C.fortytwo)
+ fmt.Println(int(C.bridge_int_func(f)))
+ // Output: 42
+ }
+
+In C, a function argument written as a fixed size array
+actually requires a pointer to the first element of the array.
+C compilers are aware of this calling convention and adjust
+the call accordingly, but Go cannot. In Go, you must pass
+the pointer to the first element explicitly: C.f(&x[0]).
+
+A few special functions convert between Go and C types
+by making copies of the data. In pseudo-Go definitions:
+
+ // Go string to C string
+ // The C string is allocated in the C heap using malloc.
+ // It is the caller's responsibility to arrange for it to be
+ // freed, such as by calling C.free (be sure to include stdlib.h
+ // if C.free is needed).
+ func C.CString(string) *C.char
+
+ // C string to Go string
+ func C.GoString(*C.char) string
+
+ // C string, length to Go string
+ func C.GoStringN(*C.char, C.int) string
+
+ // C pointer, length to Go []byte
+ func C.GoBytes(unsafe.Pointer, C.int) []byte
+
+C references to Go
+
+Go functions can be exported for use by C code in the following way:
+
+ //export MyFunction
+ func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
+
+ //export MyFunction2
+ func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...}
+
+They will be available in the C code as:
+
+ extern int64 MyFunction(int arg1, int arg2, GoString arg3);
+ extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
+
+found in the _cgo_export.h generated header, after any preambles
+copied from the cgo input files. Functions with multiple
+return values are mapped to functions returning a struct.
+Not all Go types can be mapped to C types in a useful way.
+
+Using //export in a file places a restriction on the preamble:
+since it is copied into two different C output files, it must not
+contain any definitions, only declarations. Definitions must be
+placed in preambles in other files, or in C source files.
+
+Using cgo directly
+
+Usage:
+ go tool cgo [cgo options] [-- compiler options] file.go
+
+Cgo transforms the input file.go into four output files: two Go source
+files, a C file for 6c (or 8c or 5c), and a C file for gcc.
+
+The compiler options are passed through uninterpreted when
+invoking the C compiler to compile the C parts of the package.
+
+The following options are available when running cgo directly:
+
+ -dynimport file
+ Write list of symbols imported by file. Write to
+ -dynout argument or to standard output. Used by go
+ build when building a cgo package.
+ -dynout file
+ Write -dynimport output to file.
+ -dynlinker
+ Write dynamic linker as part of -dynimport output.
+ -godefs
+ Write out input file in Go syntax replacing C package
+ names with real values. Used to generate files in the
+ syscall package when bootstrapping a new target.
+ -cdefs
+ Like -godefs, but write file in C syntax.
+ Used to generate files in the runtime package when
+ bootstrapping a new target.
+ -objdir directory
+ Put all generated files in directory.
+ -gccgo
+ Generate output for the gccgo compiler rather than the
+ gc compiler.
+ -gccgoprefix prefix
+ The -fgo-prefix option to be used with gccgo.
+ -gccgopkgpath path
+ The -fgo-pkgpath option to be used with gccgo.
+ -import_runtime_cgo
+ If set (which it is by default) import runtime/cgo in
+ generated output.
+ -import_syscall
+ If set (which it is by default) import syscall in
+ generated output.
+ -debug-define
+ Debugging option. Print #defines.
+ -debug-gcc
+ Debugging option. Trace C compiler execution and output.
+*/
+package main
+
+/*
+Implementation details.
+
+Cgo provides a way for Go programs to call C code linked into the same
+address space. This comment explains the operation of cgo.
+
+Cgo reads a set of Go source files and looks for statements saying
+import "C". If the import has a doc comment, that comment is
+taken as literal C code to be used as a preamble to any C code
+generated by cgo. A typical preamble #includes necessary definitions:
+
+ // #include <stdio.h>
+ import "C"
+
+For more details about the usage of cgo, see the documentation
+comment at the top of this file.
+
+Understanding C
+
+Cgo scans the Go source files that import "C" for uses of that
+package, such as C.puts. It collects all such identifiers. The next
+step is to determine each kind of name. In C.xxx the xxx might refer
+to a type, a function, a constant, or a global variable. Cgo must
+decide which.
+
+The obvious thing for cgo to do is to process the preamble, expanding
+#includes and processing the corresponding C code. That would require
+a full C parser and type checker that was also aware of any extensions
+known to the system compiler (for example, all the GNU C extensions) as
+well as the system-specific header locations and system-specific
+pre-#defined macros. This is certainly possible to do, but it is an
+enormous amount of work.
+
+Cgo takes a different approach. It determines the meaning of C
+identifiers not by parsing C code but by feeding carefully constructed
+programs into the system C compiler and interpreting the generated
+error messages, debug information, and object files. In practice,
+parsing these is significantly less work and more robust than parsing
+C source.
+
+Cgo first invokes gcc -E -dM on the preamble, in order to find out
+about simple #defines for constants and the like. These are recorded
+for later use.
+
+Next, cgo needs to identify the kinds for each identifier. For the
+identifiers C.foo and C.bar, cgo generates this C program:
+
+ <preamble>
+ #line 1 "not-declared"
+ void __cgo_f_xxx_1(void) { __typeof__(foo) *__cgo_undefined__; }
+ #line 1 "not-type"
+ void __cgo_f_xxx_2(void) { foo *__cgo_undefined__; }
+ #line 1 "not-const"
+ void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (foo)*1 }; }
+ #line 2 "not-declared"
+ void __cgo_f_xxx_1(void) { __typeof__(bar) *__cgo_undefined__; }
+ #line 2 "not-type"
+ void __cgo_f_xxx_2(void) { bar *__cgo_undefined__; }
+ #line 2 "not-const"
+ void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (bar)*1 }; }
+
+This program will not compile, but cgo can use the presence or absence
+of an error message on a given line to deduce the information it
+needs. The program is syntactically valid regardless of whether each
+name is a type or an ordinary identifier, so there will be no syntax
+errors that might stop parsing early.
+
+An error on not-declared:1 indicates that foo is undeclared.
+An error on not-type:1 indicates that foo is not a type (if declared at all, it is an identifier).
+An error on not-const:1 indicates that foo is not an integer constant.
+
+The line number specifies the name involved. In the example, 1 is foo and 2 is bar.
+
+Next, cgo must learn the details of each type, variable, function, or
+constant. It can do this by reading object files. If cgo has decided
+that t1 is a type, v2 and v3 are variables or functions, and c4, c5,
+and c6 are constants, it generates:
+
+ <preamble>
+ __typeof__(t1) *__cgo__1;
+ __typeof__(v2) *__cgo__2;
+ __typeof__(v3) *__cgo__3;
+ __typeof__(c4) *__cgo__4;
+ enum { __cgo_enum__4 = c4 };
+ __typeof__(c5) *__cgo__5;
+ enum { __cgo_enum__5 = c5 };
+ __typeof__(c6) *__cgo__6;
+ enum { __cgo_enum__6 = c6 };
+
+ long long __cgo_debug_data[] = {
+ 0, // t1
+ 0, // v2
+ 0, // v3
+ c4,
+ c5,
+ c6,
+ 1
+ };
+
+and again invokes the system C compiler, to produce an object file
+containing debug information. Cgo parses the DWARF debug information
+for __cgo__N to learn the type of each identifier. (The types also
+distinguish functions from global variables.) If using a standard gcc,
+cgo can parse the DWARF debug information for the __cgo_enum__N to
+learn the identifier's value. The LLVM-based gcc on OS X emits
+incomplete DWARF information for enums; in that case cgo reads the
+constant values from the __cgo_debug_data from the object file's data
+segment.
+
+At this point cgo knows the meaning of each C.xxx well enough to start
+the translation process.
+
+Translating Go
+
+[The rest of this comment refers to 6g and 6c, the Go and C compilers
+that are part of the amd64 port of the gc Go toolchain. Everything here
+applies to another architecture's compilers as well.]
+
+Given the input Go files x.go and y.go, cgo generates these source
+files:
+
+ x.cgo1.go # for 6g
+ y.cgo1.go # for 6g
+ _cgo_gotypes.go # for 6g
+ _cgo_defun.c # for 6c
+ x.cgo2.c # for gcc
+ y.cgo2.c # for gcc
+ _cgo_export.c # for gcc
+ _cgo_main.c # for gcc
+
+The file x.cgo1.go is a copy of x.go with the import "C" removed and
+references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx.
+The definitions of those identifiers, written as Go functions, types,
+or variables, are provided in _cgo_gotypes.go.
+
+Here is a _cgo_gotypes.go containing definitions for C.flush (provided
+in the preamble) and C.puts (from stdio):
+
+ type _Ctype_char int8
+ type _Ctype_int int32
+ type _Ctype_void [0]byte
+
+ func _Cfunc_CString(string) *_Ctype_char
+ func _Cfunc_flush() _Ctype_void
+ func _Cfunc_puts(*_Ctype_char) _Ctype_int
+
+For functions, cgo only writes an external declaration in the Go
+output. The implementation is in a combination of C for 6c (meaning
+any gc-toolchain compiler) and C for gcc.
+
+The 6c file contains the definitions of the functions. They all have
+similar bodies that invoke runtime·cgocall to make a switch from the
+Go runtime world to the system C (GCC-based) world.
+
+For example, here is the definition of _Cfunc_puts:
+
+ void _cgo_be59f0f25121_Cfunc_puts(void*);
+
+ void
+ ·_Cfunc_puts(struct{uint8 x[1];}p)
+ {
+ runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p);
+ }
+
+The hexadecimal number is a hash of cgo's input, chosen to be
+deterministic yet unlikely to collide with other uses. The actual
+function _cgo_be59f0f25121_Cfunc_puts is implemented in a C source
+file compiled by gcc, the file x.cgo2.c:
+
+ void
+ _cgo_be59f0f25121_Cfunc_puts(void *v)
+ {
+ struct {
+ char* p0;
+ int r;
+ char __pad12[4];
+ } __attribute__((__packed__, __gcc_struct__)) *a = v;
+ a->r = puts((void*)a->p0);
+ }
+
+It extracts the arguments from the pointer to _Cfunc_puts's argument
+frame, invokes the system C function (in this case, puts), stores the
+result in the frame, and returns.
+
+Linking
+
+Once the _cgo_export.c and *.cgo2.c files have been compiled with gcc,
+they need to be linked into the final binary, along with the libraries
+they might depend on (in the case of puts, stdio). 6l has been
+extended to understand basic ELF files, but it does not understand ELF
+in the full complexity that modern C libraries embrace, so it cannot
+in general generate direct references to the system libraries.
+
+Instead, the build process generates an object file using dynamic
+linkage to the desired libraries. The main function is provided by
+_cgo_main.c:
+
+ int main() { return 0; }
+ void crosscall2(void(*fn)(void*, int), void *a, int c) { }
+ void _cgo_allocate(void *a, int c) { }
+ void _cgo_panic(void *a, int c) { }
+
+The extra functions here are stubs to satisfy the references in the C
+code generated for gcc. The build process links this stub, along with
+_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets
+cgo examine the executable. Cgo records the list of shared library
+references and resolved names and writes them into a new file
+_cgo_import.c, which looks like:
+
+ #pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2"
+ #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+ #pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6"
+ #pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6"
+ #pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6"
+ #pragma cgo_import_dynamic _ _ "libpthread.so.0"
+ #pragma cgo_import_dynamic _ _ "libc.so.6"
+
+In the end, the compiled Go package, which will eventually be
+presented to 6l as part of a larger program, contains:
+
+ _go_.6 # 6g-compiled object for _cgo_gotypes.go *.cgo1.go
+ _cgo_defun.6 # 6c-compiled object for _cgo_defun.c
+ _all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c
+ _cgo_import.6 # 6c-compiled object for _cgo_import.c
+
+The final program will be a dynamic executable, so that 6l can avoid
+needing to process arbitrary .o files. It only needs to process the .o
+files generated from C files that cgo writes, and those are much more
+limited in the ELF or other features that they use.
+
+In essence, the _cgo_import.6 file includes the extra linking
+directives that 6l is not sophisticated enough to derive from _all.o
+on its own. Similarly, the _all.o uses dynamic references to real
+system object code because 6l is not sophisticated enough to process
+the real code.
+
+The main benefits of this system are that 6l remains relatively simple
+(it does not need to implement a complete ELF and Mach-O linker) and
+that gcc is not needed after the package is compiled. For example,
+package net uses cgo for access to name resolution functions provided
+by libc. Although gcc is needed to compile package net, gcc is not
+needed to link programs that import package net.
+
+Runtime
+
+When using cgo, Go must not assume that it owns all details of the
+process. In particular it needs to coordinate with C in the use of
+threads and thread-local storage. The runtime package, in its own
+(6c-compiled) C code, declares a few uninitialized (default bss)
+variables:
+
+ bool runtime·iscgo;
+ void (*libcgo_thread_start)(void*);
+ void (*initcgo)(G*);
+
+Any package using cgo imports "runtime/cgo", which provides
+initializations for these variables. It sets iscgo to 1, initcgo to a
+gcc-compiled function that can be called early during program startup,
+and libcgo_thread_start to a gcc-compiled function that can be used to
+create a new thread, in place of the runtime's usual direct system
+calls.
+
+Internal and External Linking
+
+The text above describes "internal" linking, in which 6l parses and
+links host object files (ELF, Mach-O, PE, and so on) into the final
+executable itself. Keeping 6l simple means we cannot possibly
+implement the full semantics of the host linker, so the kinds of
+objects that can be linked directly into the binary is limited (other
+code can only be used as a dynamic library). On the other hand, when
+using internal linking, 6l can generate Go binaries by itself.
+
+In order to allow linking arbitrary object files without requiring
+dynamic libraries, cgo will soon support an "external" linking mode
+too. In external linking mode, 6l does not process any host object
+files. Instead, it collects all the Go code and writes a single go.o
+object file containing it. Then it invokes the host linker (usually
+gcc) to combine the go.o object file and any supporting non-Go code
+into a final executable. External linking avoids the dynamic library
+requirement but introduces a requirement that the host linker be
+present to create such a binary.
+
+Most builds both compile source code and invoke the linker to create a
+binary. When cgo is involved, the compile step already requires gcc, so
+it is not problematic for the link step to require gcc too.
+
+An important exception is builds using a pre-compiled copy of the
+standard library. In particular, package net uses cgo on most systems,
+and we want to preserve the ability to compile pure Go code that
+imports net without requiring gcc to be present at link time. (In this
+case, the dynamic library requirement is less significant, because the
+only library involved is libc.so, which can usually be assumed
+present.)
+
+This conflict between functionality and the gcc requirement means we
+must support both internal and external linking, depending on the
+circumstances: if net is the only cgo-using package, then internal
+linking is probably fine, but if other packages are involved, so that there
+are dependencies on libraries beyond libc, external linking is likely
+to work better. The compilation of a package records the relevant
+information to support both linking modes, leaving the decision
+to be made when linking the final binary.
+
+Linking Directives
+
+In either linking mode, package-specific directives must be passed
+through to 6l. These are communicated by writing #pragma directives
+in a C source file compiled by 6c. The directives are copied into the .6 object file
+and then processed by the linker.
+
+The directives are:
+
+#pragma cgo_import_dynamic <local> [<remote> ["<library>"]]
+
+ In internal linking mode, allow an unresolved reference to
+ <local>, assuming it will be resolved by a dynamic library
+ symbol. The optional <remote> specifies the symbol's name and
+ possibly version in the dynamic library, and the optional "<library>"
+ names the specific library where the symbol should be found.
+
+ In the <remote>, # or @ can be used to introduce a symbol version.
+
+ Examples:
+ #pragma cgo_import_dynamic puts
+ #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5
+ #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6"
+
+ A side effect of the cgo_import_dynamic directive with a
+ library is to make the final binary depend on that dynamic
+ library. To get the dependency without importing any specific
+ symbols, use _ for local and remote.
+
+ Example:
+ #pragma cgo_import_dynamic _ _ "libc.so.6"
+
+ For compatibility with current versions of SWIG,
+ #pragma dynimport is an alias for #pragma cgo_import_dynamic.
+
+#pragma cgo_dynamic_linker "<path>"
+
+ In internal linking mode, use "<path>" as the dynamic linker
+ in the final binary. This directive is only needed from one
+ package when constructing a binary; by convention it is
+ supplied by runtime/cgo.
+
+ Example:
+ #pragma cgo_dynamic_linker "/lib/ld-linux.so.2"
+
+#pragma cgo_export_dynamic <local> <remote>
+
+ In internal linking mode, put the Go symbol
+ named <local> into the program's exported symbol table as
+ <remote>, so that C code can refer to it by that name. This
+ mechanism makes it possible for C code to call back into Go or
+ to share Go's data.
+
+ For compatibility with current versions of SWIG,
+ #pragma dynexport is an alias for #pragma cgo_export_dynamic.
+
+#pragma cgo_import_static <local>
+
+ In external linking mode, allow unresolved references to
+ <local> in the go.o object file prepared for the host linker,
+ under the assumption that <local> will be supplied by the
+ other object files that will be linked with go.o.
+
+ Example:
+ #pragma cgo_import_static puts_wrapper
+
+#pragma cgo_export_static <local> <remote>
+
+ In external linking mode, put the Go symbol
+ named <local> into the program's exported symbol table as
+ <remote>, so that C code can refer to it by that name. This
+ mechanism makes it possible for C code to call back into Go or
+ to share Go's data.
+
+#pragma cgo_ldflag "<arg>"
+
+ In external linking mode, invoke the host linker (usually gcc)
+ with "<arg>" as a command-line argument following the .o files.
+ Note that the arguments are for "gcc", not "ld".
+
+ Example:
+ #pragma cgo_ldflag "-lpthread"
+ #pragma cgo_ldflag "-L/usr/local/sqlite3/lib"
+
+A package compiled with cgo will include directives for both
+internal and external linking; the linker will select the appropriate
+subset for the chosen linking mode.
+
+Example
+
+As a simple example, consider a package that uses cgo to call C.sin.
+The following code will be generated by cgo:
+
+ // compiled by 6g
+
+ type _Ctype_double float64
+ func _Cfunc_sin(_Ctype_double) _Ctype_double
+
+ // compiled by 6c
+
+ #pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6"
+
+ #pragma cgo_import_static _cgo_gcc_Cfunc_sin
+ #pragma cgo_ldflag "-lm"
+
+ void _cgo_gcc_Cfunc_sin(void*);
+
+ void
+ ·_Cfunc_sin(struct{uint8 x[16];}p)
+ {
+ runtime·cgocall(_cgo_gcc_Cfunc_sin, &p);
+ }
+
+ // compiled by gcc, into foo.cgo2.o
+
+ void
+ _cgo_gcc_Cfunc_sin(void *v)
+ {
+ struct {
+ double p0;
+ double r;
+ } __attribute__((__packed__)) *a = v;
+ a->r = sin(a->p0);
+ }
+
+What happens at link time depends on whether the final binary is linked
+using the internal or external mode. If other packages are compiled in
+"external only" mode, then the final link will be an external one.
+Otherwise the link will be an internal one.
+
+The directives in the 6c-compiled file are used according to the kind
+of final link used.
+
+In internal mode, 6l itself processes all the host object files, in
+particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and
+cgo_dynamic_linker directives to learn that the otherwise undefined
+reference to sin in foo.cgo2.o should be rewritten to refer to the
+symbol sin with version GLIBC_2.2.5 from the dynamic library
+"libm.so.6", and the binary should request "/lib/ld-linux.so.2" as its
+runtime dynamic linker.
+
+In external mode, 6l does not process any host object files, in
+particular foo.cgo2.o. It links together the 6g- and 6c-generated
+object files, along with any other Go code, into a go.o file. While
+doing that, 6l will discover that there is no definition for
+_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This
+is okay, because 6l also processes the cgo_import_static directive and
+knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
+object file, so 6l does not treat the missing symbol as an error when
+creating go.o. Indeed, the definition for _cgo_gcc_Cfunc_sin will be
+provided to the host linker by foo2.cgo.o, which in turn will need the
+symbol 'sin'. 6l also processes the cgo_ldflag directives, so that it
+knows that the eventual host link command must include the -lm
+argument, so that the host linker will be able to find 'sin' in the
+math library.
+
+6l Command Line Interface
+
+The go command and any other Go-aware build systems invoke 6l
+to link a collection of packages into a single binary. By default, 6l will
+present the same interface it does today:
+
+ 6l main.a
+
+produces a file named 6.out, even if 6l does so by invoking the host
+linker in external linking mode.
+
+By default, 6l will decide the linking mode as follows: if the only
+packages using cgo are those on a whitelist of standard library
+packages (net, os/user, runtime/cgo), 6l will use internal linking
+mode. Otherwise, there are non-standard cgo packages involved, and 6l
+will use external linking mode. The first rule means that a build of
+the godoc binary, which uses net but no other cgo, can run without
+needing gcc available. The second rule means that a build of a
+cgo-wrapped library like sqlite3 can generate a standalone executable
+instead of needing to refer to a dynamic library. The specific choice
+can be overridden using a command line flag: 6l -linkmode=internal or
+6l -linkmode=external.
+
+In an external link, 6l will create a temporary directory, write any
+host object files found in package archives to that directory (renamed
+to avoid conflicts), write the go.o file to that directory, and invoke
+the host linker. The default value for the host linker is $CC, split
+into fields, or else "gcc". The specific host linker command line can
+be overridden using command line flags: 6l -extld=clang
+-extldflags='-ggdb -O3'. If any package in a build includes a .cc or
+other file compiled by the C++ compiler, the go tool will use the
+-extld option to set the host linker to the C++ compiler.
+
+These defaults mean that Go-aware build systems can ignore the linking
+changes and keep running plain '6l' and get reasonable results, but
+they can also control the linking details if desired.
+
+*/
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
new file mode 100644
index 0000000..f55cfba
--- /dev/null
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -0,0 +1,1728 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Annotate Ref in Prog with C types by parsing gcc debug output.
+// Conversion of debug output to Go types.
+
+package main
+
+import (
+ "bytes"
+ "debug/dwarf"
+ "debug/elf"
+ "debug/macho"
+ "debug/pe"
+ "encoding/binary"
+ "errors"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "os"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
+var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
+
+var nameToC = map[string]string{
+ "schar": "signed char",
+ "uchar": "unsigned char",
+ "ushort": "unsigned short",
+ "uint": "unsigned int",
+ "ulong": "unsigned long",
+ "longlong": "long long",
+ "ulonglong": "unsigned long long",
+ "complexfloat": "float complex",
+ "complexdouble": "double complex",
+}
+
+// cname returns the C name to use for C.s.
+// The expansions are listed in nameToC and also
+// struct_foo becomes "struct foo", and similarly for
+// union and enum.
+func cname(s string) string {
+ if t, ok := nameToC[s]; ok {
+ return t
+ }
+
+ if strings.HasPrefix(s, "struct_") {
+ return "struct " + s[len("struct_"):]
+ }
+ if strings.HasPrefix(s, "union_") {
+ return "union " + s[len("union_"):]
+ }
+ if strings.HasPrefix(s, "enum_") {
+ return "enum " + s[len("enum_"):]
+ }
+ if strings.HasPrefix(s, "sizeof_") {
+ return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
+ }
+ return s
+}
+
+// DiscardCgoDirectives processes the import C preamble, and discards
+// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
+// way into _cgo_export.h.
+func (f *File) DiscardCgoDirectives() {
+ linesIn := strings.Split(f.Preamble, "\n")
+ linesOut := make([]string, 0, len(linesIn))
+ for _, line := range linesIn {
+ l := strings.TrimSpace(line)
+ if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
+ linesOut = append(linesOut, line)
+ } else {
+ linesOut = append(linesOut, "")
+ }
+ }
+ f.Preamble = strings.Join(linesOut, "\n")
+}
+
+// addToFlag appends args to flag. All flags are later written out onto the
+// _cgo_flags file for the build system to use.
+func (p *Package) addToFlag(flag string, args []string) {
+ p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
+ if flag == "CFLAGS" {
+ // We'll also need these when preprocessing for dwarf information.
+ p.GccOptions = append(p.GccOptions, args...)
+ }
+}
+
+// splitQuoted splits the string s around each instance of one or more consecutive
+// white space characters while taking into account quotes and escaping, and
+// returns an array of substrings of s or an empty list if s contains only white space.
+// Single quotes and double quotes are recognized to prevent splitting within the
+// quoted region, and are removed from the resulting substrings. If a quote in s
+// isn't closed err will be set and r will have the unclosed argument as the
+// last element. The backslash is used for escaping.
+//
+// For example, the following string:
+//
+// `a b:"c d" 'e''f' "g\""`
+//
+// Would be parsed as:
+//
+// []string{"a", "b:c d", "ef", `g"`}
+//
+func splitQuoted(s string) (r []string, err error) {
+ var args []string
+ arg := make([]rune, len(s))
+ escaped := false
+ quoted := false
+ quote := '\x00'
+ i := 0
+ for _, r := range s {
+ switch {
+ case escaped:
+ escaped = false
+ case r == '\\':
+ escaped = true
+ continue
+ case quote != 0:
+ if r == quote {
+ quote = 0
+ continue
+ }
+ case r == '"' || r == '\'':
+ quoted = true
+ quote = r
+ continue
+ case unicode.IsSpace(r):
+ if quoted || i > 0 {
+ quoted = false
+ args = append(args, string(arg[:i]))
+ i = 0
+ }
+ continue
+ }
+ arg[i] = r
+ i++
+ }
+ if quoted || i > 0 {
+ args = append(args, string(arg[:i]))
+ }
+ if quote != 0 {
+ err = errors.New("unclosed quote")
+ } else if escaped {
+ err = errors.New("unfinished escaping")
+ }
+ return args, err
+}
+
+var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
+
+func safeName(s string) bool {
+ if s == "" {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Translate rewrites f.AST, the original Go input, to remove
+// references to the imported package C, replacing them with
+// references to the equivalent Go types, functions, and variables.
+func (p *Package) Translate(f *File) {
+ for _, cref := range f.Ref {
+ // Convert C.ulong to C.unsigned long, etc.
+ cref.Name.C = cname(cref.Name.Go)
+ }
+ p.loadDefines(f)
+ needType := p.guessKinds(f)
+ if len(needType) > 0 {
+ p.loadDWARF(f, needType)
+ }
+ p.rewriteRef(f)
+}
+
+// loadDefines coerces gcc into spitting out the #defines in use
+// in the file f and saves relevant renamings in f.Name[name].Define.
+func (p *Package) loadDefines(f *File) {
+ var b bytes.Buffer
+ b.WriteString(f.Preamble)
+ b.WriteString(builtinProlog)
+ stdout := p.gccDefines(b.Bytes())
+
+ for _, line := range strings.Split(stdout, "\n") {
+ if len(line) < 9 || line[0:7] != "#define" {
+ continue
+ }
+
+ line = strings.TrimSpace(line[8:])
+
+ var key, val string
+ spaceIndex := strings.Index(line, " ")
+ tabIndex := strings.Index(line, "\t")
+
+ if spaceIndex == -1 && tabIndex == -1 {
+ continue
+ } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
+ key = line[0:spaceIndex]
+ val = strings.TrimSpace(line[spaceIndex:])
+ } else {
+ key = line[0:tabIndex]
+ val = strings.TrimSpace(line[tabIndex:])
+ }
+
+ if n := f.Name[key]; n != nil {
+ if *debugDefine {
+ fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
+ }
+ n.Define = val
+ }
+ }
+}
+
+// guessKinds tricks gcc into revealing the kind of each
+// name xxx for the references C.xxx in the Go input.
+// The kind is either a constant, type, or variable.
+func (p *Package) guessKinds(f *File) []*Name {
+ // Determine kinds for names we already know about,
+ // like #defines or 'struct foo', before bothering with gcc.
+ var names, needType []*Name
+ for _, n := range f.Name {
+ // If we've already found this name as a #define
+ // and we can translate it as a constant value, do so.
+ if n.Define != "" {
+ isConst := false
+ if _, err := strconv.Atoi(n.Define); err == nil {
+ isConst = true
+ } else if n.Define[0] == '"' || n.Define[0] == '\'' {
+ if _, err := parser.ParseExpr(n.Define); err == nil {
+ isConst = true
+ }
+ }
+ if isConst {
+ n.Kind = "const"
+ // Turn decimal into hex, just for consistency
+ // with enum-derived constants. Otherwise
+ // in the cgo -godefs output half the constants
+ // are in hex and half are in whatever the #define used.
+ i, err := strconv.ParseInt(n.Define, 0, 64)
+ if err == nil {
+ n.Const = fmt.Sprintf("%#x", i)
+ } else {
+ n.Const = n.Define
+ }
+ continue
+ }
+
+ if isName(n.Define) {
+ n.C = n.Define
+ }
+ }
+
+ needType = append(needType, n)
+
+ // If this is a struct, union, or enum type name, no need to guess the kind.
+ if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
+ n.Kind = "type"
+ continue
+ }
+
+ // Otherwise, we'll need to find out from gcc.
+ names = append(names, n)
+ }
+
+ // Bypass gcc if there's nothing left to find out.
+ if len(names) == 0 {
+ return needType
+ }
+
+ // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
+ // For names, find out whether they are integer constants.
+ // We used to look at specific warning or error messages here, but that tied the
+ // behavior too closely to specific versions of the compilers.
+ // Instead, arrange that we can infer what we need from only the presence or absence
+ // of an error on a specific line.
+ //
+ // For each name, we generate these lines, where xxx is the index in toSniff plus one.
+ //
+ // #line xxx "not-declared"
+ // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
+ // #line xxx "not-type"
+ // void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
+ // #line xxx "not-const"
+ // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
+ //
+ // If we see an error at not-declared:xxx, the corresponding name is not declared.
+ // If we see an error at not-type:xxx, the corresponding name is a type.
+ // If we see an error at not-const:xxx, the corresponding name is not an integer constant.
+ // If we see no errors, we assume the name is an expression but not a constant
+ // (so a variable or a function).
+ //
+ // The specific input forms are chosen so that they are valid C syntax regardless of
+ // whether name denotes a type or an expression.
+
+ var b bytes.Buffer
+ b.WriteString(f.Preamble)
+ b.WriteString(builtinProlog)
+
+ for i, n := range names {
+ fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
+ "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
+ "#line %d \"not-type\"\n"+
+ "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
+ "#line %d \"not-const\"\n"+
+ "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
+ i+1, i+1, n.C,
+ i+1, i+1, n.C,
+ i+1, i+1, n.C)
+ }
+ fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
+ "int __cgo__1 = __cgo__2;\n")
+
+ stderr := p.gccErrors(b.Bytes())
+ if stderr == "" {
+ fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
+ }
+
+ completed := false
+ sniff := make([]int, len(names))
+ const (
+ notType = 1 << iota
+ notConst
+ )
+ for _, line := range strings.Split(stderr, "\n") {
+ if !strings.Contains(line, ": error:") {
+ // we only care about errors.
+ // we tried to turn off warnings on the command line, but one never knows.
+ continue
+ }
+
+ c1 := strings.Index(line, ":")
+ if c1 < 0 {
+ continue
+ }
+ c2 := strings.Index(line[c1+1:], ":")
+ if c2 < 0 {
+ continue
+ }
+ c2 += c1 + 1
+
+ filename := line[:c1]
+ i, _ := strconv.Atoi(line[c1+1 : c2])
+ i--
+ if i < 0 || i >= len(names) {
+ continue
+ }
+
+ switch filename {
+ case "completed":
+ // Strictly speaking, there is no guarantee that seeing the error at completed:1
+ // (at the end of the file) means we've seen all the errors from earlier in the file,
+ // but usually it does. Certainly if we don't see the completed:1 error, we did
+ // not get all the errors we expected.
+ completed = true
+
+ case "not-declared":
+ error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
+ case "not-type":
+ sniff[i] |= notType
+ case "not-const":
+ sniff[i] |= notConst
+ }
+ }
+
+ if !completed {
+ fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
+ }
+
+ for i, n := range names {
+ switch sniff[i] {
+ case 0:
+ error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
+ case notType:
+ n.Kind = "const"
+ case notConst:
+ n.Kind = "type"
+ case notConst | notType:
+ n.Kind = "not-type"
+ }
+ }
+ if nerrors > 0 {
+ fatalf("unresolved names")
+ }
+
+ needType = append(needType, names...)
+ return needType
+}
+
+// loadDWARF parses the DWARF debug information generated
+// by gcc to learn the details of the constants, variables, and types
+// being referred to as C.xxx.
+func (p *Package) loadDWARF(f *File, names []*Name) {
+ // Extract the types from the DWARF section of an object
+ // from a well-formed C program. Gcc only generates DWARF info
+ // for symbols in the object file, so it is not enough to print the
+ // preamble and hope the symbols we care about will be there.
+ // Instead, emit
+ // __typeof__(names[i]) *__cgo__i;
+ // for each entry in names and then dereference the type we
+ // learn for __cgo__i.
+ var b bytes.Buffer
+ b.WriteString(f.Preamble)
+ b.WriteString(builtinProlog)
+ for i, n := range names {
+ fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
+ if n.Kind == "const" {
+ fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
+ }
+ }
+
+ // Apple's LLVM-based gcc does not include the enumeration
+ // names and values in its DWARF debug output. In case we're
+ // using such a gcc, create a data block initialized with the values.
+ // We can read them out of the object file.
+ fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
+ for _, n := range names {
+ if n.Kind == "const" {
+ fmt.Fprintf(&b, "\t%s,\n", n.C)
+ } else {
+ fmt.Fprintf(&b, "\t0,\n")
+ }
+ }
+ // for the last entry, we can not use 0, otherwise
+ // in case all __cgodebug_data is zero initialized,
+ // LLVM-based gcc will place the it in the __DATA.__common
+ // zero-filled section (our debug/macho doesn't support
+ // this)
+ fmt.Fprintf(&b, "\t1\n")
+ fmt.Fprintf(&b, "};\n")
+
+ d, bo, debugData := p.gccDebug(b.Bytes())
+ enumVal := make([]int64, len(debugData)/8)
+ for i := range enumVal {
+ enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
+ }
+
+ // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
+ types := make([]dwarf.Type, len(names))
+ enums := make([]dwarf.Offset, len(names))
+ nameToIndex := make(map[*Name]int)
+ for i, n := range names {
+ nameToIndex[n] = i
+ }
+ nameToRef := make(map[*Name]*Ref)
+ for _, ref := range f.Ref {
+ nameToRef[ref.Name] = ref
+ }
+ r := d.Reader()
+ for {
+ e, err := r.Next()
+ if err != nil {
+ fatalf("reading DWARF entry: %s", err)
+ }
+ if e == nil {
+ break
+ }
+ switch e.Tag {
+ case dwarf.TagEnumerationType:
+ offset := e.Offset
+ for {
+ e, err := r.Next()
+ if err != nil {
+ fatalf("reading DWARF entry: %s", err)
+ }
+ if e.Tag == 0 {
+ break
+ }
+ if e.Tag == dwarf.TagEnumerator {
+ entryName := e.Val(dwarf.AttrName).(string)
+ if strings.HasPrefix(entryName, "__cgo_enum__") {
+ n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
+ if 0 <= n && n < len(names) {
+ enums[n] = offset
+ }
+ }
+ }
+ }
+ case dwarf.TagVariable:
+ name, _ := e.Val(dwarf.AttrName).(string)
+ typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
+ if name == "" || typOff == 0 {
+ fatalf("malformed DWARF TagVariable entry")
+ }
+ if !strings.HasPrefix(name, "__cgo__") {
+ break
+ }
+ typ, err := d.Type(typOff)
+ if err != nil {
+ fatalf("loading DWARF type: %s", err)
+ }
+ t, ok := typ.(*dwarf.PtrType)
+ if !ok || t == nil {
+ fatalf("internal error: %s has non-pointer type", name)
+ }
+ i, err := strconv.Atoi(name[7:])
+ if err != nil {
+ fatalf("malformed __cgo__ name: %s", name)
+ }
+ if enums[i] != 0 {
+ t, err := d.Type(enums[i])
+ if err != nil {
+ fatalf("loading DWARF type: %s", err)
+ }
+ types[i] = t
+ } else {
+ types[i] = t.Type
+ }
+ }
+ if e.Tag != dwarf.TagCompileUnit {
+ r.SkipChildren()
+ }
+ }
+
+ // Record types and typedef information.
+ var conv typeConv
+ conv.Init(p.PtrSize, p.IntSize)
+ for i, n := range names {
+ if types[i] == nil {
+ continue
+ }
+ pos := token.NoPos
+ if ref, ok := nameToRef[n]; ok {
+ pos = ref.Pos()
+ }
+ f, fok := types[i].(*dwarf.FuncType)
+ if n.Kind != "type" && fok {
+ n.Kind = "func"
+ n.FuncType = conv.FuncType(f, pos)
+ } else {
+ n.Type = conv.Type(types[i], pos)
+ if enums[i] != 0 && n.Type.EnumValues != nil {
+ k := fmt.Sprintf("__cgo_enum__%d", i)
+ n.Kind = "const"
+ n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
+ // Remove injected enum to ensure the value will deep-compare
+ // equally in future loads of the same constant.
+ delete(n.Type.EnumValues, k)
+ }
+ // Prefer debug data over DWARF debug output, if we have it.
+ if n.Kind == "const" && i < len(enumVal) {
+ n.Const = fmt.Sprintf("%#x", enumVal[i])
+ }
+ }
+ conv.FinishType(pos)
+ }
+}
+
+// mangleName does name mangling to translate names
+// from the original Go source files to the names
+// used in the final Go files generated by cgo.
+func (p *Package) mangleName(n *Name) {
+ // When using gccgo variables have to be
+ // exported so that they become global symbols
+ // that the C code can refer to.
+ prefix := "_C"
+ if *gccgo && n.IsVar() {
+ prefix = "C"
+ }
+ n.Mangle = prefix + n.Kind + "_" + n.Go
+}
+
+// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
+// Go equivalents, now that we have figured out the meaning of all
+// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
+// with full definitions instead of mangled names.
+func (p *Package) rewriteRef(f *File) {
+ // Keep a list of all the functions, to remove the ones
+ // only used as expressions and avoid generating bridge
+ // code for them.
+ functions := make(map[string]bool)
+
+ // Assign mangled names.
+ for _, n := range f.Name {
+ if n.Kind == "not-type" {
+ n.Kind = "var"
+ }
+ if n.Mangle == "" {
+ p.mangleName(n)
+ }
+ if n.Kind == "func" {
+ functions[n.Go] = false
+ }
+ }
+
+ // Now that we have all the name types filled in,
+ // scan through the Refs to identify the ones that
+ // are trying to do a ,err call. Also check that
+ // functions are only used in calls.
+ for _, r := range f.Ref {
+ if r.Name.Kind == "const" && r.Name.Const == "" {
+ error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
+ }
+ var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
+ switch r.Context {
+ case "call", "call2":
+ if r.Name.Kind != "func" {
+ if r.Name.Kind == "type" {
+ r.Context = "type"
+ expr = r.Name.Type.Go
+ break
+ }
+ error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
+ break
+ }
+ functions[r.Name.Go] = true
+ if r.Context == "call2" {
+ if r.Name.Go == "_CMalloc" {
+ error_(r.Pos(), "no two-result form for C.malloc")
+ break
+ }
+ // Invent new Name for the two-result function.
+ n := f.Name["2"+r.Name.Go]
+ if n == nil {
+ n = new(Name)
+ *n = *r.Name
+ n.AddError = true
+ n.Mangle = "_C2func_" + n.Go
+ f.Name["2"+r.Name.Go] = n
+ }
+ expr = ast.NewIdent(n.Mangle)
+ r.Name = n
+ break
+ }
+ case "expr":
+ if r.Name.Kind == "func" {
+ // Function is being used in an expression, to e.g. pass around a C function pointer.
+ // Create a new Name for this Ref which causes the variable to be declared in Go land.
+ fpName := "fp_" + r.Name.Go
+ name := f.Name[fpName]
+ if name == nil {
+ name = &Name{
+ Go: fpName,
+ C: r.Name.C,
+ Kind: "fpvar",
+ Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
+ }
+ p.mangleName(name)
+ f.Name[fpName] = name
+ }
+ r.Name = name
+ expr = ast.NewIdent(name.Mangle)
+ } else if r.Name.Kind == "type" {
+ // Okay - might be new(T)
+ expr = r.Name.Type.Go
+ } else if r.Name.Kind == "var" {
+ expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
+ }
+
+ case "type":
+ if r.Name.Kind != "type" {
+ error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
+ } else if r.Name.Type == nil {
+ // Use of C.enum_x, C.struct_x or C.union_x without C definition.
+ // GCC won't raise an error when using pointers to such unknown types.
+ error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
+ } else {
+ expr = r.Name.Type.Go
+ }
+ default:
+ if r.Name.Kind == "func" {
+ error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
+ }
+ }
+ if *godefs || *cdefs {
+ // Substitute definition for mangled type name.
+ if id, ok := expr.(*ast.Ident); ok {
+ if t := typedef[id.Name]; t != nil {
+ expr = t.Go
+ }
+ if id.Name == r.Name.Mangle && r.Name.Const != "" {
+ expr = ast.NewIdent(r.Name.Const)
+ }
+ }
+ }
+
+ // Copy position information from old expr into new expr,
+ // in case expression being replaced is first on line.
+ // See golang.org/issue/6563.
+ pos := (*r.Expr).Pos()
+ switch x := expr.(type) {
+ case *ast.Ident:
+ expr = &ast.Ident{NamePos: pos, Name: x.Name}
+ }
+
+ *r.Expr = expr
+ }
+
+ // Remove functions only used as expressions, so their respective
+ // bridge functions are not generated.
+ for name, used := range functions {
+ if !used {
+ delete(f.Name, name)
+ }
+ }
+}
+
+// gccBaseCmd returns the start of the compiler command line.
+// It uses $CC if set, or else $GCC, or else the compiler recorded
+// during the initial build as defaultCC.
+// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
+func (p *Package) gccBaseCmd() []string {
+ // Use $CC if set, since that's what the build uses.
+ if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
+ return ret
+ }
+ // Try $GCC if set, since that's what we used to use.
+ if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
+ return ret
+ }
+ return strings.Fields(defaultCC)
+}
+
+// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
+func (p *Package) gccMachine() []string {
+ switch goarch {
+ case "amd64":
+ return []string{"-m64"}
+ case "386":
+ return []string{"-m32"}
+ case "arm":
+ return []string{"-marm"} // not thumb
+ }
+ return nil
+}
+
+func gccTmp() string {
+ return *objDir + "_cgo_.o"
+}
+
+// gccCmd returns the gcc command line to use for compiling
+// the input.
+func (p *Package) gccCmd() []string {
+ c := append(p.gccBaseCmd(),
+ "-w", // no warnings
+ "-Wno-error", // warnings are not errors
+ "-o"+gccTmp(), // write object to tmp
+ "-gdwarf-2", // generate DWARF v2 debugging symbols
+ "-c", // do not link
+ "-xc", // input language is C
+ )
+ if strings.Contains(c[0], "clang") {
+ c = append(c,
+ "-ferror-limit=0",
+ // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
+ // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
+ // flag to disable the warning. Yes, really good diagnostics, clang.
+ "-Wno-unknown-warning-option",
+ "-Wno-unneeded-internal-declaration",
+ "-Wno-unused-function",
+ "-Qunused-arguments",
+ // Clang embeds prototypes for some builtin functions,
+ // like malloc and calloc, but all size_t parameters are
+ // incorrectly typed unsigned long. We work around that
+ // by disabling the builtin functions (this is safe as
+ // it won't affect the actual compilation of the C code).
+ // See: http://golang.org/issue/6506.
+ "-fno-builtin",
+ )
+ }
+
+ c = append(c, p.GccOptions...)
+ c = append(c, p.gccMachine()...)
+ c = append(c, "-") //read input from standard input
+ return c
+}
+
+// gccDebug runs gcc -gdwarf-2 over the C program stdin and
+// returns the corresponding DWARF data and, if present, debug data block.
+func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
+ runGcc(stdin, p.gccCmd())
+
+ isDebugData := func(s string) bool {
+ // Some systems use leading _ to denote non-assembly symbols.
+ return s == "__cgodebug_data" || s == "___cgodebug_data"
+ }
+
+ if f, err := macho.Open(gccTmp()); err == nil {
+ defer f.Close()
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+ }
+ var data []byte
+ if f.Symtab != nil {
+ for i := range f.Symtab.Syms {
+ s := &f.Symtab.Syms[i]
+ if isDebugData(s.Name) {
+ // Found it. Now find data section.
+ if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data = sdat[s.Value-sect.Addr:]
+ }
+ }
+ }
+ }
+ }
+ }
+ return d, f.ByteOrder, data
+ }
+
+ if f, err := elf.Open(gccTmp()); err == nil {
+ defer f.Close()
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+ }
+ var data []byte
+ symtab, err := f.Symbols()
+ if err == nil {
+ for i := range symtab {
+ s := &symtab[i]
+ if isDebugData(s.Name) {
+ // Found it. Now find data section.
+ if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data = sdat[s.Value-sect.Addr:]
+ }
+ }
+ }
+ }
+ }
+ }
+ return d, f.ByteOrder, data
+ }
+
+ if f, err := pe.Open(gccTmp()); err == nil {
+ defer f.Close()
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
+ }
+ var data []byte
+ for _, s := range f.Symbols {
+ if isDebugData(s.Name) {
+ if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if s.Value < sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data = sdat[s.Value:]
+ }
+ }
+ }
+ }
+ }
+ return d, binary.LittleEndian, data
+ }
+
+ fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
+ panic("not reached")
+}
+
+// gccDefines runs gcc -E -dM -xc - over the C program stdin
+// and returns the corresponding standard output, which is the
+// #defines that gcc encountered while processing the input
+// and its included files.
+func (p *Package) gccDefines(stdin []byte) string {
+ base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
+ base = append(base, p.gccMachine()...)
+ stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
+ return stdout
+}
+
+// gccErrors runs gcc over the C program stdin and returns
+// the errors that gcc prints. That is, this function expects
+// gcc to fail.
+func (p *Package) gccErrors(stdin []byte) string {
+ // TODO(rsc): require failure
+ args := p.gccCmd()
+
+ if *debugGcc {
+ fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
+ os.Stderr.Write(stdin)
+ fmt.Fprint(os.Stderr, "EOF\n")
+ }
+ stdout, stderr, _ := run(stdin, args)
+ if *debugGcc {
+ os.Stderr.Write(stdout)
+ os.Stderr.Write(stderr)
+ }
+ return string(stderr)
+}
+
+// runGcc runs the gcc command line args with stdin on standard input.
+// If the command exits with a non-zero exit status, runGcc prints
+// details about what was run and exits.
+// Otherwise runGcc returns the data written to standard output and standard error.
+// Note that for some of the uses we expect useful data back
+// on standard error, but for those uses gcc must still exit 0.
+func runGcc(stdin []byte, args []string) (string, string) {
+ if *debugGcc {
+ fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
+ os.Stderr.Write(stdin)
+ fmt.Fprint(os.Stderr, "EOF\n")
+ }
+ stdout, stderr, ok := run(stdin, args)
+ if *debugGcc {
+ os.Stderr.Write(stdout)
+ os.Stderr.Write(stderr)
+ }
+ if !ok {
+ os.Stderr.Write(stderr)
+ os.Exit(2)
+ }
+ return string(stdout), string(stderr)
+}
+
+// A typeConv is a translator from dwarf types to Go types
+// with equivalent memory layout.
+type typeConv struct {
+ // Cache of already-translated or in-progress types.
+ m map[dwarf.Type]*Type
+ typedef map[string]ast.Expr
+
+ // Map from types to incomplete pointers to those types.
+ ptrs map[dwarf.Type][]*Type
+
+ // Fields to be processed by godefsField after completing pointers.
+ todoFlds [][]*ast.Field
+
+ // Predeclared types.
+ bool ast.Expr
+ byte ast.Expr // denotes padding
+ int8, int16, int32, int64 ast.Expr
+ uint8, uint16, uint32, uint64, uintptr ast.Expr
+ float32, float64 ast.Expr
+ complex64, complex128 ast.Expr
+ void ast.Expr
+ unsafePointer ast.Expr
+ string ast.Expr
+ goVoid ast.Expr // _Ctype_void, denotes C's void
+
+ ptrSize int64
+ intSize int64
+}
+
+var tagGen int
+var typedef = make(map[string]*Type)
+var goIdent = make(map[string]*ast.Ident)
+
+func (c *typeConv) Init(ptrSize, intSize int64) {
+ c.ptrSize = ptrSize
+ c.intSize = intSize
+ c.m = make(map[dwarf.Type]*Type)
+ c.ptrs = make(map[dwarf.Type][]*Type)
+ c.bool = c.Ident("bool")
+ c.byte = c.Ident("byte")
+ c.int8 = c.Ident("int8")
+ c.int16 = c.Ident("int16")
+ c.int32 = c.Ident("int32")
+ c.int64 = c.Ident("int64")
+ c.uint8 = c.Ident("uint8")
+ c.uint16 = c.Ident("uint16")
+ c.uint32 = c.Ident("uint32")
+ c.uint64 = c.Ident("uint64")
+ c.uintptr = c.Ident("uintptr")
+ c.float32 = c.Ident("float32")
+ c.float64 = c.Ident("float64")
+ c.complex64 = c.Ident("complex64")
+ c.complex128 = c.Ident("complex128")
+ c.unsafePointer = c.Ident("unsafe.Pointer")
+ c.void = c.Ident("void")
+ c.string = c.Ident("string")
+ c.goVoid = c.Ident("_Ctype_void")
+}
+
+// base strips away qualifiers and typedefs to get the underlying type
+func base(dt dwarf.Type) dwarf.Type {
+ for {
+ if d, ok := dt.(*dwarf.QualType); ok {
+ dt = d.Type
+ continue
+ }
+ if d, ok := dt.(*dwarf.TypedefType); ok {
+ dt = d.Type
+ continue
+ }
+ break
+ }
+ return dt
+}
+
+// Map from dwarf text names to aliases we use in package "C".
+var dwarfToName = map[string]string{
+ "long int": "long",
+ "long unsigned int": "ulong",
+ "unsigned int": "uint",
+ "short unsigned int": "ushort",
+ "short int": "short",
+ "long long int": "longlong",
+ "long long unsigned int": "ulonglong",
+ "signed char": "schar",
+ "float complex": "complexfloat",
+ "double complex": "complexdouble",
+}
+
+const signedDelta = 64
+
+// String returns the current type representation. Format arguments
+// are assembled within this method so that any changes in mutable
+// values are taken into account.
+func (tr *TypeRepr) String() string {
+ if len(tr.Repr) == 0 {
+ return ""
+ }
+ if len(tr.FormatArgs) == 0 {
+ return tr.Repr
+ }
+ return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
+}
+
+// Empty returns true if the result of String would be "".
+func (tr *TypeRepr) Empty() bool {
+ return len(tr.Repr) == 0
+}
+
+// Set modifies the type representation.
+// If fargs are provided, repr is used as a format for fmt.Sprintf.
+// Otherwise, repr is used unprocessed as the type representation.
+func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
+ tr.Repr = repr
+ tr.FormatArgs = fargs
+}
+
+// FinishType completes any outstanding type mapping work.
+// In particular, it resolves incomplete pointer types and also runs
+// godefsFields on any new struct types.
+func (c *typeConv) FinishType(pos token.Pos) {
+ // Completing one pointer type might produce more to complete.
+ // Keep looping until they're all done.
+ for len(c.ptrs) > 0 {
+ for dtype := range c.ptrs {
+ // Note Type might invalidate c.ptrs[dtype].
+ t := c.Type(dtype, pos)
+ for _, ptr := range c.ptrs[dtype] {
+ ptr.Go.(*ast.StarExpr).X = t.Go
+ ptr.C.Set("%s*", t.C)
+ }
+ delete(c.ptrs, dtype)
+ }
+ }
+
+ // Now that pointer types are completed, we can invoke godefsFields
+ // to rewrite struct definitions.
+ for _, fld := range c.todoFlds {
+ godefsFields(fld)
+ }
+ c.todoFlds = nil
+}
+
+// Type returns a *Type with the same memory layout as
+// dtype when used as the type of a variable or a struct field.
+func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
+ if t, ok := c.m[dtype]; ok {
+ if t.Go == nil {
+ fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
+ }
+ return t
+ }
+
+ // clang won't generate DW_AT_byte_size for pointer types,
+ // so we have to fix it here.
+ if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
+ dt.ByteSize = c.ptrSize
+ }
+
+ t := new(Type)
+ t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
+ t.Align = -1
+ t.C = &TypeRepr{Repr: dtype.Common().Name}
+ c.m[dtype] = t
+
+ switch dt := dtype.(type) {
+ default:
+ fatalf("%s: unexpected type: %s", lineno(pos), dtype)
+
+ case *dwarf.AddrType:
+ if t.Size != c.ptrSize {
+ fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
+ }
+ t.Go = c.uintptr
+ t.Align = t.Size
+
+ case *dwarf.ArrayType:
+ if dt.StrideBitSize > 0 {
+ // Cannot represent bit-sized elements in Go.
+ t.Go = c.Opaque(t.Size)
+ break
+ }
+ sub := c.Type(dt.Type, pos)
+ t.Align = sub.Align
+ t.Go = &ast.ArrayType{
+ Len: c.intExpr(dt.Count),
+ Elt: sub.Go,
+ }
+ t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
+
+ case *dwarf.BoolType:
+ t.Go = c.bool
+ t.Align = 1
+
+ case *dwarf.CharType:
+ if t.Size != 1 {
+ fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
+ }
+ t.Go = c.int8
+ t.Align = 1
+
+ case *dwarf.EnumType:
+ if t.Align = t.Size; t.Align >= c.ptrSize {
+ t.Align = c.ptrSize
+ }
+ t.C.Set("enum " + dt.EnumName)
+ signed := 0
+ t.EnumValues = make(map[string]int64)
+ for _, ev := range dt.Val {
+ t.EnumValues[ev.Name] = ev.Val
+ if ev.Val < 0 {
+ signed = signedDelta
+ }
+ }
+ switch t.Size + int64(signed) {
+ default:
+ fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
+ case 1:
+ t.Go = c.uint8
+ case 2:
+ t.Go = c.uint16
+ case 4:
+ t.Go = c.uint32
+ case 8:
+ t.Go = c.uint64
+ case 1 + signedDelta:
+ t.Go = c.int8
+ case 2 + signedDelta:
+ t.Go = c.int16
+ case 4 + signedDelta:
+ t.Go = c.int32
+ case 8 + signedDelta:
+ t.Go = c.int64
+ }
+
+ case *dwarf.FloatType:
+ switch t.Size {
+ default:
+ fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
+ case 4:
+ t.Go = c.float32
+ case 8:
+ t.Go = c.float64
+ }
+ if t.Align = t.Size; t.Align >= c.ptrSize {
+ t.Align = c.ptrSize
+ }
+
+ case *dwarf.ComplexType:
+ switch t.Size {
+ default:
+ fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
+ case 8:
+ t.Go = c.complex64
+ case 16:
+ t.Go = c.complex128
+ }
+ if t.Align = t.Size; t.Align >= c.ptrSize {
+ t.Align = c.ptrSize
+ }
+
+ case *dwarf.FuncType:
+ // No attempt at translation: would enable calls
+ // directly between worlds, but we need to moderate those.
+ t.Go = c.uintptr
+ t.Align = c.ptrSize
+
+ case *dwarf.IntType:
+ if dt.BitSize > 0 {
+ fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
+ }
+ switch t.Size {
+ default:
+ fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
+ case 1:
+ t.Go = c.int8
+ case 2:
+ t.Go = c.int16
+ case 4:
+ t.Go = c.int32
+ case 8:
+ t.Go = c.int64
+ }
+ if t.Align = t.Size; t.Align >= c.ptrSize {
+ t.Align = c.ptrSize
+ }
+
+ case *dwarf.PtrType:
+ t.Align = c.ptrSize
+
+ // Translate void* as unsafe.Pointer
+ if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
+ t.Go = c.unsafePointer
+ t.C.Set("void*")
+ break
+ }
+
+ // Placeholder initialization; completed in FinishType.
+ t.Go = &ast.StarExpr{}
+ t.C.Set("<incomplete>*")
+ c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
+
+ case *dwarf.QualType:
+ // Ignore qualifier.
+ t = c.Type(dt.Type, pos)
+ c.m[dtype] = t
+ return t
+
+ case *dwarf.StructType:
+ // Convert to Go struct, being careful about alignment.
+ // Have to give it a name to simulate C "struct foo" references.
+ tag := dt.StructName
+ if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
+ break
+ }
+ if tag == "" {
+ tag = "__" + strconv.Itoa(tagGen)
+ tagGen++
+ } else if t.C.Empty() {
+ t.C.Set(dt.Kind + " " + tag)
+ }
+ name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
+ t.Go = name // publish before recursive calls
+ goIdent[name.Name] = name
+ if dt.ByteSize < 0 {
+ // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
+ // so execute the basic things that the struct case would do
+ // other than try to determine a Go representation.
+ tt := *t
+ tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
+ tt.Go = c.Ident("struct{}")
+ typedef[name.Name] = &tt
+ break
+ }
+ switch dt.Kind {
+ case "class", "union":
+ t.Go = c.Opaque(t.Size)
+ if t.C.Empty() {
+ t.C.Set("__typeof__(unsigned char[%d])", t.Size)
+ }
+ t.Align = 1 // TODO: should probably base this on field alignment.
+ typedef[name.Name] = t
+ case "struct":
+ g, csyntax, align := c.Struct(dt, pos)
+ if t.C.Empty() {
+ t.C.Set(csyntax)
+ }
+ t.Align = align
+ tt := *t
+ if tag != "" {
+ tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
+ }
+ tt.Go = g
+ typedef[name.Name] = &tt
+ }
+
+ case *dwarf.TypedefType:
+ // Record typedef for printing.
+ if dt.Name == "_GoString_" {
+ // Special C name for Go string type.
+ // Knows string layout used by compilers: pointer plus length,
+ // which rounds up to 2 pointers after alignment.
+ t.Go = c.string
+ t.Size = c.ptrSize * 2
+ t.Align = c.ptrSize
+ break
+ }
+ if dt.Name == "_GoBytes_" {
+ // Special C name for Go []byte type.
+ // Knows slice layout used by compilers: pointer, length, cap.
+ t.Go = c.Ident("[]byte")
+ t.Size = c.ptrSize + 4 + 4
+ t.Align = c.ptrSize
+ break
+ }
+ name := c.Ident("_Ctype_" + dt.Name)
+ goIdent[name.Name] = name
+ sub := c.Type(dt.Type, pos)
+ t.Go = name
+ t.Size = sub.Size
+ t.Align = sub.Align
+ oldType := typedef[name.Name]
+ if oldType == nil {
+ tt := *t
+ tt.Go = sub.Go
+ typedef[name.Name] = &tt
+ }
+
+ // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
+ // use that as the Go form for this typedef too, so that the typedef will be interchangeable
+ // with the base type.
+ // In -godefs and -cdefs mode, do this for all typedefs.
+ if isStructUnionClass(sub.Go) || *godefs || *cdefs {
+ t.Go = sub.Go
+
+ if isStructUnionClass(sub.Go) {
+ // Use the typedef name for C code.
+ typedef[sub.Go.(*ast.Ident).Name].C = t.C
+ }
+
+ // If we've seen this typedef before, and it
+ // was an anonymous struct/union/class before
+ // too, use the old definition.
+ // TODO: it would be safer to only do this if
+ // we verify that the types are the same.
+ if oldType != nil && isStructUnionClass(oldType.Go) {
+ t.Go = oldType.Go
+ }
+ }
+
+ case *dwarf.UcharType:
+ if t.Size != 1 {
+ fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
+ }
+ t.Go = c.uint8
+ t.Align = 1
+
+ case *dwarf.UintType:
+ if dt.BitSize > 0 {
+ fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
+ }
+ switch t.Size {
+ default:
+ fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
+ case 1:
+ t.Go = c.uint8
+ case 2:
+ t.Go = c.uint16
+ case 4:
+ t.Go = c.uint32
+ case 8:
+ t.Go = c.uint64
+ }
+ if t.Align = t.Size; t.Align >= c.ptrSize {
+ t.Align = c.ptrSize
+ }
+
+ case *dwarf.VoidType:
+ t.Go = c.goVoid
+ t.C.Set("void")
+ t.Align = 1
+ }
+
+ switch dtype.(type) {
+ case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
+ s := dtype.Common().Name
+ if s != "" {
+ if ss, ok := dwarfToName[s]; ok {
+ s = ss
+ }
+ s = strings.Join(strings.Split(s, " "), "") // strip spaces
+ name := c.Ident("_Ctype_" + s)
+ tt := *t
+ typedef[name.Name] = &tt
+ if !*godefs && !*cdefs {
+ t.Go = name
+ }
+ }
+ }
+
+ if t.Size <= 0 {
+ // Clang does not record the size of a pointer in its DWARF entry,
+ // so if dtype is an array, the call to dtype.Size at the top of the function
+ // computed the size as the array length * 0 = 0.
+ // The type switch called Type (this function) recursively on the pointer
+ // entry, and the code near the top of the function updated the size to
+ // be correct, so calling dtype.Size again will produce the correct value.
+ t.Size = dtype.Size()
+ if t.Size < 0 {
+ // Unsized types are [0]byte, unless they're typedefs of other types
+ // or structs with tags.
+ // if so, use the name we've already defined.
+ t.Size = 0
+ switch dt := dtype.(type) {
+ case *dwarf.TypedefType:
+ // ok
+ case *dwarf.StructType:
+ if dt.StructName != "" {
+ break
+ }
+ t.Go = c.Opaque(0)
+ default:
+ t.Go = c.Opaque(0)
+ }
+ if t.C.Empty() {
+ t.C.Set("void")
+ }
+ return t
+ }
+ }
+
+ if t.C.Empty() {
+ fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
+ }
+
+ return t
+}
+
+// isStructUnionClass reports whether the type described by the Go syntax x
+// is a struct, union, or class with a tag.
+func isStructUnionClass(x ast.Expr) bool {
+ id, ok := x.(*ast.Ident)
+ if !ok {
+ return false
+ }
+ name := id.Name
+ return strings.HasPrefix(name, "_Ctype_struct_") ||
+ strings.HasPrefix(name, "_Ctype_union_") ||
+ strings.HasPrefix(name, "_Ctype_class_")
+}
+
+// FuncArg returns a Go type with the same memory layout as
+// dtype when used as the type of a C function argument.
+func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
+ t := c.Type(dtype, pos)
+ switch dt := dtype.(type) {
+ case *dwarf.ArrayType:
+ // Arrays are passed implicitly as pointers in C.
+ // In Go, we must be explicit.
+ tr := &TypeRepr{}
+ tr.Set("%s*", t.C)
+ return &Type{
+ Size: c.ptrSize,
+ Align: c.ptrSize,
+ Go: &ast.StarExpr{X: t.Go},
+ C: tr,
+ }
+ case *dwarf.TypedefType:
+ // C has much more relaxed rules than Go for
+ // implicit type conversions. When the parameter
+ // is type T defined as *X, simulate a little of the
+ // laxness of C by making the argument *X instead of T.
+ if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
+ // Unless the typedef happens to point to void* since
+ // Go has special rules around using unsafe.Pointer.
+ if _, void := base(ptr.Type).(*dwarf.VoidType); void {
+ break
+ }
+
+ t = c.Type(ptr, pos)
+ if t == nil {
+ return nil
+ }
+
+ // Remember the C spelling, in case the struct
+ // has __attribute__((unavailable)) on it. See issue 2888.
+ t.Typedef = dt.Name
+ }
+ }
+ return t
+}
+
+// FuncType returns the Go type analogous to dtype.
+// There is no guarantee about matching memory layout.
+func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
+ p := make([]*Type, len(dtype.ParamType))
+ gp := make([]*ast.Field, len(dtype.ParamType))
+ for i, f := range dtype.ParamType {
+ // gcc's DWARF generator outputs a single DotDotDotType parameter for
+ // function pointers that specify no parameters (e.g. void
+ // (*__cgo_0)()). Treat this special case as void. This case is
+ // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
+ // legal).
+ if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
+ p, gp = nil, nil
+ break
+ }
+ p[i] = c.FuncArg(f, pos)
+ gp[i] = &ast.Field{Type: p[i].Go}
+ }
+ var r *Type
+ var gr []*ast.Field
+ if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
+ gr = []*ast.Field{{Type: c.goVoid}}
+ } else if dtype.ReturnType != nil {
+ r = c.Type(dtype.ReturnType, pos)
+ gr = []*ast.Field{{Type: r.Go}}
+ }
+ return &FuncType{
+ Params: p,
+ Result: r,
+ Go: &ast.FuncType{
+ Params: &ast.FieldList{List: gp},
+ Results: &ast.FieldList{List: gr},
+ },
+ }
+}
+
+// Identifier
+func (c *typeConv) Ident(s string) *ast.Ident {
+ return ast.NewIdent(s)
+}
+
+// Opaque type of n bytes.
+func (c *typeConv) Opaque(n int64) ast.Expr {
+ return &ast.ArrayType{
+ Len: c.intExpr(n),
+ Elt: c.byte,
+ }
+}
+
+// Expr for integer n.
+func (c *typeConv) intExpr(n int64) ast.Expr {
+ return &ast.BasicLit{
+ Kind: token.INT,
+ Value: strconv.FormatInt(n, 10),
+ }
+}
+
+// Add padding of given size to fld.
+func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
+ n := len(fld)
+ fld = fld[0 : n+1]
+ fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
+ return fld
+}
+
+// Struct conversion: return Go and (6g) C syntax for type.
+func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
+ var buf bytes.Buffer
+ buf.WriteString("struct {")
+ fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
+ off := int64(0)
+
+ // Rename struct fields that happen to be named Go keywords into
+ // _{keyword}. Create a map from C ident -> Go ident. The Go ident will
+ // be mangled. Any existing identifier that already has the same name on
+ // the C-side will cause the Go-mangled version to be prefixed with _.
+ // (e.g. in a struct with fields '_type' and 'type', the latter would be
+ // rendered as '__type' in Go).
+ ident := make(map[string]string)
+ used := make(map[string]bool)
+ for _, f := range dt.Field {
+ ident[f.Name] = f.Name
+ used[f.Name] = true
+ }
+
+ if !*godefs && !*cdefs {
+ for cid, goid := range ident {
+ if token.Lookup(goid).IsKeyword() {
+ // Avoid keyword
+ goid = "_" + goid
+
+ // Also avoid existing fields
+ for _, exist := used[goid]; exist; _, exist = used[goid] {
+ goid = "_" + goid
+ }
+
+ used[goid] = true
+ ident[cid] = goid
+ }
+ }
+ }
+
+ anon := 0
+ for _, f := range dt.Field {
+ if f.ByteOffset > off {
+ fld = c.pad(fld, f.ByteOffset-off)
+ off = f.ByteOffset
+ }
+ t := c.Type(f.Type, pos)
+ tgo := t.Go
+ size := t.Size
+ talign := t.Align
+ if f.BitSize > 0 {
+ if f.BitSize%8 != 0 {
+ continue
+ }
+ size = f.BitSize / 8
+ name := tgo.(*ast.Ident).String()
+ if strings.HasPrefix(name, "int") {
+ name = "int"
+ } else {
+ name = "uint"
+ }
+ tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
+ talign = size
+ }
+
+ if talign > 0 && f.ByteOffset%talign != 0 {
+ // Drop misaligned fields, the same way we drop integer bit fields.
+ // The goal is to make available what can be made available.
+ // Otherwise one bad and unneeded field in an otherwise okay struct
+ // makes the whole program not compile. Much of the time these
+ // structs are in system headers that cannot be corrected.
+ continue
+ }
+ n := len(fld)
+ fld = fld[0 : n+1]
+ name := f.Name
+ if name == "" {
+ name = fmt.Sprintf("anon%d", anon)
+ anon++
+ ident[name] = name
+ }
+ fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
+ off += size
+ buf.WriteString(t.C.String())
+ buf.WriteString(" ")
+ buf.WriteString(name)
+ buf.WriteString("; ")
+ if talign > align {
+ align = talign
+ }
+ }
+ if off < dt.ByteSize {
+ fld = c.pad(fld, dt.ByteSize-off)
+ off = dt.ByteSize
+ }
+ if off != dt.ByteSize {
+ fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
+ }
+ buf.WriteString("}")
+ csyntax = buf.String()
+
+ if *godefs || *cdefs {
+ c.todoFlds = append(c.todoFlds, fld)
+ }
+ expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
+ return
+}
+
+func upper(s string) string {
+ if s == "" {
+ return ""
+ }
+ r, size := utf8.DecodeRuneInString(s)
+ if r == '_' {
+ return "X" + s
+ }
+ return string(unicode.ToUpper(r)) + s[size:]
+}
+
+// godefsFields rewrites field names for use in Go or C definitions.
+// It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
+// converts names to upper case, and rewrites _ into Pad_godefs_n,
+// so that all fields are exported.
+func godefsFields(fld []*ast.Field) {
+ prefix := fieldPrefix(fld)
+ npad := 0
+ for _, f := range fld {
+ for _, n := range f.Names {
+ if n.Name != prefix {
+ n.Name = strings.TrimPrefix(n.Name, prefix)
+ }
+ if n.Name == "_" {
+ // Use exported name instead.
+ n.Name = "Pad_cgo_" + strconv.Itoa(npad)
+ npad++
+ }
+ if !*cdefs {
+ n.Name = upper(n.Name)
+ }
+ }
+ p := &f.Type
+ t := *p
+ if star, ok := t.(*ast.StarExpr); ok {
+ star = &ast.StarExpr{X: star.X}
+ *p = star
+ p = &star.X
+ t = *p
+ }
+ if id, ok := t.(*ast.Ident); ok {
+ if id.Name == "unsafe.Pointer" {
+ *p = ast.NewIdent("*byte")
+ }
+ }
+ }
+}
+
+// fieldPrefix returns the prefix that should be removed from all the
+// field names when generating the C or Go code. For generated
+// C, we leave the names as is (tv_sec, tv_usec), since that's what
+// people are used to seeing in C. For generated Go code, such as
+// package syscall's data structures, we drop a common prefix
+// (so sec, usec, which will get turned into Sec, Usec for exporting).
+func fieldPrefix(fld []*ast.Field) string {
+ if *cdefs {
+ return ""
+ }
+ prefix := ""
+ for _, f := range fld {
+ for _, n := range f.Names {
+ // Ignore field names that don't have the prefix we're
+ // looking for. It is common in C headers to have fields
+ // named, say, _pad in an otherwise prefixed header.
+ // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
+ // still want to remove the tv_ prefix.
+ // The check for "orig_" here handles orig_eax in the
+ // x86 ptrace register sets, which otherwise have all fields
+ // with reg_ prefixes.
+ if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
+ continue
+ }
+ i := strings.Index(n.Name, "_")
+ if i < 0 {
+ continue
+ }
+ if prefix == "" {
+ prefix = n.Name[:i+1]
+ } else if prefix != n.Name[:i+1] {
+ return ""
+ }
+ }
+ }
+ return prefix
+}
diff --git a/libgo/go/cmd/cgo/godefs.go b/libgo/go/cmd/cgo/godefs.go
new file mode 100644
index 0000000..ce5ac27
--- /dev/null
+++ b/libgo/go/cmd/cgo/godefs.go
@@ -0,0 +1,294 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/printer"
+ "go/token"
+ "os"
+ "strings"
+)
+
+// godefs returns the output for -godefs mode.
+func (p *Package) godefs(f *File, srcfile string) string {
+ var buf bytes.Buffer
+
+ fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
+ fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
+ fmt.Fprintf(&buf, "\n")
+
+ override := make(map[string]string)
+
+ // Allow source file to specify override mappings.
+ // For example, the socket data structures refer
+ // to in_addr and in_addr6 structs but we want to be
+ // able to treat them as byte arrays, so the godefs
+ // inputs in package syscall say
+ //
+ // // +godefs map struct_in_addr [4]byte
+ // // +godefs map struct_in_addr6 [16]byte
+ //
+ for _, g := range f.Comments {
+ for _, c := range g.List {
+ i := strings.Index(c.Text, "+godefs map")
+ if i < 0 {
+ continue
+ }
+ s := strings.TrimSpace(c.Text[i+len("+godefs map"):])
+ i = strings.Index(s, " ")
+ if i < 0 {
+ fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text)
+ continue
+ }
+ override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:])
+ }
+ }
+ for _, n := range f.Name {
+ if s := override[n.Go]; s != "" {
+ override[n.Mangle] = s
+ }
+ }
+
+ // Otherwise, if the source file says type T C.whatever,
+ // use "T" as the mangling of C.whatever,
+ // except in the definition (handled at end of function).
+ refName := make(map[*ast.Expr]*Name)
+ for _, r := range f.Ref {
+ refName[r.Expr] = r.Name
+ }
+ for _, d := range f.AST.Decls {
+ d, ok := d.(*ast.GenDecl)
+ if !ok || d.Tok != token.TYPE {
+ continue
+ }
+ for _, s := range d.Specs {
+ s := s.(*ast.TypeSpec)
+ n := refName[&s.Type]
+ if n != nil && n.Mangle != "" {
+ override[n.Mangle] = s.Name.Name
+ }
+ }
+ }
+
+ // Extend overrides using typedefs:
+ // If we know that C.xxx should format as T
+ // and xxx is a typedef for yyy, make C.yyy format as T.
+ for typ, def := range typedef {
+ if new := override[typ]; new != "" {
+ if id, ok := def.Go.(*ast.Ident); ok {
+ override[id.Name] = new
+ }
+ }
+ }
+
+ // Apply overrides.
+ for old, new := range override {
+ if id := goIdent[old]; id != nil {
+ id.Name = new
+ }
+ }
+
+ // Any names still using the _C syntax are not going to compile,
+ // although in general we don't know whether they all made it
+ // into the file, so we can't warn here.
+ //
+ // The most common case is union types, which begin with
+ // _Ctype_union and for which typedef[name] is a Go byte
+ // array of the appropriate size (such as [4]byte).
+ // Substitute those union types with byte arrays.
+ for name, id := range goIdent {
+ if id.Name == name && strings.Contains(name, "_Ctype_union") {
+ if def := typedef[name]; def != nil {
+ id.Name = gofmt(def)
+ }
+ }
+ }
+
+ conf.Fprint(&buf, fset, f.AST)
+
+ return buf.String()
+}
+
+// cdefs returns the output for -cdefs mode.
+// The easiest way to do this is to translate the godefs Go to C.
+func (p *Package) cdefs(f *File, srcfile string) string {
+ godefsOutput := p.godefs(f, srcfile)
+
+ lines := strings.Split(godefsOutput, "\n")
+ lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
+
+ for i, line := range lines {
+ lines[i] = strings.TrimSpace(line)
+ }
+
+ var out bytes.Buffer
+ printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
+
+ didTypedef := false
+ for i := 0; i < len(lines); i++ {
+ line := lines[i]
+
+ // Delete
+ // package x
+ if strings.HasPrefix(line, "package ") {
+ continue
+ }
+
+ // Convert
+ // const (
+ // A = 1
+ // B = 2
+ // )
+ //
+ // to
+ //
+ // enum {
+ // A = 1,
+ // B = 2,
+ // };
+ if line == "const (" {
+ printf("enum {\n")
+ for i++; i < len(lines) && lines[i] != ")"; i++ {
+ line = lines[i]
+ if line != "" {
+ printf("\t%s,", line)
+ }
+ printf("\n")
+ }
+ printf("};\n")
+ continue
+ }
+
+ // Convert
+ // const A = 1
+ // to
+ // enum { A = 1 };
+ if strings.HasPrefix(line, "const ") {
+ printf("enum { %s };\n", line[len("const "):])
+ continue
+ }
+
+ // On first type definition, typedef all the structs
+ // in case there are dependencies between them.
+ if !didTypedef && strings.HasPrefix(line, "type ") {
+ didTypedef = true
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+ s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
+ printf("typedef struct %s %s;\n", s, s)
+ }
+ }
+ printf("\n")
+ printf("#pragma pack on\n")
+ printf("\n")
+ }
+
+ // Convert
+ // type T struct {
+ // X int64
+ // Y *int32
+ // Z [4]byte
+ // }
+ //
+ // to
+ //
+ // struct T {
+ // int64 X;
+ // int32 *Y;
+ // byte Z[4];
+ // }
+ if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
+ if len(lines) > i+1 && lines[i+1] == "}" {
+ // do not output empty struct
+ i++
+ continue
+ }
+ s := line[len("type ") : len(line)-len(" struct {")]
+ printf("struct %s {\n", s)
+ for i++; i < len(lines) && lines[i] != "}"; i++ {
+ line := lines[i]
+ if line != "" {
+ f := strings.Fields(line)
+ if len(f) != 2 {
+ fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
+ nerrors++
+ continue
+ }
+ printf("\t%s;", cdecl(f[0], f[1]))
+ }
+ printf("\n")
+ }
+ printf("};\n")
+ continue
+ }
+
+ // Convert
+ // type T int
+ // to
+ // typedef int T;
+ if strings.HasPrefix(line, "type ") {
+ f := strings.Fields(line[len("type "):])
+ if len(f) != 2 {
+ fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
+ nerrors++
+ continue
+ }
+ printf("typedef\t%s;\n", cdecl(f[0], f[1]))
+ continue
+ }
+
+ printf("%s\n", line)
+ }
+
+ if didTypedef {
+ printf("\n")
+ printf("#pragma pack off\n")
+ }
+
+ return out.String()
+}
+
+// cdecl returns the C declaration for the given Go name and type.
+// It only handles the specific cases necessary for converting godefs output.
+func cdecl(name, typ string) string {
+ // X *[0]byte -> X *void
+ if strings.HasPrefix(typ, "*[0]") {
+ typ = "*void"
+ }
+ // X [4]byte -> X[4] byte
+ for strings.HasPrefix(typ, "[") {
+ i := strings.Index(typ, "]") + 1
+ name = name + typ[:i]
+ typ = typ[i:]
+ }
+ // X *byte -> *X byte
+ for strings.HasPrefix(typ, "*") {
+ name = "*" + name
+ typ = typ[1:]
+ }
+ // X T -> T X
+ // Handle the special case: 'unsafe.Pointer' is 'void *'
+ if typ == "unsafe.Pointer" {
+ typ = "void"
+ name = "*" + name
+ }
+ return typ + "\t" + name
+}
+
+var gofmtBuf bytes.Buffer
+
+// gofmt returns the gofmt-formatted string for an AST node.
+func gofmt(n interface{}) string {
+ gofmtBuf.Reset()
+ err := printer.Fprint(&gofmtBuf, fset, n)
+ if err != nil {
+ return "<" + err.Error() + ">"
+ }
+ return gofmtBuf.String()
+}
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
new file mode 100644
index 0000000..ea4b9c2
--- /dev/null
+++ b/libgo/go/cmd/cgo/main.go
@@ -0,0 +1,360 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Cgo; see gmp.go for an overview.
+
+// TODO(rsc):
+// Emit correct line number annotations.
+// Make 6g understand the annotations.
+
+package main
+
+import (
+ "crypto/md5"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/printer"
+ "go/token"
+ "io"
+ "os"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "sort"
+ "strings"
+)
+
+// A Package collects information about the package we're going to write.
+type Package struct {
+ PackageName string // name of package
+ PackagePath string
+ PtrSize int64
+ IntSize int64
+ GccOptions []string
+ CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS)
+ Written map[string]bool
+ Name map[string]*Name // accumulated Name from Files
+ ExpFunc []*ExpFunc // accumulated ExpFunc from Files
+ Decl []ast.Decl
+ GoFiles []string // list of Go files
+ GccFiles []string // list of gcc output files
+ Preamble string // collected preamble for _cgo_export.h
+}
+
+// A File collects information about a single Go input file.
+type File struct {
+ AST *ast.File // parsed AST
+ Comments []*ast.CommentGroup // comments from file
+ Package string // Package name
+ Preamble string // C preamble (doc comment on import "C")
+ Ref []*Ref // all references to C.xxx in AST
+ ExpFunc []*ExpFunc // exported functions for this file
+ Name map[string]*Name // map from Go name to Name
+}
+
+func nameKeys(m map[string]*Name) []string {
+ var ks []string
+ for k := range m {
+ ks = append(ks, k)
+ }
+ sort.Strings(ks)
+ return ks
+}
+
+// A Ref refers to an expression of the form C.xxx in the AST.
+type Ref struct {
+ Name *Name
+ Expr *ast.Expr
+ Context string // "type", "expr", "call", or "call2"
+}
+
+func (r *Ref) Pos() token.Pos {
+ return (*r.Expr).Pos()
+}
+
+// A Name collects information about C.xxx.
+type Name struct {
+ Go string // name used in Go referring to package C
+ Mangle string // name used in generated Go
+ C string // name used in C
+ Define string // #define expansion
+ Kind string // "const", "type", "var", "fpvar", "func", "not-type"
+ Type *Type // the type of xxx
+ FuncType *FuncType
+ AddError bool
+ Const string // constant definition
+}
+
+// IsVar returns true if Kind is either "var" or "fpvar"
+func (n *Name) IsVar() bool {
+ return n.Kind == "var" || n.Kind == "fpvar"
+}
+
+// A ExpFunc is an exported function, callable from C.
+// Such functions are identified in the Go input file
+// by doc comments containing the line //export ExpName
+type ExpFunc struct {
+ Func *ast.FuncDecl
+ ExpName string // name to use from C
+}
+
+// A TypeRepr contains the string representation of a type.
+type TypeRepr struct {
+ Repr string
+ FormatArgs []interface{}
+}
+
+// A Type collects information about a type in both the C and Go worlds.
+type Type struct {
+ Size int64
+ Align int64
+ C *TypeRepr
+ Go ast.Expr
+ EnumValues map[string]int64
+ Typedef string
+}
+
+// A FuncType collects information about a function type in both the C and Go worlds.
+type FuncType struct {
+ Params []*Type
+ Result *Type
+ Go *ast.FuncType
+}
+
+func usage() {
+ fmt.Fprint(os.Stderr, "usage: cgo -- [compiler options] file.go ...\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
+var ptrSizeMap = map[string]int64{
+ "386": 4,
+ "amd64": 8,
+ "arm": 4,
+ "ppc64": 8,
+ "ppc64le": 8,
+ "s390x": 8,
+}
+
+var intSizeMap = map[string]int64{
+ "386": 4,
+ "amd64": 8,
+ "arm": 4,
+ "ppc64": 8,
+ "ppc64le": 8,
+ "s390x": 8,
+}
+
+var cPrefix string
+
+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 dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
+
+// These flags are for bootstrapping a new Go implementation,
+// to generate Go and C headers that match the data layout and
+// constant values used in the host's C libraries and system calls.
+var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
+var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
+var objDir = flag.String("objdir", "", "object directory")
+
+var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
+var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
+var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
+var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
+var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
+var goarch, goos string
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if *dynobj != "" {
+ // cgo -dynimport is essentially a separate helper command
+ // built into the cgo binary. It scans a gcc-produced executable
+ // and dumps information about the imported symbols and the
+ // imported libraries. The 'go build' rules for cgo prepare an
+ // appropriate executable and then use its import information
+ // instead of needing to make the linkers duplicate all the
+ // specialized knowledge gcc has about where to look for imported
+ // symbols and which ones to use.
+ dynimport(*dynobj)
+ return
+ }
+
+ if *godefs && *cdefs {
+ fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
+ os.Exit(2)
+ }
+
+ if *godefs || *cdefs {
+ // Generating definitions pulled from header files,
+ // to be checked into Go repositories.
+ // Line numbers are just noise.
+ conf.Mode &^= printer.SourcePos
+ }
+
+ args := flag.Args()
+ if len(args) < 1 {
+ usage()
+ }
+
+ // Find first arg that looks like a go file and assume everything before
+ // that are options to pass to gcc.
+ var i int
+ for i = len(args); i > 0; i-- {
+ if !strings.HasSuffix(args[i-1], ".go") {
+ break
+ }
+ }
+ if i == len(args) {
+ usage()
+ }
+
+ goFiles := args[i:]
+
+ p := newPackage(args[:i])
+
+ // Record CGO_LDFLAGS from the environment for external linking.
+ if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" {
+ args, err := splitQuoted(ldflags)
+ if err != nil {
+ fatalf("bad CGO_LDFLAGS: %q (%s)", ldflags, err)
+ }
+ p.addToFlag("LDFLAGS", args)
+ }
+
+ // Need a unique prefix for the global C symbols that
+ // we use to coordinate between gcc and ourselves.
+ // We already put _cgo_ at the beginning, so the main
+ // concern is other cgo wrappers for the same functions.
+ // Use the beginning of the md5 of the input to disambiguate.
+ h := md5.New()
+ for _, input := range goFiles {
+ f, err := os.Open(input)
+ if err != nil {
+ fatalf("%s", err)
+ }
+ io.Copy(h, f)
+ f.Close()
+ }
+ cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
+
+ fs := make([]*File, len(goFiles))
+ for i, input := range goFiles {
+ f := new(File)
+ f.ReadGo(input)
+ f.DiscardCgoDirectives()
+ fs[i] = f
+ }
+
+ if *objDir == "" {
+ // make sure that _obj directory exists, so that we can write
+ // all the output files there.
+ os.Mkdir("_obj", 0777)
+ *objDir = "_obj"
+ }
+ *objDir += string(filepath.Separator)
+
+ for i, input := range goFiles {
+ f := fs[i]
+ p.Translate(f)
+ for _, cref := range f.Ref {
+ switch cref.Context {
+ case "call", "call2":
+ if cref.Name.Kind != "type" {
+ break
+ }
+ *cref.Expr = cref.Name.Type.Go
+ }
+ }
+ if nerrors > 0 {
+ os.Exit(2)
+ }
+ pkg := f.Package
+ if dir := os.Getenv("CGOPKGPATH"); dir != "" {
+ pkg = filepath.Join(dir, pkg)
+ }
+ p.PackagePath = pkg
+ p.Record(f)
+ if *godefs {
+ os.Stdout.WriteString(p.godefs(f, input))
+ } else if *cdefs {
+ os.Stdout.WriteString(p.cdefs(f, input))
+ } else {
+ p.writeOutput(f, input)
+ }
+ }
+
+ if !*godefs && !*cdefs {
+ p.writeDefs()
+ }
+ if nerrors > 0 {
+ os.Exit(2)
+ }
+}
+
+// newPackage returns a new Package that will invoke
+// gcc with the additional arguments specified in args.
+func newPackage(args []string) *Package {
+ goarch = runtime.GOARCH
+ if s := os.Getenv("GOARCH"); s != "" {
+ goarch = s
+ }
+ goos = runtime.GOOS
+ if s := os.Getenv("GOOS"); s != "" {
+ goos = s
+ }
+ ptrSize := ptrSizeMap[goarch]
+ if ptrSize == 0 {
+ fatalf("unknown ptrSize for $GOARCH %q", goarch)
+ }
+ intSize := intSizeMap[goarch]
+ if intSize == 0 {
+ fatalf("unknown intSize for $GOARCH %q", goarch)
+ }
+
+ // Reset locale variables so gcc emits English errors [sic].
+ os.Setenv("LANG", "en_US.UTF-8")
+ os.Setenv("LC_ALL", "C")
+
+ p := &Package{
+ PtrSize: ptrSize,
+ IntSize: intSize,
+ CgoFlags: make(map[string][]string),
+ Written: make(map[string]bool),
+ }
+ p.addToFlag("CFLAGS", args)
+ return p
+}
+
+// Record what needs to be recorded about f.
+func (p *Package) Record(f *File) {
+ if p.PackageName == "" {
+ p.PackageName = f.Package
+ } else if p.PackageName != f.Package {
+ error_(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package)
+ }
+
+ if p.Name == nil {
+ p.Name = f.Name
+ } else {
+ for k, v := range f.Name {
+ if p.Name[k] == nil {
+ p.Name[k] = v
+ } else if !reflect.DeepEqual(p.Name[k], v) {
+ error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
+ }
+ }
+ }
+
+ if f.ExpFunc != nil {
+ p.ExpFunc = append(p.ExpFunc, f.ExpFunc...)
+ p.Preamble += "\n" + f.Preamble
+ }
+ p.Decl = append(p.Decl, f.AST.Decls...)
+}
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
new file mode 100644
index 0000000..76c7247
--- /dev/null
+++ b/libgo/go/cmd/cgo/out.go
@@ -0,0 +1,1299 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "debug/elf"
+ "debug/macho"
+ "debug/pe"
+ "fmt"
+ "go/ast"
+ "go/printer"
+ "go/token"
+ "os"
+ "sort"
+ "strings"
+)
+
+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")
+ fm := creat(*objDir + "_cgo_main.c")
+
+ var gccgoInit bytes.Buffer
+
+ fflg := creat(*objDir + "_cgo_flags")
+ for k, v := range p.CgoFlags {
+ 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)
+ }
+ }
+ }
+ fflg.Close()
+
+ // Write C main file for using gcc to resolve imports.
+ fmt.Fprintf(fm, "int main() { return 0; }\n")
+ if *importRuntimeCgo {
+ fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+ } else {
+ // If we're not importing runtime/cgo, we *are* runtime/cgo,
+ // which provides crosscall2. We just need a prototype.
+ fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
+ }
+ fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
+ fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
+
+ // Write second Go output: definitions of _C_xxx.
+ // In a separate file so that the import of "unsafe" does not
+ // pollute the original file.
+ fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
+ fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
+ fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
+ if *importSyscall {
+ fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
+ }
+ if !*gccgo && *importRuntimeCgo {
+ fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
+ }
+ fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
+ if *importSyscall {
+ fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
+ }
+
+ typedefNames := make([]string, 0, len(typedef))
+ for name := range typedef {
+ typedefNames = append(typedefNames, name)
+ }
+ sort.Strings(typedefNames)
+ for _, name := range typedefNames {
+ def := typedef[name]
+ fmt.Fprintf(fgo2, "type %s ", name)
+ conf.Fprint(fgo2, fset, def.Go)
+ fmt.Fprintf(fgo2, "\n\n")
+ }
+ if *gccgo {
+ fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
+ } else {
+ fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
+ }
+
+ if *gccgo {
+ fmt.Fprintf(fc, p.cPrologGccgo())
+ } else {
+ fmt.Fprintf(fc, cProlog)
+ }
+
+ gccgoSymbolPrefix := p.gccgoSymbolPrefix()
+
+ cVars := make(map[string]bool)
+ for _, key := range nameKeys(p.Name) {
+ n := p.Name[key]
+ if !n.IsVar() {
+ continue
+ }
+
+ 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)
+ }
+
+ 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, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
+ }
+ fmt.Fprintf(fc, "\n")
+
+ fmt.Fprintf(fgo2, "var %s ", n.Mangle)
+ conf.Fprint(fgo2, fset, node)
+ fmt.Fprintf(fgo2, "\n")
+ }
+ fmt.Fprintf(fc, "\n")
+
+ for _, key := range nameKeys(p.Name) {
+ n := p.Name[key]
+ if n.Const != "" {
+ fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
+ }
+ }
+ fmt.Fprintf(fgo2, "\n")
+
+ for _, key := range nameKeys(p.Name) {
+ n := p.Name[key]
+ if n.FuncType != nil {
+ p.writeDefsFunc(fc, fgo2, n)
+ }
+ }
+
+ if *gccgo {
+ p.writeGccgoExports(fgo2, fc, fm)
+ } else {
+ p.writeExports(fgo2, fc, fm)
+ }
+
+ init := gccgoInit.String()
+ if init != "" {
+ fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
+ fmt.Fprintln(fc, "static void init(void) {")
+ fmt.Fprint(fc, init)
+ fmt.Fprintln(fc, "}")
+ }
+
+ fgo2.Close()
+ fc.Close()
+}
+
+func dynimport(obj string) {
+ stdout := os.Stdout
+ if *dynout != "" {
+ f, err := os.Create(*dynout)
+ if err != nil {
+ fatalf("%s", err)
+ }
+ stdout = f
+ }
+
+ 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]))
+ }
+ }
+ }
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
+ }
+ for _, s := range sym {
+ targ := s.Name
+ if s.Version != "" {
+ targ += "#" + s.Version
+ }
+ fmt.Fprintf(stdout, "#pragma 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)
+ }
+ return
+ }
+
+ if f, err := macho.Open(obj); err == nil {
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
+ }
+ for _, s := range sym {
+ if len(s) > 0 && s[0] == '_' {
+ s = s[1:]
+ }
+ fmt.Fprintf(stdout, "#pragma 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)
+ }
+ return
+ }
+
+ if f, err := pe.Open(obj); err == nil {
+ sym, err := f.ImportedSymbols()
+ if err != nil {
+ fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
+ }
+ 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]))
+ }
+ return
+ }
+
+ fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
+}
+
+// Construct a gcc struct matching the 6c 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
+// input and output parameters.
+func (p *Package) structType(n *Name) (string, int64) {
+ var buf bytes.Buffer
+ fmt.Fprint(&buf, "struct {\n")
+ off := int64(0)
+ for i, t := range n.FuncType.Params {
+ if off%t.Align != 0 {
+ pad := t.Align - off%t.Align
+ fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+ off += pad
+ }
+ c := t.Typedef
+ if c == "" {
+ c = t.C.String()
+ }
+ fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
+ off += t.Size
+ }
+ if off%p.PtrSize != 0 {
+ pad := p.PtrSize - off%p.PtrSize
+ fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+ off += pad
+ }
+ if t := n.FuncType.Result; t != nil {
+ if off%t.Align != 0 {
+ pad := t.Align - off%t.Align
+ fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+ off += pad
+ }
+ qual := ""
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ qual = "const "
+ }
+ fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
+ off += t.Size
+ }
+ if off%p.PtrSize != 0 {
+ pad := p.PtrSize - off%p.PtrSize
+ fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
+ off += pad
+ }
+ if n.AddError {
+ fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n")
+ off += 2 * p.PtrSize
+ }
+ if off == 0 {
+ fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
+ }
+ fmt.Fprintf(&buf, "\t}")
+ return buf.String(), off
+}
+
+func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
+ name := n.Go
+ gtype := n.FuncType.Go
+ void := gtype.Results == nil || len(gtype.Results.List) == 0
+ if n.AddError {
+ // Add "error" to return type list.
+ // Type list is known to be 0 or 1 element - it's a C function.
+ err := &ast.Field{Type: ast.NewIdent("error")}
+ l := gtype.Results.List
+ if len(l) == 0 {
+ l = []*ast.Field{err}
+ } else {
+ l = []*ast.Field{l[0], err}
+ }
+ t := new(ast.FuncType)
+ *t = *gtype
+ t.Results = &ast.FieldList{List: l}
+ gtype = t
+ }
+
+ // Go func declaration.
+ d := &ast.FuncDecl{
+ Name: ast.NewIdent(n.Mangle),
+ Type: gtype,
+ }
+
+ // Builtins defined in the C prolog.
+ inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
+
+ if *gccgo {
+ // Gccgo style hooks.
+ fmt.Fprint(fgo2, "\n")
+ 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.Fprint(fgo2, " {\n")
+ if !inProlog {
+ fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
+ fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
+ }
+ if n.AddError {
+ fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
+ }
+ fmt.Fprint(fgo2, "\t")
+ if !void {
+ fmt.Fprint(fgo2, "r := ")
+ }
+ fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
+
+ if n.AddError {
+ fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
+ fmt.Fprint(fgo2, "\tif e != 0 {\n")
+ fmt.Fprint(fgo2, "\t\treturn ")
+ if !void {
+ fmt.Fprint(fgo2, "r, ")
+ }
+ fmt.Fprint(fgo2, "e\n")
+ fmt.Fprint(fgo2, "\t}\n")
+ fmt.Fprint(fgo2, "\treturn ")
+ if !void {
+ fmt.Fprint(fgo2, "r, ")
+ }
+ fmt.Fprint(fgo2, "nil\n")
+ } else if !void {
+ fmt.Fprint(fgo2, "\treturn r\n")
+ }
+
+ fmt.Fprint(fgo2, "}\n")
+
+ // declare the C function.
+ fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
+ d.Name = ast.NewIdent(cname)
+ if n.AddError {
+ 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 inProlog {
+ return
+ }
+
+ var argSize int64
+ _, argSize = p.structType(n)
+
+ // C wrapper calls into gcc, passing a pointer to the argument frame.
+ fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
+ fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
+ fmt.Fprintf(fc, "\n")
+ fmt.Fprintf(fc, "void\n")
+ if argSize == 0 {
+ argSize++
+ }
+ // TODO(rsc): The struct here should declare pointers only where
+ // there are pointers in the actual argument frame.
+ // This is a workaround for golang.org/issue/6397.
+ fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
+ if n := argSize / p.PtrSize; n > 0 {
+ fmt.Fprintf(fc, "void *y[%d];", n)
+ }
+ if n := argSize % p.PtrSize; n > 0 {
+ fmt.Fprintf(fc, "uint8 x[%d];", n)
+ }
+ fmt.Fprintf(fc, "}p)\n")
+ fmt.Fprintf(fc, "{\n")
+ fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
+ if n.AddError {
+ // gcc leaves errno in first word of interface at end of p.
+ // check whether it is zero; if so, turn interface into nil.
+ // if not, turn interface into errno.
+ // Go init function initializes ·_Cerrno with an os.Errno
+ // for us to copy.
+ fmt.Fprintln(fc, ` {
+ int32 e;
+ void **v;
+ v = (void**)(&p+1) - 2; /* v = final two void* of p */
+ e = *(int32*)v;
+ v[0] = (void*)0xdeadbeef;
+ v[1] = (void*)0xdeadbeef;
+ if(e == 0) {
+ /* nil interface */
+ v[0] = 0;
+ v[1] = 0;
+ } else {
+ ·_Cerrno(v, e); /* fill in v as error for errno e */
+ }
+ }`)
+ }
+ fmt.Fprintf(fc, "}\n")
+ fmt.Fprintf(fc, "\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.)
+func (p *Package) writeOutput(f *File, srcfile string) {
+ base := srcfile
+ if strings.HasSuffix(base, ".go") {
+ base = base[0 : len(base)-3]
+ }
+ base = strings.Map(slashToUnderscore, base)
+ fgo1 := creat(*objDir + base + ".cgo1.go")
+ fgcc := creat(*objDir + base + ".cgo2.c")
+
+ p.GoFiles = append(p.GoFiles, base+".cgo1.go")
+ p.GccFiles = append(p.GccFiles, base+".cgo2.c")
+
+ // Write Go output: Go input with rewrites of C.xxx to _C_xxx.
+ 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.
+ // Gcc output starts with the preamble.
+ fmt.Fprintf(fgcc, "%s\n", f.Preamble)
+ fmt.Fprintf(fgcc, "%s\n", gccProlog)
+
+ for _, key := range nameKeys(f.Name) {
+ n := f.Name[key]
+ if n.FuncType != nil {
+ p.writeOutputFunc(fgcc, n)
+ }
+ }
+
+ fgo1.Close()
+ fgcc.Close()
+}
+
+// fixGo converts the internal Name.Go field into the name we should show
+// to users in error messages. There's only one for now: on input we rewrite
+// C.malloc into C._CMalloc, so change it back here.
+func fixGo(name string) string {
+ if name == "_CMalloc" {
+ return "malloc"
+ }
+ return name
+}
+
+var isBuiltin = map[string]bool{
+ "_Cfunc_CString": true,
+ "_Cfunc_GoString": true,
+ "_Cfunc_GoStringN": true,
+ "_Cfunc_GoBytes": true,
+ "_Cfunc__CMalloc": true,
+}
+
+func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
+ name := n.Mangle
+ if isBuiltin[name] || p.Written[name] {
+ // The builtins are already defined in the C prolog, and we don't
+ // want to duplicate function definitions we've already done.
+ return
+ }
+ p.Written[name] = true
+
+ if *gccgo {
+ p.writeGccgoOutputFunc(fgcc, n)
+ return
+ }
+
+ ctype, _ := p.structType(n)
+
+ // Gcc wrapper unpacks the C argument struct
+ // and calls the actual C function.
+ fmt.Fprintf(fgcc, "void\n")
+ fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
+ fmt.Fprintf(fgcc, "{\n")
+ if n.AddError {
+ fmt.Fprintf(fgcc, "\terrno = 0;\n")
+ }
+ // We're trying to write a gcc struct that matches 6c/8c/5c'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())
+ fmt.Fprintf(fgcc, "\t")
+ if t := n.FuncType.Result; t != nil {
+ fmt.Fprintf(fgcc, "a->r = ")
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
+ }
+ }
+ fmt.Fprintf(fgcc, "%s(", n.C)
+ for i, t := range n.FuncType.Params {
+ if i > 0 {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ // We know the type params are correct, because
+ // the Go equivalents had good type params.
+ // However, our version of the type omits the magic
+ // words const and volatile, which can provoke
+ // C compiler warnings. Silence them by casting
+ // all pointers to void*. (Eventually that will produce
+ // other warnings.)
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(void*)")
+ }
+ fmt.Fprintf(fgcc, "a->p%d", i)
+ }
+ fmt.Fprintf(fgcc, ");\n")
+ if n.AddError {
+ fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
+ }
+ fmt.Fprintf(fgcc, "}\n")
+ fmt.Fprintf(fgcc, "\n")
+}
+
+// Write out a wrapper for a function when using gccgo. This is a
+// simple wrapper that just calls the real function. We only need a
+// wrapper to support static functions in the prologue--without a
+// wrapper, we can't refer to the function, since the reference is in
+// a different file.
+func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
+ if t := n.FuncType.Result; t != nil {
+ fmt.Fprintf(fgcc, "%s\n", t.C.String())
+ } else {
+ fmt.Fprintf(fgcc, "void\n")
+ }
+ fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
+ for i, t := range n.FuncType.Params {
+ if i > 0 {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ c := t.Typedef
+ if c == "" {
+ c = t.C.String()
+ }
+ fmt.Fprintf(fgcc, "%s p%d", c, i)
+ }
+ fmt.Fprintf(fgcc, ")\n")
+ fmt.Fprintf(fgcc, "{\n")
+ fmt.Fprintf(fgcc, "\t")
+ if t := n.FuncType.Result; t != nil {
+ fmt.Fprintf(fgcc, "return ")
+ // Cast to void* to avoid warnings due to omitted qualifiers.
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(void*)")
+ }
+ }
+ fmt.Fprintf(fgcc, "%s(", n.C)
+ for i, t := range n.FuncType.Params {
+ if i > 0 {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ // Cast to void* to avoid warnings due to omitted qualifiers.
+ if c := t.C.String(); c[len(c)-1] == '*' {
+ fmt.Fprintf(fgcc, "(void*)")
+ }
+ fmt.Fprintf(fgcc, "p%d", i)
+ }
+ fmt.Fprintf(fgcc, ");\n")
+ fmt.Fprintf(fgcc, "}\n")
+ fmt.Fprintf(fgcc, "\n")
+}
+
+// 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.
+// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
+// and http://golang.org/issue/5603.
+func (p *Package) packedAttribute() string {
+ s := "__attribute__((__packed__"
+ if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
+ s += ", __gcc_struct__"
+ }
+ return s + "))"
+}
+
+// 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())
+
+ fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
+ fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
+
+ fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
+
+ for _, exp := range p.ExpFunc {
+ fn := exp.Func
+
+ // Construct a gcc struct matching the 6c argument and
+ // result frame. The gcc struct will be compiled with
+ // __attribute__((packed)) so all padding must be accounted
+ // for explicitly.
+ ctype := "struct {\n"
+ off := int64(0)
+ npad := 0
+ if fn.Recv != nil {
+ t := p.cgoType(fn.Recv.List[0].Type)
+ ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
+ off += t.Size
+ }
+ fntype := fn.Type
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ t := p.cgoType(atype)
+ if off%t.Align != 0 {
+ pad := t.Align - off%t.Align
+ ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+ off += pad
+ npad++
+ }
+ ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
+ off += t.Size
+ })
+ if off%p.PtrSize != 0 {
+ pad := p.PtrSize - off%p.PtrSize
+ ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+ off += pad
+ npad++
+ }
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ t := p.cgoType(atype)
+ if off%t.Align != 0 {
+ pad := t.Align - off%t.Align
+ ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+ off += pad
+ npad++
+ }
+ ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
+ off += t.Size
+ })
+ if off%p.PtrSize != 0 {
+ pad := p.PtrSize - off%p.PtrSize
+ ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
+ off += pad
+ npad++
+ }
+ if ctype == "struct {\n" {
+ ctype += "\t\tchar unused;\n" // avoid empty struct
+ }
+ ctype += "\t}"
+
+ // Get the return type of the wrapper function
+ // compiled by gcc.
+ gccResult := ""
+ if fntype.Results == nil || len(fntype.Results.List) == 0 {
+ gccResult = "void"
+ } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
+ gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
+ } else {
+ fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
+ fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
+ })
+ fmt.Fprintf(fgcch, "};\n")
+ gccResult = "struct " + exp.ExpName + "_return"
+ }
+
+ // Build the wrapper function compiled by gcc.
+ s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
+ if fn.Recv != nil {
+ s += p.cgoType(fn.Recv.List[0].Type).C.String()
+ s += " recv"
+ }
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 || fn.Recv != nil {
+ s += ", "
+ }
+ s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
+ })
+ s += ")"
+ 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%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)
+ }
+ if fn.Recv != nil {
+ fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
+ }
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
+ })
+ fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
+ if gccResult != "void" {
+ if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
+ fmt.Fprintf(fgcc, "\treturn a.r0;\n")
+ } else {
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
+ })
+ fmt.Fprintf(fgcc, "\treturn r;\n")
+ }
+ }
+ fmt.Fprintf(fgcc, "}\n")
+
+ // Build the wrapper function compiled by 6c/8c
+ 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(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
+
+ // Calling a function with a receiver from C requires
+ // a Go wrapper function.
+ if fn.Recv != nil {
+ fmt.Fprintf(fgo2, "func %s(recv ", goname)
+ conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ fmt.Fprintf(fgo2, ", p%d ", i)
+ conf.Fprint(fgo2, fset, atype)
+ })
+ fmt.Fprintf(fgo2, ")")
+ if gccResult != "void" {
+ fmt.Fprint(fgo2, " (")
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ if i > 0 {
+ fmt.Fprint(fgo2, ", ")
+ }
+ conf.Fprint(fgo2, fset, atype)
+ })
+ fmt.Fprint(fgo2, ")")
+ }
+ fmt.Fprint(fgo2, " {\n")
+ fmt.Fprint(fgo2, "\t")
+ if gccResult != "void" {
+ fmt.Fprint(fgo2, "return ")
+ }
+ fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 {
+ fmt.Fprint(fgo2, ", ")
+ }
+ fmt.Fprintf(fgo2, "p%d", i)
+ })
+ fmt.Fprint(fgo2, ")\n")
+ fmt.Fprint(fgo2, "}\n")
+ }
+ }
+}
+
+// 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")
+
+ 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())
+
+ 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")
+
+ for _, exp := range p.ExpFunc {
+ fn := exp.Func
+ fntype := fn.Type
+
+ cdeclBuf := new(bytes.Buffer)
+ resultCount := 0
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) { resultCount++ })
+ switch resultCount {
+ case 0:
+ fmt.Fprintf(cdeclBuf, "void")
+ case 1:
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ t := p.cgoType(atype)
+ fmt.Fprintf(cdeclBuf, "%s", t.C)
+ })
+ default:
+ // Declare a result struct.
+ fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ t := p.cgoType(atype)
+ fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
+ })
+ fmt.Fprintf(fgcch, "};\n")
+ fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
+ }
+
+ cRet := cdeclBuf.String()
+
+ cdeclBuf = new(bytes.Buffer)
+ fmt.Fprintf(cdeclBuf, "(")
+ if fn.Recv != nil {
+ fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
+ }
+ // Function parameters.
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 || fn.Recv != nil {
+ fmt.Fprintf(cdeclBuf, ", ")
+ }
+ t := p.cgoType(atype)
+ fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
+ })
+ fmt.Fprintf(cdeclBuf, ")")
+ cParams := cdeclBuf.String()
+
+ // 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
+ // code.
+ goName := "Cgoexp_" + exp.ExpName
+ fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
+ fmt.Fprint(fgcch, "\n")
+
+ // Use a #define so that the C code that includes
+ // cgo_export.h will be able to refer to the Go
+ // function using the expected name.
+ fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName)
+
+ // Use a #undef in _cgo_export.c so that we ignore the
+ // #define from cgo_export.h, since here we are
+ // defining the real function.
+ fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName)
+
+ fmt.Fprint(fgcc, "\n")
+ fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
+ fmt.Fprint(fgcc, "\t")
+ if resultCount > 0 {
+ fmt.Fprint(fgcc, "return ")
+ }
+ fmt.Fprintf(fgcc, "%s(", goName)
+ if fn.Recv != nil {
+ fmt.Fprint(fgcc, "recv")
+ }
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 || fn.Recv != nil {
+ fmt.Fprintf(fgcc, ", ")
+ }
+ fmt.Fprintf(fgcc, "p%d", i)
+ })
+ fmt.Fprint(fgcc, ");\n")
+ fmt.Fprint(fgcc, "}\n")
+
+ // Dummy declaration for _cgo_main.c
+ fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
+
+ // For gccgo we use a wrapper function in Go, in order
+ // to call CgocallBack and CgocallBackDone.
+
+ // This code uses printer.Fprint, not conf.Fprint,
+ // because we don't want //line comments in the middle
+ // of the function types.
+ fmt.Fprint(fgo2, "\n")
+ fmt.Fprintf(fgo2, "func %s(", goName)
+ if fn.Recv != nil {
+ fmt.Fprint(fgo2, "recv ")
+ printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+ }
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 || fn.Recv != nil {
+ fmt.Fprintf(fgo2, ", ")
+ }
+ fmt.Fprintf(fgo2, "p%d ", i)
+ printer.Fprint(fgo2, fset, atype)
+ })
+ fmt.Fprintf(fgo2, ")")
+ if resultCount > 0 {
+ fmt.Fprintf(fgo2, " (")
+ forFieldList(fntype.Results,
+ func(i int, atype ast.Expr) {
+ if i > 0 {
+ fmt.Fprint(fgo2, ", ")
+ }
+ printer.Fprint(fgo2, fset, atype)
+ })
+ fmt.Fprint(fgo2, ")")
+ }
+ fmt.Fprint(fgo2, " {\n")
+ fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
+ fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
+ fmt.Fprint(fgo2, "\t")
+ if resultCount > 0 {
+ fmt.Fprint(fgo2, "return ")
+ }
+ if fn.Recv != nil {
+ fmt.Fprint(fgo2, "recv.")
+ }
+ fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
+ forFieldList(fntype.Params,
+ func(i int, atype ast.Expr) {
+ if i > 0 {
+ fmt.Fprint(fgo2, ", ")
+ }
+ fmt.Fprintf(fgo2, "p%d", i)
+ })
+ fmt.Fprint(fgo2, ")\n")
+ fmt.Fprint(fgo2, "}\n")
+ }
+}
+
+// Return the package prefix when using gccgo.
+func (p *Package) gccgoSymbolPrefix() string {
+ if !*gccgo {
+ return ""
+ }
+
+ clean := func(r rune) rune {
+ switch {
+ case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
+ '0' <= r && r <= '9':
+ return r
+ }
+ return '_'
+ }
+
+ if *gccgopkgpath != "" {
+ return strings.Map(clean, *gccgopkgpath)
+ }
+ if *gccgoprefix == "" && p.PackageName == "main" {
+ return "main"
+ }
+ prefix := strings.Map(clean, *gccgoprefix)
+ if prefix == "" {
+ prefix = "go"
+ }
+ return prefix + "." + p.PackageName
+}
+
+// Call a function for each entry in an ast.FieldList, passing the
+// index into the list and the type.
+func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
+ if fl == nil {
+ return
+ }
+ i := 0
+ for _, r := range fl.List {
+ if r.Names == nil {
+ fn(i, r.Type)
+ i++
+ } else {
+ for _ = range r.Names {
+ fn(i, r.Type)
+ i++
+ }
+ }
+ }
+}
+
+func c(repr string, args ...interface{}) *TypeRepr {
+ return &TypeRepr{repr, args}
+}
+
+// Map predeclared Go types to Type.
+var goTypes = map[string]*Type{
+ "bool": {Size: 1, Align: 1, C: c("GoUint8")},
+ "byte": {Size: 1, Align: 1, C: c("GoUint8")},
+ "int": {Size: 0, Align: 0, C: c("GoInt")},
+ "uint": {Size: 0, Align: 0, C: c("GoUint")},
+ "rune": {Size: 4, Align: 4, C: c("GoInt32")},
+ "int8": {Size: 1, Align: 1, C: c("GoInt8")},
+ "uint8": {Size: 1, Align: 1, C: c("GoUint8")},
+ "int16": {Size: 2, Align: 2, C: c("GoInt16")},
+ "uint16": {Size: 2, Align: 2, C: c("GoUint16")},
+ "int32": {Size: 4, Align: 4, C: c("GoInt32")},
+ "uint32": {Size: 4, Align: 4, C: c("GoUint32")},
+ "int64": {Size: 8, Align: 8, C: c("GoInt64")},
+ "uint64": {Size: 8, Align: 8, C: c("GoUint64")},
+ "float32": {Size: 4, Align: 4, C: c("GoFloat32")},
+ "float64": {Size: 8, Align: 8, C: c("GoFloat64")},
+ "complex64": {Size: 8, Align: 8, C: c("GoComplex64")},
+ "complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
+}
+
+// Map an ast type to a Type.
+func (p *Package) cgoType(e ast.Expr) *Type {
+ switch t := e.(type) {
+ case *ast.StarExpr:
+ x := p.cgoType(t.X)
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
+ case *ast.ArrayType:
+ if t.Len == nil {
+ // Slice: pointer, len, cap.
+ return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")}
+ }
+ case *ast.StructType:
+ // TODO
+ case *ast.FuncType:
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
+ case *ast.InterfaceType:
+ return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+ case *ast.MapType:
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
+ case *ast.ChanType:
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
+ case *ast.Ident:
+ // Look up the type in the top level declarations.
+ // TODO: Handle types defined within a function.
+ for _, d := range p.Decl {
+ gd, ok := d.(*ast.GenDecl)
+ if !ok || gd.Tok != token.TYPE {
+ continue
+ }
+ for _, spec := range gd.Specs {
+ ts, ok := spec.(*ast.TypeSpec)
+ if !ok {
+ continue
+ }
+ if ts.Name.Name == t.Name {
+ return p.cgoType(ts.Type)
+ }
+ }
+ }
+ if def := typedef[t.Name]; def != nil {
+ return def
+ }
+ if t.Name == "uintptr" {
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
+ }
+ if t.Name == "string" {
+ // The string data is 1 pointer + 1 (pointer-sized) int.
+ return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
+ }
+ if t.Name == "error" {
+ return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+ }
+ if r, ok := goTypes[t.Name]; ok {
+ if r.Size == 0 { // int or uint
+ rr := new(Type)
+ *rr = *r
+ rr.Size = p.IntSize
+ rr.Align = p.IntSize
+ r = rr
+ }
+ if r.Align > p.PtrSize {
+ r.Align = p.PtrSize
+ }
+ return r
+ }
+ error_(e.Pos(), "unrecognized Go type %s", t.Name)
+ return &Type{Size: 4, Align: 4, C: c("int")}
+ case *ast.SelectorExpr:
+ id, ok := t.X.(*ast.Ident)
+ if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
+ return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
+ }
+ }
+ error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
+ return &Type{Size: 4, Align: 4, C: c("int")}
+}
+
+const gccProlog = `
+// Usual nonsense: if x and y are not equal, the type will be invalid
+// (have a negative array count) and an inscrutable error will come
+// out of the compiler and hopefully mention "name".
+#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
+
+// Check at compile time that the sizes we use match our expectations.
+#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
+
+__cgo_size_assert(char, 1)
+__cgo_size_assert(short, 2)
+__cgo_size_assert(int, 4)
+typedef long long __cgo_long_long;
+__cgo_size_assert(__cgo_long_long, 8)
+__cgo_size_assert(float, 4)
+__cgo_size_assert(double, 8)
+
+#include <errno.h>
+#include <string.h>
+`
+
+const builtinProlog = `
+#include <sys/types.h> /* for size_t below */
+
+/* Define intgo when compiling with GCC. */
+#ifdef __PTRDIFF_TYPE__
+typedef __PTRDIFF_TYPE__ intgo;
+#elif defined(_LP64)
+typedef long long intgo;
+#else
+typedef int intgo;
+#endif
+
+typedef struct { char *p; intgo n; } _GoString_;
+typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
+_GoString_ GoString(char *p);
+_GoString_ GoStringN(char *p, int l);
+_GoBytes_ GoBytes(void *p, int n);
+char *CString(_GoString_);
+void *_CMalloc(size_t);
+`
+
+const cProlog = `
+#include "runtime.h"
+#include "cgocall.h"
+
+void ·_Cerrno(void*, int32);
+
+void
+·_Cfunc_GoString(int8 *p, String s)
+{
+ s = runtime·gostring((byte*)p);
+ FLUSH(&s);
+}
+
+void
+·_Cfunc_GoStringN(int8 *p, int32 l, String s)
+{
+ s = runtime·gostringn((byte*)p, l);
+ FLUSH(&s);
+}
+
+void
+·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
+{
+ s = runtime·gobytes((byte*)p, l);
+ FLUSH(&s);
+}
+
+void
+·_Cfunc_CString(String s, int8 *p)
+{
+ p = runtime·cmalloc(s.len+1);
+ runtime·memmove((byte*)p, s.str, s.len);
+ p[s.len] = 0;
+ FLUSH(&p);
+}
+
+void
+·_Cfunc__CMalloc(uintptr n, int8 *p)
+{
+ p = runtime·cmalloc(n);
+ FLUSH(&p);
+}
+`
+
+func (p *Package) cPrologGccgo() string {
+ return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
+}
+
+const cPrologGccgo = `
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char byte;
+typedef intptr_t intgo;
+
+struct __go_string {
+ const unsigned char *__data;
+ intgo __length;
+};
+
+typedef struct __go_open_array {
+ void* __values;
+ intgo __count;
+ intgo __capacity;
+} Slice;
+
+struct __go_string __go_byte_array_to_string(const void* p, intgo len);
+struct __go_open_array __go_string_to_byte_array (struct __go_string str);
+
+const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
+ char *p = malloc(s.__length+1);
+ memmove(p, s.__data, s.__length);
+ p[s.__length] = 0;
+ return p;
+}
+
+struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
+ intgo len = (p != NULL) ? strlen(p) : 0;
+ return __go_byte_array_to_string(p, len);
+}
+
+struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
+ return __go_byte_array_to_string(p, n);
+}
+
+Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
+ struct __go_string s = { (const unsigned char *)p, n };
+ return __go_string_to_byte_array(s);
+}
+
+extern void runtime_throw(const char *);
+void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
+ void *p = malloc(n);
+ if(p == NULL && n == 0)
+ p = malloc(1);
+ if(p == NULL)
+ runtime_throw("runtime: C malloc failed");
+ return p;
+}
+`
+
+func (p *Package) gccExportHeaderProlog() string {
+ return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
+}
+
+const gccExportHeaderProlog = `
+typedef signed char GoInt8;
+typedef unsigned char GoUint8;
+typedef short GoInt16;
+typedef unsigned short GoUint16;
+typedef int GoInt32;
+typedef unsigned int GoUint32;
+typedef long long GoInt64;
+typedef unsigned long long GoUint64;
+typedef GoIntGOINTBITS GoInt;
+typedef GoUintGOINTBITS GoUint;
+typedef __SIZE_TYPE__ GoUintptr;
+typedef float GoFloat32;
+typedef double GoFloat64;
+typedef __complex float GoComplex64;
+typedef __complex double GoComplex128;
+
+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;
+`
diff --git a/libgo/go/cmd/cgo/util.go b/libgo/go/cmd/cgo/util.go
new file mode 100644
index 0000000..4e7800d
--- /dev/null
+++ b/libgo/go/cmd/cgo/util.go
@@ -0,0 +1,84 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/token"
+ "os"
+ "os/exec"
+)
+
+// run runs the command argv, feeding in stdin on standard input.
+// It returns the output to standard output and standard error.
+// ok indicates whether the command exited successfully.
+func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
+ p := exec.Command(argv[0], argv[1:]...)
+ p.Stdin = bytes.NewReader(stdin)
+ var bout, berr bytes.Buffer
+ p.Stdout = &bout
+ p.Stderr = &berr
+ err := p.Run()
+ if _, ok := err.(*exec.ExitError); err != nil && !ok {
+ fatalf("%s", err)
+ }
+ ok = p.ProcessState.Success()
+ stdout, stderr = bout.Bytes(), berr.Bytes()
+ return
+}
+
+func lineno(pos token.Pos) string {
+ return fset.Position(pos).String()
+}
+
+// Die with an error message.
+func fatalf(msg string, args ...interface{}) {
+ // If we've already printed other errors, they might have
+ // caused the fatal condition. Assume they're enough.
+ if nerrors == 0 {
+ fmt.Fprintf(os.Stderr, msg+"\n", args...)
+ }
+ os.Exit(2)
+}
+
+var nerrors int
+
+func error_(pos token.Pos, msg string, args ...interface{}) {
+ nerrors++
+ if pos.IsValid() {
+ fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String())
+ }
+ fmt.Fprintf(os.Stderr, msg, args...)
+ fmt.Fprintf(os.Stderr, "\n")
+}
+
+// isName returns true if s is a valid C identifier
+func isName(s string) bool {
+ for i, v := range s {
+ if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') {
+ return false
+ }
+ if i == 0 && '0' <= v && v <= '9' {
+ return false
+ }
+ }
+ return s != ""
+}
+
+func creat(name string) *os.File {
+ f, err := os.Create(name)
+ if err != nil {
+ fatalf("%s", err)
+ }
+ return f
+}
+
+func slashToUnderscore(c rune) rune {
+ if c == '/' || c == '\\' || c == ':' {
+ c = '_'
+ }
+ return c
+}