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