github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/cmd/cgo/out.go (about)

     1  // Copyright 2009 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"debug/elf"
    10  	"debug/macho"
    11  	"debug/pe"
    12  	"fmt"
    13  	"go/ast"
    14  	"go/printer"
    15  	"go/token"
    16  	"io"
    17  	"os"
    18  	"sort"
    19  	"strings"
    20  )
    21  
    22  var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
    23  
    24  // writeDefs creates output files to be compiled by 6g, 6c, and gcc.
    25  // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
    26  func (p *Package) writeDefs() {
    27  	var fgo2, fc io.Writer
    28  	f := creat(*objDir + "_cgo_gotypes.go")
    29  	defer f.Close()
    30  	fgo2 = f
    31  	if *gccgo {
    32  		f := creat(*objDir + "_cgo_defun.c")
    33  		defer f.Close()
    34  		fc = f
    35  	}
    36  	fm := creat(*objDir + "_cgo_main.c")
    37  
    38  	var gccgoInit bytes.Buffer
    39  
    40  	fflg := creat(*objDir + "_cgo_flags")
    41  	for k, v := range p.CgoFlags {
    42  		fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
    43  		if k == "LDFLAGS" && !*gccgo {
    44  			for _, arg := range v {
    45  				fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
    46  			}
    47  		}
    48  	}
    49  	fflg.Close()
    50  
    51  	// Write C main file for using gcc to resolve imports.
    52  	fmt.Fprintf(fm, "int main() { return 0; }\n")
    53  	if *importRuntimeCgo {
    54  		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
    55  		fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
    56  	} else {
    57  		// If we're not importing runtime/cgo, we *are* runtime/cgo,
    58  		// which provides crosscall2.  We just need a prototype.
    59  		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
    60  	}
    61  	fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
    62  	fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
    63  
    64  	// Write second Go output: definitions of _C_xxx.
    65  	// In a separate file so that the import of "unsafe" does not
    66  	// pollute the original file.
    67  	fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
    68  	fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
    69  	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
    70  	if !*gccgo && *importRuntimeCgo {
    71  		fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
    72  	}
    73  	if *importSyscall {
    74  		fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
    75  		fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
    76  	}
    77  	fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
    78  
    79  	typedefNames := make([]string, 0, len(typedef))
    80  	for name := range typedef {
    81  		typedefNames = append(typedefNames, name)
    82  	}
    83  	sort.Strings(typedefNames)
    84  	for _, name := range typedefNames {
    85  		def := typedef[name]
    86  		fmt.Fprintf(fgo2, "type %s ", name)
    87  		conf.Fprint(fgo2, fset, def.Go)
    88  		fmt.Fprintf(fgo2, "\n\n")
    89  	}
    90  	if *gccgo {
    91  		fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
    92  	} else {
    93  		fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
    94  	}
    95  
    96  	if *gccgo {
    97  		fmt.Fprint(fc, p.cPrologGccgo())
    98  	} else {
    99  		fmt.Fprint(fgo2, goProlog)
   100  	}
   101  
   102  	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
   103  
   104  	cVars := make(map[string]bool)
   105  	for _, key := range nameKeys(p.Name) {
   106  		n := p.Name[key]
   107  		if !n.IsVar() {
   108  			continue
   109  		}
   110  
   111  		if !cVars[n.C] {
   112  			fmt.Fprintf(fm, "extern char %s[];\n", n.C)
   113  			fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
   114  			if *gccgo {
   115  				fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
   116  			} else {
   117  				fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
   118  				fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
   119  				fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
   120  			}
   121  			cVars[n.C] = true
   122  		}
   123  
   124  		var node ast.Node
   125  		if n.Kind == "var" {
   126  			node = &ast.StarExpr{X: n.Type.Go}
   127  		} else if n.Kind == "fpvar" {
   128  			node = n.Type.Go
   129  		} else {
   130  			panic(fmt.Errorf("invalid var kind %q", n.Kind))
   131  		}
   132  		if *gccgo {
   133  			fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
   134  			fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
   135  			fmt.Fprintf(fc, "\n")
   136  		}
   137  
   138  		fmt.Fprintf(fgo2, "var %s ", n.Mangle)
   139  		conf.Fprint(fgo2, fset, node)
   140  		if !*gccgo {
   141  			fmt.Fprintf(fgo2, " = (")
   142  			conf.Fprint(fgo2, fset, node)
   143  			fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
   144  		}
   145  		fmt.Fprintf(fgo2, "\n")
   146  	}
   147  	if *gccgo {
   148  		fmt.Fprintf(fc, "\n")
   149  	}
   150  
   151  	for _, key := range nameKeys(p.Name) {
   152  		n := p.Name[key]
   153  		if n.Const != "" {
   154  			fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
   155  		}
   156  	}
   157  	fmt.Fprintf(fgo2, "\n")
   158  
   159  	for _, key := range nameKeys(p.Name) {
   160  		n := p.Name[key]
   161  		if n.FuncType != nil {
   162  			p.writeDefsFunc(fc, fgo2, n)
   163  		}
   164  	}
   165  
   166  	if *gccgo {
   167  		p.writeGccgoExports(fgo2, fc, fm)
   168  	} else {
   169  		p.writeExports(fgo2, fc, fm)
   170  	}
   171  
   172  	init := gccgoInit.String()
   173  	if init != "" {
   174  		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
   175  		fmt.Fprintln(fc, "static void init(void) {")
   176  		fmt.Fprint(fc, init)
   177  		fmt.Fprintln(fc, "}")
   178  	}
   179  }
   180  
   181  func dynimport(obj string) {
   182  	stdout := os.Stdout
   183  	if *dynout != "" {
   184  		f, err := os.Create(*dynout)
   185  		if err != nil {
   186  			fatalf("%s", err)
   187  		}
   188  		stdout = f
   189  	}
   190  
   191  	fmt.Fprintf(stdout, "package %s\n", *dynpackage)
   192  
   193  	if f, err := elf.Open(obj); err == nil {
   194  		if *dynlinker {
   195  			// Emit the cgo_dynamic_linker line.
   196  			if sec := f.Section(".interp"); sec != nil {
   197  				if data, err := sec.Data(); err == nil && len(data) > 1 {
   198  					// skip trailing \0 in data
   199  					fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
   200  				}
   201  			}
   202  		}
   203  		sym, err := f.ImportedSymbols()
   204  		if err != nil {
   205  			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
   206  		}
   207  		for _, s := range sym {
   208  			targ := s.Name
   209  			if s.Version != "" {
   210  				targ += "#" + s.Version
   211  			}
   212  			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
   213  		}
   214  		lib, err := f.ImportedLibraries()
   215  		if err != nil {
   216  			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
   217  		}
   218  		for _, l := range lib {
   219  			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
   220  		}
   221  		return
   222  	}
   223  
   224  	if f, err := macho.Open(obj); err == nil {
   225  		sym, err := f.ImportedSymbols()
   226  		if err != nil {
   227  			fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
   228  		}
   229  		for _, s := range sym {
   230  			if len(s) > 0 && s[0] == '_' {
   231  				s = s[1:]
   232  			}
   233  			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
   234  		}
   235  		lib, err := f.ImportedLibraries()
   236  		if err != nil {
   237  			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
   238  		}
   239  		for _, l := range lib {
   240  			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
   241  		}
   242  		return
   243  	}
   244  
   245  	if f, err := pe.Open(obj); err == nil {
   246  		sym, err := f.ImportedSymbols()
   247  		if err != nil {
   248  			fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
   249  		}
   250  		for _, s := range sym {
   251  			ss := strings.Split(s, ":")
   252  			name := strings.Split(ss[0], "@")[0]
   253  			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
   254  		}
   255  		return
   256  	}
   257  
   258  	fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
   259  }
   260  
   261  // Construct a gcc struct matching the 6c argument frame.
   262  // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
   263  // These assumptions are checked by the gccProlog.
   264  // Also assumes that 6c convention is to word-align the
   265  // input and output parameters.
   266  func (p *Package) structType(n *Name) (string, int64) {
   267  	var buf bytes.Buffer
   268  	fmt.Fprint(&buf, "struct {\n")
   269  	off := int64(0)
   270  	for i, t := range n.FuncType.Params {
   271  		if off%t.Align != 0 {
   272  			pad := t.Align - off%t.Align
   273  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   274  			off += pad
   275  		}
   276  		c := t.Typedef
   277  		if c == "" {
   278  			c = t.C.String()
   279  		}
   280  		fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
   281  		off += t.Size
   282  	}
   283  	if off%p.PtrSize != 0 {
   284  		pad := p.PtrSize - off%p.PtrSize
   285  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   286  		off += pad
   287  	}
   288  	if t := n.FuncType.Result; t != nil {
   289  		if off%t.Align != 0 {
   290  			pad := t.Align - off%t.Align
   291  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   292  			off += pad
   293  		}
   294  		qual := ""
   295  		if c := t.C.String(); c[len(c)-1] == '*' {
   296  			qual = "const "
   297  		}
   298  		fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
   299  		off += t.Size
   300  	}
   301  	if off%p.PtrSize != 0 {
   302  		pad := p.PtrSize - off%p.PtrSize
   303  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   304  		off += pad
   305  	}
   306  	if off == 0 {
   307  		fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
   308  	}
   309  	fmt.Fprintf(&buf, "\t}")
   310  	return buf.String(), off
   311  }
   312  
   313  func (p *Package) writeDefsFunc(fc, fgo2 io.Writer, n *Name) {
   314  	name := n.Go
   315  	gtype := n.FuncType.Go
   316  	void := gtype.Results == nil || len(gtype.Results.List) == 0
   317  	if n.AddError {
   318  		// Add "error" to return type list.
   319  		// Type list is known to be 0 or 1 element - it's a C function.
   320  		err := &ast.Field{Type: ast.NewIdent("error")}
   321  		l := gtype.Results.List
   322  		if len(l) == 0 {
   323  			l = []*ast.Field{err}
   324  		} else {
   325  			l = []*ast.Field{l[0], err}
   326  		}
   327  		t := new(ast.FuncType)
   328  		*t = *gtype
   329  		t.Results = &ast.FieldList{List: l}
   330  		gtype = t
   331  	}
   332  
   333  	// Go func declaration.
   334  	d := &ast.FuncDecl{
   335  		Name: ast.NewIdent(n.Mangle),
   336  		Type: gtype,
   337  	}
   338  
   339  	// Builtins defined in the C prolog.
   340  	inProlog := builtinDefs[name] != ""
   341  	cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
   342  	paramnames := []string(nil)
   343  	for i, param := range d.Type.Params.List {
   344  		paramName := fmt.Sprintf("p%d", i)
   345  		param.Names = []*ast.Ident{ast.NewIdent(paramName)}
   346  		paramnames = append(paramnames, paramName)
   347  	}
   348  
   349  	if *gccgo {
   350  		// Gccgo style hooks.
   351  		fmt.Fprint(fgo2, "\n")
   352  		conf.Fprint(fgo2, fset, d)
   353  		fmt.Fprint(fgo2, " {\n")
   354  		if !inProlog {
   355  			fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
   356  			fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
   357  		}
   358  		if n.AddError {
   359  			fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
   360  		}
   361  		fmt.Fprint(fgo2, "\t")
   362  		if !void {
   363  			fmt.Fprint(fgo2, "r := ")
   364  		}
   365  		fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
   366  
   367  		if n.AddError {
   368  			fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
   369  			fmt.Fprint(fgo2, "\tif e != 0 {\n")
   370  			fmt.Fprint(fgo2, "\t\treturn ")
   371  			if !void {
   372  				fmt.Fprint(fgo2, "r, ")
   373  			}
   374  			fmt.Fprint(fgo2, "e\n")
   375  			fmt.Fprint(fgo2, "\t}\n")
   376  			fmt.Fprint(fgo2, "\treturn ")
   377  			if !void {
   378  				fmt.Fprint(fgo2, "r, ")
   379  			}
   380  			fmt.Fprint(fgo2, "nil\n")
   381  		} else if !void {
   382  			fmt.Fprint(fgo2, "\treturn r\n")
   383  		}
   384  
   385  		fmt.Fprint(fgo2, "}\n")
   386  
   387  		// declare the C function.
   388  		fmt.Fprintf(fgo2, "//extern %s\n", cname)
   389  		d.Name = ast.NewIdent(cname)
   390  		if n.AddError {
   391  			l := d.Type.Results.List
   392  			d.Type.Results.List = l[:len(l)-1]
   393  		}
   394  		conf.Fprint(fgo2, fset, d)
   395  		fmt.Fprint(fgo2, "\n")
   396  
   397  		return
   398  	}
   399  
   400  	if inProlog {
   401  		fmt.Fprint(fgo2, builtinDefs[name])
   402  		return
   403  	}
   404  
   405  	// C wrapper calls into gcc, passing a pointer to the argument frame.
   406  	fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
   407  	fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
   408  	fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
   409  	fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
   410  
   411  	nret := 0
   412  	if !void {
   413  		d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")}
   414  		nret = 1
   415  	}
   416  	if n.AddError {
   417  		d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")}
   418  	}
   419  
   420  	fmt.Fprint(fgo2, "\n")
   421  	conf.Fprint(fgo2, fset, d)
   422  	fmt.Fprint(fgo2, " {\n")
   423  
   424  	// NOTE: Using uintptr to hide from escape analysis.
   425  	arg := "0"
   426  	if len(paramnames) > 0 {
   427  		arg = "uintptr(unsafe.Pointer(&p0))"
   428  	} else if !void {
   429  		arg = "uintptr(unsafe.Pointer(&r1))"
   430  	}
   431  
   432  	prefix := ""
   433  	if n.AddError {
   434  		prefix = "errno := "
   435  	}
   436  	fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg)
   437  	if n.AddError {
   438  		fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
   439  	}
   440  	fmt.Fprintf(fgo2, "\treturn\n")
   441  	fmt.Fprintf(fgo2, "}\n")
   442  }
   443  
   444  // writeOutput creates stubs for a specific source file to be compiled by 6g
   445  // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
   446  func (p *Package) writeOutput(f *File, srcfile string) {
   447  	base := srcfile
   448  	if strings.HasSuffix(base, ".go") {
   449  		base = base[0 : len(base)-3]
   450  	}
   451  	base = strings.Map(slashToUnderscore, base)
   452  	fgo1 := creat(*objDir + base + ".cgo1.go")
   453  	fgcc := creat(*objDir + base + ".cgo2.c")
   454  
   455  	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
   456  	p.GccFiles = append(p.GccFiles, base+".cgo2.c")
   457  
   458  	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
   459  	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
   460  	conf.Fprint(fgo1, fset, f.AST)
   461  
   462  	// While we process the vars and funcs, also write 6c and gcc output.
   463  	// Gcc output starts with the preamble.
   464  	fmt.Fprintf(fgcc, "%s\n", f.Preamble)
   465  	fmt.Fprintf(fgcc, "%s\n", gccProlog)
   466  
   467  	for _, key := range nameKeys(f.Name) {
   468  		n := f.Name[key]
   469  		if n.FuncType != nil {
   470  			p.writeOutputFunc(fgcc, n)
   471  		}
   472  	}
   473  
   474  	fgo1.Close()
   475  	fgcc.Close()
   476  }
   477  
   478  // fixGo converts the internal Name.Go field into the name we should show
   479  // to users in error messages. There's only one for now: on input we rewrite
   480  // C.malloc into C._CMalloc, so change it back here.
   481  func fixGo(name string) string {
   482  	if name == "_CMalloc" {
   483  		return "malloc"
   484  	}
   485  	return name
   486  }
   487  
   488  var isBuiltin = map[string]bool{
   489  	"_Cfunc_CString":   true,
   490  	"_Cfunc_GoString":  true,
   491  	"_Cfunc_GoStringN": true,
   492  	"_Cfunc_GoBytes":   true,
   493  	"_Cfunc__CMalloc":  true,
   494  }
   495  
   496  func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
   497  	name := n.Mangle
   498  	if isBuiltin[name] || p.Written[name] {
   499  		// The builtins are already defined in the C prolog, and we don't
   500  		// want to duplicate function definitions we've already done.
   501  		return
   502  	}
   503  	p.Written[name] = true
   504  
   505  	if *gccgo {
   506  		p.writeGccgoOutputFunc(fgcc, n)
   507  		return
   508  	}
   509  
   510  	ctype, _ := p.structType(n)
   511  
   512  	// Gcc wrapper unpacks the C argument struct
   513  	// and calls the actual C function.
   514  	if n.AddError {
   515  		fmt.Fprintf(fgcc, "int\n")
   516  	} else {
   517  		fmt.Fprintf(fgcc, "void\n")
   518  	}
   519  	fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
   520  	fmt.Fprintf(fgcc, "{\n")
   521  	if n.AddError {
   522  		fmt.Fprintf(fgcc, "\terrno = 0;\n")
   523  	}
   524  	// We're trying to write a gcc struct that matches 6c/8c/5c's layout.
   525  	// Use packed attribute to force no padding in this struct in case
   526  	// gcc has different packing requirements.
   527  	fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
   528  	if n.FuncType.Result != nil {
   529  		// Save the stack top for use below.
   530  		fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
   531  	}
   532  	fmt.Fprintf(fgcc, "\t")
   533  	if t := n.FuncType.Result; t != nil {
   534  		fmt.Fprintf(fgcc, "__typeof__(a->r) r = ")
   535  		if c := t.C.String(); c[len(c)-1] == '*' {
   536  			fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
   537  		}
   538  	}
   539  	fmt.Fprintf(fgcc, "%s(", n.C)
   540  	for i, t := range n.FuncType.Params {
   541  		if i > 0 {
   542  			fmt.Fprintf(fgcc, ", ")
   543  		}
   544  		// We know the type params are correct, because
   545  		// the Go equivalents had good type params.
   546  		// However, our version of the type omits the magic
   547  		// words const and volatile, which can provoke
   548  		// C compiler warnings.  Silence them by casting
   549  		// all pointers to void*.  (Eventually that will produce
   550  		// other warnings.)
   551  		if c := t.C.String(); c[len(c)-1] == '*' {
   552  			fmt.Fprintf(fgcc, "(void*)")
   553  		}
   554  		fmt.Fprintf(fgcc, "a->p%d", i)
   555  	}
   556  	fmt.Fprintf(fgcc, ");\n")
   557  	if n.FuncType.Result != nil {
   558  		// The cgo call may have caused a stack copy (via a callback).
   559  		// Adjust the return value pointer appropriately.
   560  		fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n")
   561  		// Save the return value.
   562  		fmt.Fprintf(fgcc, "\ta->r = r;\n")
   563  	}
   564  	if n.AddError {
   565  		fmt.Fprintf(fgcc, "\treturn errno;\n")
   566  	}
   567  	fmt.Fprintf(fgcc, "}\n")
   568  	fmt.Fprintf(fgcc, "\n")
   569  }
   570  
   571  // Write out a wrapper for a function when using gccgo.  This is a
   572  // simple wrapper that just calls the real function.  We only need a
   573  // wrapper to support static functions in the prologue--without a
   574  // wrapper, we can't refer to the function, since the reference is in
   575  // a different file.
   576  func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
   577  	if t := n.FuncType.Result; t != nil {
   578  		fmt.Fprintf(fgcc, "%s\n", t.C.String())
   579  	} else {
   580  		fmt.Fprintf(fgcc, "void\n")
   581  	}
   582  	fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
   583  	for i, t := range n.FuncType.Params {
   584  		if i > 0 {
   585  			fmt.Fprintf(fgcc, ", ")
   586  		}
   587  		c := t.Typedef
   588  		if c == "" {
   589  			c = t.C.String()
   590  		}
   591  		fmt.Fprintf(fgcc, "%s p%d", c, i)
   592  	}
   593  	fmt.Fprintf(fgcc, ")\n")
   594  	fmt.Fprintf(fgcc, "{\n")
   595  	fmt.Fprintf(fgcc, "\t")
   596  	if t := n.FuncType.Result; t != nil {
   597  		fmt.Fprintf(fgcc, "return ")
   598  		// Cast to void* to avoid warnings due to omitted qualifiers.
   599  		if c := t.C.String(); c[len(c)-1] == '*' {
   600  			fmt.Fprintf(fgcc, "(void*)")
   601  		}
   602  	}
   603  	fmt.Fprintf(fgcc, "%s(", n.C)
   604  	for i, t := range n.FuncType.Params {
   605  		if i > 0 {
   606  			fmt.Fprintf(fgcc, ", ")
   607  		}
   608  		// Cast to void* to avoid warnings due to omitted qualifiers.
   609  		if c := t.C.String(); c[len(c)-1] == '*' {
   610  			fmt.Fprintf(fgcc, "(void*)")
   611  		}
   612  		fmt.Fprintf(fgcc, "p%d", i)
   613  	}
   614  	fmt.Fprintf(fgcc, ");\n")
   615  	fmt.Fprintf(fgcc, "}\n")
   616  	fmt.Fprintf(fgcc, "\n")
   617  }
   618  
   619  // packedAttribute returns host compiler struct attribute that will be
   620  // used to match 6c/8c/5c's struct layout. For example, on 386 Windows,
   621  // gcc wants to 8-align int64s, but 8c does not.
   622  // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
   623  // and http://golang.org/issue/5603.
   624  func (p *Package) packedAttribute() string {
   625  	s := "__attribute__((__packed__"
   626  	if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
   627  		s += ", __gcc_struct__"
   628  	}
   629  	return s + "))"
   630  }
   631  
   632  // Write out the various stubs we need to support functions exported
   633  // from Go so that they are callable from C.
   634  func (p *Package) writeExports(fgo2, fc, fm io.Writer) {
   635  	fgcc := creat(*objDir + "_cgo_export.c")
   636  	fgcch := creat(*objDir + "_cgo_export.h")
   637  
   638  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   639  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   640  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   641  
   642  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   643  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   644  
   645  	fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
   646  
   647  	for _, exp := range p.ExpFunc {
   648  		fn := exp.Func
   649  
   650  		// Construct a gcc struct matching the 6c argument and
   651  		// result frame.  The gcc struct will be compiled with
   652  		// __attribute__((packed)) so all padding must be accounted
   653  		// for explicitly.
   654  		ctype := "struct {\n"
   655  		off := int64(0)
   656  		npad := 0
   657  		if fn.Recv != nil {
   658  			t := p.cgoType(fn.Recv.List[0].Type)
   659  			ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
   660  			off += t.Size
   661  		}
   662  		fntype := fn.Type
   663  		forFieldList(fntype.Params,
   664  			func(i int, atype ast.Expr) {
   665  				t := p.cgoType(atype)
   666  				if off%t.Align != 0 {
   667  					pad := t.Align - off%t.Align
   668  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   669  					off += pad
   670  					npad++
   671  				}
   672  				ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
   673  				off += t.Size
   674  			})
   675  		if off%p.PtrSize != 0 {
   676  			pad := p.PtrSize - off%p.PtrSize
   677  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   678  			off += pad
   679  			npad++
   680  		}
   681  		forFieldList(fntype.Results,
   682  			func(i int, atype ast.Expr) {
   683  				t := p.cgoType(atype)
   684  				if off%t.Align != 0 {
   685  					pad := t.Align - off%t.Align
   686  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   687  					off += pad
   688  					npad++
   689  				}
   690  				ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
   691  				off += t.Size
   692  			})
   693  		if off%p.PtrSize != 0 {
   694  			pad := p.PtrSize - off%p.PtrSize
   695  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   696  			off += pad
   697  			npad++
   698  		}
   699  		if ctype == "struct {\n" {
   700  			ctype += "\t\tchar unused;\n" // avoid empty struct
   701  		}
   702  		ctype += "\t}"
   703  
   704  		// Get the return type of the wrapper function
   705  		// compiled by gcc.
   706  		gccResult := ""
   707  		if fntype.Results == nil || len(fntype.Results.List) == 0 {
   708  			gccResult = "void"
   709  		} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   710  			gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
   711  		} else {
   712  			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
   713  			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
   714  			forFieldList(fntype.Results,
   715  				func(i int, atype ast.Expr) {
   716  					fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
   717  				})
   718  			fmt.Fprintf(fgcch, "};\n")
   719  			gccResult = "struct " + exp.ExpName + "_return"
   720  		}
   721  
   722  		// Build the wrapper function compiled by gcc.
   723  		s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
   724  		if fn.Recv != nil {
   725  			s += p.cgoType(fn.Recv.List[0].Type).C.String()
   726  			s += " recv"
   727  		}
   728  		forFieldList(fntype.Params,
   729  			func(i int, atype ast.Expr) {
   730  				if i > 0 || fn.Recv != nil {
   731  					s += ", "
   732  				}
   733  				s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
   734  			})
   735  		s += ")"
   736  		fmt.Fprintf(fgcch, "\nextern %s;\n", s)
   737  
   738  		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
   739  		fmt.Fprintf(fgcc, "\n%s\n", s)
   740  		fmt.Fprintf(fgcc, "{\n")
   741  		fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
   742  		if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
   743  			fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
   744  		}
   745  		if fn.Recv != nil {
   746  			fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
   747  		}
   748  		forFieldList(fntype.Params,
   749  			func(i int, atype ast.Expr) {
   750  				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
   751  			})
   752  		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
   753  		if gccResult != "void" {
   754  			if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   755  				fmt.Fprintf(fgcc, "\treturn a.r0;\n")
   756  			} else {
   757  				forFieldList(fntype.Results,
   758  					func(i int, atype ast.Expr) {
   759  						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
   760  					})
   761  				fmt.Fprintf(fgcc, "\treturn r;\n")
   762  			}
   763  		}
   764  		fmt.Fprintf(fgcc, "}\n")
   765  
   766  		// Build the wrapper function compiled by 6c/8c
   767  		goname := exp.Func.Name.Name
   768  		if fn.Recv != nil {
   769  			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
   770  		}
   771  		fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
   772  		fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
   773  		fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
   774  		fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
   775  		fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
   776  		fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
   777  		// The indirect here is converting from a Go function pointer to a C function pointer.
   778  		fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
   779  		fmt.Fprintf(fgo2, "}\n")
   780  
   781  		fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
   782  
   783  		// Calling a function with a receiver from C requires
   784  		// a Go wrapper function.
   785  		if fn.Recv != nil {
   786  			fmt.Fprintf(fgo2, "func %s(recv ", goname)
   787  			conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   788  			forFieldList(fntype.Params,
   789  				func(i int, atype ast.Expr) {
   790  					fmt.Fprintf(fgo2, ", p%d ", i)
   791  					conf.Fprint(fgo2, fset, atype)
   792  				})
   793  			fmt.Fprintf(fgo2, ")")
   794  			if gccResult != "void" {
   795  				fmt.Fprint(fgo2, " (")
   796  				forFieldList(fntype.Results,
   797  					func(i int, atype ast.Expr) {
   798  						if i > 0 {
   799  							fmt.Fprint(fgo2, ", ")
   800  						}
   801  						conf.Fprint(fgo2, fset, atype)
   802  					})
   803  				fmt.Fprint(fgo2, ")")
   804  			}
   805  			fmt.Fprint(fgo2, " {\n")
   806  			fmt.Fprint(fgo2, "\t")
   807  			if gccResult != "void" {
   808  				fmt.Fprint(fgo2, "return ")
   809  			}
   810  			fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
   811  			forFieldList(fntype.Params,
   812  				func(i int, atype ast.Expr) {
   813  					if i > 0 {
   814  						fmt.Fprint(fgo2, ", ")
   815  					}
   816  					fmt.Fprintf(fgo2, "p%d", i)
   817  				})
   818  			fmt.Fprint(fgo2, ")\n")
   819  			fmt.Fprint(fgo2, "}\n")
   820  		}
   821  	}
   822  }
   823  
   824  // Write out the C header allowing C code to call exported gccgo functions.
   825  func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) {
   826  	fgcc := creat(*objDir + "_cgo_export.c")
   827  	fgcch := creat(*objDir + "_cgo_export.h")
   828  
   829  	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
   830  
   831  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   832  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   833  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   834  
   835  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   836  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   837  
   838  	fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
   839  
   840  	for _, exp := range p.ExpFunc {
   841  		fn := exp.Func
   842  		fntype := fn.Type
   843  
   844  		cdeclBuf := new(bytes.Buffer)
   845  		resultCount := 0
   846  		forFieldList(fntype.Results,
   847  			func(i int, atype ast.Expr) { resultCount++ })
   848  		switch resultCount {
   849  		case 0:
   850  			fmt.Fprintf(cdeclBuf, "void")
   851  		case 1:
   852  			forFieldList(fntype.Results,
   853  				func(i int, atype ast.Expr) {
   854  					t := p.cgoType(atype)
   855  					fmt.Fprintf(cdeclBuf, "%s", t.C)
   856  				})
   857  		default:
   858  			// Declare a result struct.
   859  			fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
   860  			forFieldList(fntype.Results,
   861  				func(i int, atype ast.Expr) {
   862  					t := p.cgoType(atype)
   863  					fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
   864  				})
   865  			fmt.Fprintf(fgcch, "};\n")
   866  			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
   867  		}
   868  
   869  		cRet := cdeclBuf.String()
   870  
   871  		cdeclBuf = new(bytes.Buffer)
   872  		fmt.Fprintf(cdeclBuf, "(")
   873  		if fn.Recv != nil {
   874  			fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
   875  		}
   876  		// Function parameters.
   877  		forFieldList(fntype.Params,
   878  			func(i int, atype ast.Expr) {
   879  				if i > 0 || fn.Recv != nil {
   880  					fmt.Fprintf(cdeclBuf, ", ")
   881  				}
   882  				t := p.cgoType(atype)
   883  				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
   884  			})
   885  		fmt.Fprintf(cdeclBuf, ")")
   886  		cParams := cdeclBuf.String()
   887  
   888  		// We need to use a name that will be exported by the
   889  		// Go code; otherwise gccgo will make it static and we
   890  		// will not be able to link against it from the C
   891  		// code.
   892  		goName := "Cgoexp_" + exp.ExpName
   893  		fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
   894  		fmt.Fprint(fgcch, "\n")
   895  
   896  		// Use a #define so that the C code that includes
   897  		// cgo_export.h will be able to refer to the Go
   898  		// function using the expected name.
   899  		fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName)
   900  
   901  		// Use a #undef in _cgo_export.c so that we ignore the
   902  		// #define from cgo_export.h, since here we are
   903  		// defining the real function.
   904  		fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName)
   905  
   906  		fmt.Fprint(fgcc, "\n")
   907  		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
   908  		fmt.Fprint(fgcc, "\t")
   909  		if resultCount > 0 {
   910  			fmt.Fprint(fgcc, "return ")
   911  		}
   912  		fmt.Fprintf(fgcc, "%s(", goName)
   913  		if fn.Recv != nil {
   914  			fmt.Fprint(fgcc, "recv")
   915  		}
   916  		forFieldList(fntype.Params,
   917  			func(i int, atype ast.Expr) {
   918  				if i > 0 || fn.Recv != nil {
   919  					fmt.Fprintf(fgcc, ", ")
   920  				}
   921  				fmt.Fprintf(fgcc, "p%d", i)
   922  			})
   923  		fmt.Fprint(fgcc, ");\n")
   924  		fmt.Fprint(fgcc, "}\n")
   925  
   926  		// Dummy declaration for _cgo_main.c
   927  		fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
   928  
   929  		// For gccgo we use a wrapper function in Go, in order
   930  		// to call CgocallBack and CgocallBackDone.
   931  
   932  		// This code uses printer.Fprint, not conf.Fprint,
   933  		// because we don't want //line comments in the middle
   934  		// of the function types.
   935  		fmt.Fprint(fgo2, "\n")
   936  		fmt.Fprintf(fgo2, "func %s(", goName)
   937  		if fn.Recv != nil {
   938  			fmt.Fprint(fgo2, "recv ")
   939  			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   940  		}
   941  		forFieldList(fntype.Params,
   942  			func(i int, atype ast.Expr) {
   943  				if i > 0 || fn.Recv != nil {
   944  					fmt.Fprintf(fgo2, ", ")
   945  				}
   946  				fmt.Fprintf(fgo2, "p%d ", i)
   947  				printer.Fprint(fgo2, fset, atype)
   948  			})
   949  		fmt.Fprintf(fgo2, ")")
   950  		if resultCount > 0 {
   951  			fmt.Fprintf(fgo2, " (")
   952  			forFieldList(fntype.Results,
   953  				func(i int, atype ast.Expr) {
   954  					if i > 0 {
   955  						fmt.Fprint(fgo2, ", ")
   956  					}
   957  					printer.Fprint(fgo2, fset, atype)
   958  				})
   959  			fmt.Fprint(fgo2, ")")
   960  		}
   961  		fmt.Fprint(fgo2, " {\n")
   962  		fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
   963  		fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
   964  		fmt.Fprint(fgo2, "\t")
   965  		if resultCount > 0 {
   966  			fmt.Fprint(fgo2, "return ")
   967  		}
   968  		if fn.Recv != nil {
   969  			fmt.Fprint(fgo2, "recv.")
   970  		}
   971  		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
   972  		forFieldList(fntype.Params,
   973  			func(i int, atype ast.Expr) {
   974  				if i > 0 {
   975  					fmt.Fprint(fgo2, ", ")
   976  				}
   977  				fmt.Fprintf(fgo2, "p%d", i)
   978  			})
   979  		fmt.Fprint(fgo2, ")\n")
   980  		fmt.Fprint(fgo2, "}\n")
   981  	}
   982  }
   983  
   984  // Return the package prefix when using gccgo.
   985  func (p *Package) gccgoSymbolPrefix() string {
   986  	if !*gccgo {
   987  		return ""
   988  	}
   989  
   990  	clean := func(r rune) rune {
   991  		switch {
   992  		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
   993  			'0' <= r && r <= '9':
   994  			return r
   995  		}
   996  		return '_'
   997  	}
   998  
   999  	if *gccgopkgpath != "" {
  1000  		return strings.Map(clean, *gccgopkgpath)
  1001  	}
  1002  	if *gccgoprefix == "" && p.PackageName == "main" {
  1003  		return "main"
  1004  	}
  1005  	prefix := strings.Map(clean, *gccgoprefix)
  1006  	if prefix == "" {
  1007  		prefix = "go"
  1008  	}
  1009  	return prefix + "." + p.PackageName
  1010  }
  1011  
  1012  // Call a function for each entry in an ast.FieldList, passing the
  1013  // index into the list and the type.
  1014  func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
  1015  	if fl == nil {
  1016  		return
  1017  	}
  1018  	i := 0
  1019  	for _, r := range fl.List {
  1020  		if r.Names == nil {
  1021  			fn(i, r.Type)
  1022  			i++
  1023  		} else {
  1024  			for range r.Names {
  1025  				fn(i, r.Type)
  1026  				i++
  1027  			}
  1028  		}
  1029  	}
  1030  }
  1031  
  1032  func c(repr string, args ...interface{}) *TypeRepr {
  1033  	return &TypeRepr{repr, args}
  1034  }
  1035  
  1036  // Map predeclared Go types to Type.
  1037  var goTypes = map[string]*Type{
  1038  	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
  1039  	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
  1040  	"int":        {Size: 0, Align: 0, C: c("GoInt")},
  1041  	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
  1042  	"rune":       {Size: 4, Align: 4, C: c("GoInt32")},
  1043  	"int8":       {Size: 1, Align: 1, C: c("GoInt8")},
  1044  	"uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
  1045  	"int16":      {Size: 2, Align: 2, C: c("GoInt16")},
  1046  	"uint16":     {Size: 2, Align: 2, C: c("GoUint16")},
  1047  	"int32":      {Size: 4, Align: 4, C: c("GoInt32")},
  1048  	"uint32":     {Size: 4, Align: 4, C: c("GoUint32")},
  1049  	"int64":      {Size: 8, Align: 8, C: c("GoInt64")},
  1050  	"uint64":     {Size: 8, Align: 8, C: c("GoUint64")},
  1051  	"float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
  1052  	"float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
  1053  	"complex64":  {Size: 8, Align: 8, C: c("GoComplex64")},
  1054  	"complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
  1055  }
  1056  
  1057  // Map an ast type to a Type.
  1058  func (p *Package) cgoType(e ast.Expr) *Type {
  1059  	switch t := e.(type) {
  1060  	case *ast.StarExpr:
  1061  		x := p.cgoType(t.X)
  1062  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
  1063  	case *ast.ArrayType:
  1064  		if t.Len == nil {
  1065  			// Slice: pointer, len, cap.
  1066  			return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")}
  1067  		}
  1068  	case *ast.StructType:
  1069  		// TODO
  1070  	case *ast.FuncType:
  1071  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
  1072  	case *ast.InterfaceType:
  1073  		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
  1074  	case *ast.MapType:
  1075  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
  1076  	case *ast.ChanType:
  1077  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
  1078  	case *ast.Ident:
  1079  		// Look up the type in the top level declarations.
  1080  		// TODO: Handle types defined within a function.
  1081  		for _, d := range p.Decl {
  1082  			gd, ok := d.(*ast.GenDecl)
  1083  			if !ok || gd.Tok != token.TYPE {
  1084  				continue
  1085  			}
  1086  			for _, spec := range gd.Specs {
  1087  				ts, ok := spec.(*ast.TypeSpec)
  1088  				if !ok {
  1089  					continue
  1090  				}
  1091  				if ts.Name.Name == t.Name {
  1092  					return p.cgoType(ts.Type)
  1093  				}
  1094  			}
  1095  		}
  1096  		if def := typedef[t.Name]; def != nil {
  1097  			return def
  1098  		}
  1099  		if t.Name == "uintptr" {
  1100  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
  1101  		}
  1102  		if t.Name == "string" {
  1103  			// The string data is 1 pointer + 1 (pointer-sized) int.
  1104  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
  1105  		}
  1106  		if t.Name == "error" {
  1107  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
  1108  		}
  1109  		if r, ok := goTypes[t.Name]; ok {
  1110  			if r.Size == 0 { // int or uint
  1111  				rr := new(Type)
  1112  				*rr = *r
  1113  				rr.Size = p.IntSize
  1114  				rr.Align = p.IntSize
  1115  				r = rr
  1116  			}
  1117  			if r.Align > p.PtrSize {
  1118  				r.Align = p.PtrSize
  1119  			}
  1120  			return r
  1121  		}
  1122  		error_(e.Pos(), "unrecognized Go type %s", t.Name)
  1123  		return &Type{Size: 4, Align: 4, C: c("int")}
  1124  	case *ast.SelectorExpr:
  1125  		id, ok := t.X.(*ast.Ident)
  1126  		if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
  1127  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
  1128  		}
  1129  	}
  1130  	error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
  1131  	return &Type{Size: 4, Align: 4, C: c("int")}
  1132  }
  1133  
  1134  const gccProlog = `
  1135  // Usual nonsense: if x and y are not equal, the type will be invalid
  1136  // (have a negative array count) and an inscrutable error will come
  1137  // out of the compiler and hopefully mention "name".
  1138  #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
  1139  
  1140  // Check at compile time that the sizes we use match our expectations.
  1141  #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
  1142  
  1143  __cgo_size_assert(char, 1)
  1144  __cgo_size_assert(short, 2)
  1145  __cgo_size_assert(int, 4)
  1146  typedef long long __cgo_long_long;
  1147  __cgo_size_assert(__cgo_long_long, 8)
  1148  __cgo_size_assert(float, 4)
  1149  __cgo_size_assert(double, 8)
  1150  
  1151  extern char* _cgo_topofstack(void);
  1152  
  1153  #include <errno.h>
  1154  #include <string.h>
  1155  `
  1156  
  1157  const builtinProlog = `
  1158  #include <stddef.h> /* for ptrdiff_t and size_t below */
  1159  
  1160  /* Define intgo when compiling with GCC.  */
  1161  typedef ptrdiff_t intgo;
  1162  
  1163  typedef struct { char *p; intgo n; } _GoString_;
  1164  typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
  1165  _GoString_ GoString(char *p);
  1166  _GoString_ GoStringN(char *p, int l);
  1167  _GoBytes_ GoBytes(void *p, int n);
  1168  char *CString(_GoString_);
  1169  void *_CMalloc(size_t);
  1170  `
  1171  
  1172  const goProlog = `
  1173  //go:linkname _cgo_runtime_cgocall_errno runtime.cgocall_errno
  1174  func _cgo_runtime_cgocall_errno(unsafe.Pointer, uintptr) int32
  1175  
  1176  //go:linkname _cgo_runtime_cmalloc runtime.cmalloc
  1177  func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
  1178  
  1179  //go:linkname _cgo_runtime_cgocallback runtime.cgocallback
  1180  func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
  1181  `
  1182  
  1183  const goStringDef = `
  1184  //go:linkname _cgo_runtime_gostring runtime.gostring
  1185  func _cgo_runtime_gostring(*_Ctype_char) string
  1186  
  1187  func _Cfunc_GoString(p *_Ctype_char) string {
  1188  	return _cgo_runtime_gostring(p)
  1189  }
  1190  `
  1191  
  1192  const goStringNDef = `
  1193  //go:linkname _cgo_runtime_gostringn runtime.gostringn
  1194  func _cgo_runtime_gostringn(*_Ctype_char, int) string
  1195  
  1196  func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
  1197  	return _cgo_runtime_gostringn(p, int(l))
  1198  }
  1199  `
  1200  
  1201  const goBytesDef = `
  1202  //go:linkname _cgo_runtime_gobytes runtime.gobytes
  1203  func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
  1204  
  1205  func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
  1206  	return _cgo_runtime_gobytes(p, int(l))
  1207  }
  1208  `
  1209  
  1210  const cStringDef = `
  1211  func _Cfunc_CString(s string) *_Ctype_char {
  1212  	p := _cgo_runtime_cmalloc(uintptr(len(s)+1))
  1213  	pp := (*[1<<30]byte)(p)
  1214  	copy(pp[:], s)
  1215  	pp[len(s)] = 0
  1216  	return (*_Ctype_char)(p)
  1217  }
  1218  `
  1219  
  1220  const cMallocDef = `
  1221  func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
  1222  	return _cgo_runtime_cmalloc(uintptr(n))
  1223  }
  1224  `
  1225  
  1226  var builtinDefs = map[string]string{
  1227  	"GoString":  goStringDef,
  1228  	"GoStringN": goStringNDef,
  1229  	"GoBytes":   goBytesDef,
  1230  	"CString":   cStringDef,
  1231  	"_CMalloc":  cMallocDef,
  1232  }
  1233  
  1234  func (p *Package) cPrologGccgo() string {
  1235  	return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
  1236  }
  1237  
  1238  const cPrologGccgo = `
  1239  #include <stdint.h>
  1240  #include <stdlib.h>
  1241  #include <string.h>
  1242  
  1243  typedef unsigned char byte;
  1244  typedef intptr_t intgo;
  1245  
  1246  struct __go_string {
  1247  	const unsigned char *__data;
  1248  	intgo __length;
  1249  };
  1250  
  1251  typedef struct __go_open_array {
  1252  	void* __values;
  1253  	intgo __count;
  1254  	intgo __capacity;
  1255  } Slice;
  1256  
  1257  struct __go_string __go_byte_array_to_string(const void* p, intgo len);
  1258  struct __go_open_array __go_string_to_byte_array (struct __go_string str);
  1259  
  1260  const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
  1261  	char *p = malloc(s.__length+1);
  1262  	memmove(p, s.__data, s.__length);
  1263  	p[s.__length] = 0;
  1264  	return p;
  1265  }
  1266  
  1267  struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
  1268  	intgo len = (p != NULL) ? strlen(p) : 0;
  1269  	return __go_byte_array_to_string(p, len);
  1270  }
  1271  
  1272  struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
  1273  	return __go_byte_array_to_string(p, n);
  1274  }
  1275  
  1276  Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
  1277  	struct __go_string s = { (const unsigned char *)p, n };
  1278  	return __go_string_to_byte_array(s);
  1279  }
  1280  
  1281  extern void runtime_throw(const char *);
  1282  void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
  1283          void *p = malloc(n);
  1284          if(p == NULL && n == 0)
  1285                  p = malloc(1);
  1286          if(p == NULL)
  1287                  runtime_throw("runtime: C malloc failed");
  1288          return p;
  1289  }
  1290  `
  1291  
  1292  func (p *Package) gccExportHeaderProlog() string {
  1293  	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
  1294  }
  1295  
  1296  const gccExportHeaderProlog = `
  1297  typedef signed char GoInt8;
  1298  typedef unsigned char GoUint8;
  1299  typedef short GoInt16;
  1300  typedef unsigned short GoUint16;
  1301  typedef int GoInt32;
  1302  typedef unsigned int GoUint32;
  1303  typedef long long GoInt64;
  1304  typedef unsigned long long GoUint64;
  1305  typedef GoIntGOINTBITS GoInt;
  1306  typedef GoUintGOINTBITS GoUint;
  1307  typedef __SIZE_TYPE__ GoUintptr;
  1308  typedef float GoFloat32;
  1309  typedef double GoFloat64;
  1310  typedef __complex float GoComplex64;
  1311  typedef __complex double GoComplex128;
  1312  
  1313  typedef struct { char *p; GoInt n; } GoString;
  1314  typedef void *GoMap;
  1315  typedef void *GoChan;
  1316  typedef struct { void *t; void *v; } GoInterface;
  1317  typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  1318  `