github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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  	} else {
    48  		// If we're not importing runtime/cgo, we *are* runtime/cgo,
    49  		// which provides crosscall2.  We just need a prototype.
    50  		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
    51  	}
    52  	fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
    53  	fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
    54  
    55  	// Write second Go output: definitions of _C_xxx.
    56  	// In a separate file so that the import of "unsafe" does not
    57  	// pollute the original file.
    58  	fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
    59  	fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
    60  	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
    61  	if *importSyscall {
    62  		fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
    63  	}
    64  	if !*gccgo && *importRuntimeCgo {
    65  		fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
    66  	}
    67  	fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
    68  	if *importSyscall {
    69  		fmt.Fprintf(fgo2, "func _Cerrno(dst *error, x int32) { *dst = syscall.Errno(x) }\n")
    70  	}
    71  
    72  	typedefNames := make([]string, 0, len(typedef))
    73  	for name := range typedef {
    74  		typedefNames = append(typedefNames, name)
    75  	}
    76  	sort.Strings(typedefNames)
    77  	for _, name := range typedefNames {
    78  		def := typedef[name]
    79  		fmt.Fprintf(fgo2, "type %s ", name)
    80  		conf.Fprint(fgo2, fset, def.Go)
    81  		fmt.Fprintf(fgo2, "\n\n")
    82  	}
    83  	if *gccgo {
    84  		fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
    85  	} else {
    86  		fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
    87  	}
    88  
    89  	if *gccgo {
    90  		fmt.Fprintf(fc, p.cPrologGccgo())
    91  	} else {
    92  		fmt.Fprintf(fc, cProlog)
    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, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
   134  		}
   135  		fmt.Fprintf(fc, "\n")
   136  
   137  		fmt.Fprintf(fgo2, "var %s ", n.Mangle)
   138  		conf.Fprint(fgo2, fset, node)
   139  		fmt.Fprintf(fgo2, "\n")
   140  	}
   141  	fmt.Fprintf(fc, "\n")
   142  
   143  	for _, key := range nameKeys(p.Name) {
   144  		n := p.Name[key]
   145  		if n.Const != "" {
   146  			fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
   147  		}
   148  	}
   149  	fmt.Fprintf(fgo2, "\n")
   150  
   151  	for _, key := range nameKeys(p.Name) {
   152  		n := p.Name[key]
   153  		if n.FuncType != nil {
   154  			p.writeDefsFunc(fc, fgo2, n)
   155  		}
   156  	}
   157  
   158  	if *gccgo {
   159  		p.writeGccgoExports(fgo2, fc, fm)
   160  	} else {
   161  		p.writeExports(fgo2, fc, fm)
   162  	}
   163  
   164  	init := gccgoInit.String()
   165  	if init != "" {
   166  		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
   167  		fmt.Fprintln(fc, "static void init(void) {")
   168  		fmt.Fprint(fc, init)
   169  		fmt.Fprintln(fc, "}")
   170  	}
   171  
   172  	fgo2.Close()
   173  	fc.Close()
   174  }
   175  
   176  func dynimport(obj string) {
   177  	stdout := os.Stdout
   178  	if *dynout != "" {
   179  		f, err := os.Create(*dynout)
   180  		if err != nil {
   181  			fatalf("%s", err)
   182  		}
   183  		stdout = f
   184  	}
   185  
   186  	if f, err := elf.Open(obj); err == nil {
   187  		if *dynlinker {
   188  			// Emit the cgo_dynamic_linker line.
   189  			if sec := f.Section(".interp"); sec != nil {
   190  				if data, err := sec.Data(); err == nil && len(data) > 1 {
   191  					// skip trailing \0 in data
   192  					fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
   193  				}
   194  			}
   195  		}
   196  		sym, err := f.ImportedSymbols()
   197  		if err != nil {
   198  			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
   199  		}
   200  		for _, s := range sym {
   201  			targ := s.Name
   202  			if s.Version != "" {
   203  				targ += "#" + s.Version
   204  			}
   205  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
   206  		}
   207  		lib, err := f.ImportedLibraries()
   208  		if err != nil {
   209  			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
   210  		}
   211  		for _, l := range lib {
   212  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
   213  		}
   214  		return
   215  	}
   216  
   217  	if f, err := macho.Open(obj); err == nil {
   218  		sym, err := f.ImportedSymbols()
   219  		if err != nil {
   220  			fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
   221  		}
   222  		for _, s := range sym {
   223  			if len(s) > 0 && s[0] == '_' {
   224  				s = s[1:]
   225  			}
   226  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
   227  		}
   228  		lib, err := f.ImportedLibraries()
   229  		if err != nil {
   230  			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
   231  		}
   232  		for _, l := range lib {
   233  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
   234  		}
   235  		return
   236  	}
   237  
   238  	if f, err := pe.Open(obj); err == nil {
   239  		sym, err := f.ImportedSymbols()
   240  		if err != nil {
   241  			fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
   242  		}
   243  		for _, s := range sym {
   244  			ss := strings.Split(s, ":")
   245  			name := strings.Split(ss[0], "@")[0]
   246  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
   247  		}
   248  		return
   249  	}
   250  
   251  	fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
   252  }
   253  
   254  // Construct a gcc struct matching the 6c argument frame.
   255  // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
   256  // These assumptions are checked by the gccProlog.
   257  // Also assumes that 6c convention is to word-align the
   258  // input and output parameters.
   259  func (p *Package) structType(n *Name) (string, int64) {
   260  	var buf bytes.Buffer
   261  	fmt.Fprint(&buf, "struct {\n")
   262  	off := int64(0)
   263  	for i, t := range n.FuncType.Params {
   264  		if off%t.Align != 0 {
   265  			pad := t.Align - off%t.Align
   266  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   267  			off += pad
   268  		}
   269  		c := t.Typedef
   270  		if c == "" {
   271  			c = t.C.String()
   272  		}
   273  		fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
   274  		off += t.Size
   275  	}
   276  	if off%p.PtrSize != 0 {
   277  		pad := p.PtrSize - off%p.PtrSize
   278  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   279  		off += pad
   280  	}
   281  	if t := n.FuncType.Result; t != nil {
   282  		if off%t.Align != 0 {
   283  			pad := t.Align - off%t.Align
   284  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   285  			off += pad
   286  		}
   287  		qual := ""
   288  		if c := t.C.String(); c[len(c)-1] == '*' {
   289  			qual = "const "
   290  		}
   291  		fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
   292  		off += t.Size
   293  	}
   294  	if off%p.PtrSize != 0 {
   295  		pad := p.PtrSize - off%p.PtrSize
   296  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   297  		off += pad
   298  	}
   299  	if n.AddError {
   300  		fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* error */\n")
   301  		off += 2 * p.PtrSize
   302  	}
   303  	if off == 0 {
   304  		fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
   305  	}
   306  	fmt.Fprintf(&buf, "\t}")
   307  	return buf.String(), off
   308  }
   309  
   310  func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
   311  	name := n.Go
   312  	gtype := n.FuncType.Go
   313  	void := gtype.Results == nil || len(gtype.Results.List) == 0
   314  	if n.AddError {
   315  		// Add "error" to return type list.
   316  		// Type list is known to be 0 or 1 element - it's a C function.
   317  		err := &ast.Field{Type: ast.NewIdent("error")}
   318  		l := gtype.Results.List
   319  		if len(l) == 0 {
   320  			l = []*ast.Field{err}
   321  		} else {
   322  			l = []*ast.Field{l[0], err}
   323  		}
   324  		t := new(ast.FuncType)
   325  		*t = *gtype
   326  		t.Results = &ast.FieldList{List: l}
   327  		gtype = t
   328  	}
   329  
   330  	// Go func declaration.
   331  	d := &ast.FuncDecl{
   332  		Name: ast.NewIdent(n.Mangle),
   333  		Type: gtype,
   334  	}
   335  
   336  	// Builtins defined in the C prolog.
   337  	inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
   338  
   339  	if *gccgo {
   340  		// Gccgo style hooks.
   341  		fmt.Fprint(fgo2, "\n")
   342  		cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
   343  		paramnames := []string(nil)
   344  		for i, param := range d.Type.Params.List {
   345  			paramName := fmt.Sprintf("p%d", i)
   346  			param.Names = []*ast.Ident{ast.NewIdent(paramName)}
   347  			paramnames = append(paramnames, paramName)
   348  		}
   349  
   350  		conf.Fprint(fgo2, fset, d)
   351  		fmt.Fprint(fgo2, " {\n")
   352  		if !inProlog {
   353  			fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
   354  			fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
   355  		}
   356  		if n.AddError {
   357  			fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
   358  		}
   359  		fmt.Fprint(fgo2, "\t")
   360  		if !void {
   361  			fmt.Fprint(fgo2, "r := ")
   362  		}
   363  		fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
   364  
   365  		if n.AddError {
   366  			fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
   367  			fmt.Fprint(fgo2, "\tif e != 0 {\n")
   368  			fmt.Fprint(fgo2, "\t\treturn ")
   369  			if !void {
   370  				fmt.Fprint(fgo2, "r, ")
   371  			}
   372  			fmt.Fprint(fgo2, "e\n")
   373  			fmt.Fprint(fgo2, "\t}\n")
   374  			fmt.Fprint(fgo2, "\treturn ")
   375  			if !void {
   376  				fmt.Fprint(fgo2, "r, ")
   377  			}
   378  			fmt.Fprint(fgo2, "nil\n")
   379  		} else if !void {
   380  			fmt.Fprint(fgo2, "\treturn r\n")
   381  		}
   382  
   383  		fmt.Fprint(fgo2, "}\n")
   384  
   385  		// declare the C function.
   386  		fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mangle)
   387  		d.Name = ast.NewIdent(cname)
   388  		if n.AddError {
   389  			l := d.Type.Results.List
   390  			d.Type.Results.List = l[:len(l)-1]
   391  		}
   392  		conf.Fprint(fgo2, fset, d)
   393  		fmt.Fprint(fgo2, "\n")
   394  
   395  		return
   396  	}
   397  	conf.Fprint(fgo2, fset, d)
   398  	fmt.Fprint(fgo2, "\n")
   399  
   400  	if inProlog {
   401  		return
   402  	}
   403  
   404  	var argSize int64
   405  	_, argSize = p.structType(n)
   406  
   407  	// C wrapper calls into gcc, passing a pointer to the argument frame.
   408  	fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
   409  	fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
   410  	fmt.Fprintf(fc, "\n")
   411  	fmt.Fprintf(fc, "void\n")
   412  	if argSize == 0 {
   413  		argSize++
   414  	}
   415  	// TODO(rsc): The struct here should declare pointers only where
   416  	// there are pointers in the actual argument frame.
   417  	// This is a workaround for golang.org/issue/6397.
   418  	fmt.Fprintf(fc, "·%s(struct{", n.Mangle)
   419  	if n := argSize / p.PtrSize; n > 0 {
   420  		fmt.Fprintf(fc, "void *y[%d];", n)
   421  	}
   422  	if n := argSize % p.PtrSize; n > 0 {
   423  		fmt.Fprintf(fc, "uint8 x[%d];", n)
   424  	}
   425  	fmt.Fprintf(fc, "}p)\n")
   426  	fmt.Fprintf(fc, "{\n")
   427  	fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
   428  	if n.AddError {
   429  		// gcc leaves errno in first word of interface at end of p.
   430  		// check whether it is zero; if so, turn interface into nil.
   431  		// if not, turn interface into errno.
   432  		// Go init function initializes ·_Cerrno with an os.Errno
   433  		// for us to copy.
   434  		fmt.Fprintln(fc, `	{
   435  			int32 e;
   436  			void **v;
   437  			v = (void**)(&p+1) - 2;	/* v = final two void* of p */
   438  			e = *(int32*)v;
   439  			v[0] = (void*)0xdeadbeef;
   440  			v[1] = (void*)0xdeadbeef;
   441  			if(e == 0) {
   442  				/* nil interface */
   443  				v[0] = 0;
   444  				v[1] = 0;
   445  			} else {
   446  				·_Cerrno(v, e);	/* fill in v as error for errno e */
   447  			}
   448  		}`)
   449  	}
   450  	fmt.Fprintf(fc, "}\n")
   451  	fmt.Fprintf(fc, "\n")
   452  }
   453  
   454  // writeOutput creates stubs for a specific source file to be compiled by 6g
   455  // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
   456  func (p *Package) writeOutput(f *File, srcfile string) {
   457  	base := srcfile
   458  	if strings.HasSuffix(base, ".go") {
   459  		base = base[0 : len(base)-3]
   460  	}
   461  	base = strings.Map(slashToUnderscore, base)
   462  	fgo1 := creat(*objDir + base + ".cgo1.go")
   463  	fgcc := creat(*objDir + base + ".cgo2.c")
   464  
   465  	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
   466  	p.GccFiles = append(p.GccFiles, base+".cgo2.c")
   467  
   468  	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
   469  	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
   470  	conf.Fprint(fgo1, fset, f.AST)
   471  
   472  	// While we process the vars and funcs, also write 6c and gcc output.
   473  	// Gcc output starts with the preamble.
   474  	fmt.Fprintf(fgcc, "%s\n", f.Preamble)
   475  	fmt.Fprintf(fgcc, "%s\n", gccProlog)
   476  
   477  	for _, key := range nameKeys(f.Name) {
   478  		n := f.Name[key]
   479  		if n.FuncType != nil {
   480  			p.writeOutputFunc(fgcc, n)
   481  		}
   482  	}
   483  
   484  	fgo1.Close()
   485  	fgcc.Close()
   486  }
   487  
   488  // fixGo converts the internal Name.Go field into the name we should show
   489  // to users in error messages. There's only one for now: on input we rewrite
   490  // C.malloc into C._CMalloc, so change it back here.
   491  func fixGo(name string) string {
   492  	if name == "_CMalloc" {
   493  		return "malloc"
   494  	}
   495  	return name
   496  }
   497  
   498  var isBuiltin = map[string]bool{
   499  	"_Cfunc_CString":   true,
   500  	"_Cfunc_GoString":  true,
   501  	"_Cfunc_GoStringN": true,
   502  	"_Cfunc_GoBytes":   true,
   503  	"_Cfunc__CMalloc":  true,
   504  }
   505  
   506  func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
   507  	name := n.Mangle
   508  	if isBuiltin[name] || p.Written[name] {
   509  		// The builtins are already defined in the C prolog, and we don't
   510  		// want to duplicate function definitions we've already done.
   511  		return
   512  	}
   513  	p.Written[name] = true
   514  
   515  	if *gccgo {
   516  		p.writeGccgoOutputFunc(fgcc, n)
   517  		return
   518  	}
   519  
   520  	ctype, _ := p.structType(n)
   521  
   522  	// Gcc wrapper unpacks the C argument struct
   523  	// and calls the actual C function.
   524  	fmt.Fprintf(fgcc, "void\n")
   525  	fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
   526  	fmt.Fprintf(fgcc, "{\n")
   527  	if n.AddError {
   528  		fmt.Fprintf(fgcc, "\terrno = 0;\n")
   529  	}
   530  	// We're trying to write a gcc struct that matches 6c/8c/5c's layout.
   531  	// Use packed attribute to force no padding in this struct in case
   532  	// gcc has different packing requirements.
   533  	fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
   534  	fmt.Fprintf(fgcc, "\t")
   535  	if t := n.FuncType.Result; t != nil {
   536  		fmt.Fprintf(fgcc, "a->r = ")
   537  		if c := t.C.String(); c[len(c)-1] == '*' {
   538  			fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
   539  		}
   540  	}
   541  	fmt.Fprintf(fgcc, "%s(", n.C)
   542  	for i, t := range n.FuncType.Params {
   543  		if i > 0 {
   544  			fmt.Fprintf(fgcc, ", ")
   545  		}
   546  		// We know the type params are correct, because
   547  		// the Go equivalents had good type params.
   548  		// However, our version of the type omits the magic
   549  		// words const and volatile, which can provoke
   550  		// C compiler warnings.  Silence them by casting
   551  		// all pointers to void*.  (Eventually that will produce
   552  		// other warnings.)
   553  		if c := t.C.String(); c[len(c)-1] == '*' {
   554  			fmt.Fprintf(fgcc, "(void*)")
   555  		}
   556  		fmt.Fprintf(fgcc, "a->p%d", i)
   557  	}
   558  	fmt.Fprintf(fgcc, ");\n")
   559  	if n.AddError {
   560  		fmt.Fprintf(fgcc, "\t*(int*)(a->e) = 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  #include <errno.h>
  1147  #include <string.h>
  1148  `
  1149  
  1150  const builtinProlog = `
  1151  #include <sys/types.h> /* for size_t below */
  1152  
  1153  /* Define intgo when compiling with GCC.  */
  1154  #ifdef __PTRDIFF_TYPE__
  1155  typedef __PTRDIFF_TYPE__ intgo;
  1156  #elif defined(_LP64)
  1157  typedef long long intgo;
  1158  #else
  1159  typedef int intgo;
  1160  #endif
  1161  
  1162  typedef struct { char *p; intgo n; } _GoString_;
  1163  typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
  1164  _GoString_ GoString(char *p);
  1165  _GoString_ GoStringN(char *p, int l);
  1166  _GoBytes_ GoBytes(void *p, int n);
  1167  char *CString(_GoString_);
  1168  void *_CMalloc(size_t);
  1169  `
  1170  
  1171  const cProlog = `
  1172  #include "runtime.h"
  1173  #include "cgocall.h"
  1174  
  1175  void ·_Cerrno(void*, int32);
  1176  
  1177  void
  1178  ·_Cfunc_GoString(int8 *p, String s)
  1179  {
  1180  	s = runtime·gostring((byte*)p);
  1181  	FLUSH(&s);
  1182  }
  1183  
  1184  void
  1185  ·_Cfunc_GoStringN(int8 *p, int32 l, String s)
  1186  {
  1187  	s = runtime·gostringn((byte*)p, l);
  1188  	FLUSH(&s);
  1189  }
  1190  
  1191  void
  1192  ·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
  1193  {
  1194  	s = runtime·gobytes((byte*)p, l);
  1195  	FLUSH(&s);
  1196  }
  1197  
  1198  void
  1199  ·_Cfunc_CString(String s, int8 *p)
  1200  {
  1201  	p = runtime·cmalloc(s.len+1);
  1202  	runtime·memmove((byte*)p, s.str, s.len);
  1203  	p[s.len] = 0;
  1204  	FLUSH(&p);
  1205  }
  1206  
  1207  void
  1208  ·_Cfunc__CMalloc(uintptr n, int8 *p)
  1209  {
  1210  	p = runtime·cmalloc(n);
  1211  	FLUSH(&p);
  1212  }
  1213  `
  1214  
  1215  func (p *Package) cPrologGccgo() string {
  1216  	return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
  1217  }
  1218  
  1219  const cPrologGccgo = `
  1220  #include <stdint.h>
  1221  #include <stdlib.h>
  1222  #include <string.h>
  1223  
  1224  typedef unsigned char byte;
  1225  typedef intptr_t intgo;
  1226  
  1227  struct __go_string {
  1228  	const unsigned char *__data;
  1229  	intgo __length;
  1230  };
  1231  
  1232  typedef struct __go_open_array {
  1233  	void* __values;
  1234  	intgo __count;
  1235  	intgo __capacity;
  1236  } Slice;
  1237  
  1238  struct __go_string __go_byte_array_to_string(const void* p, intgo len);
  1239  struct __go_open_array __go_string_to_byte_array (struct __go_string str);
  1240  
  1241  const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
  1242  	char *p = malloc(s.__length+1);
  1243  	memmove(p, s.__data, s.__length);
  1244  	p[s.__length] = 0;
  1245  	return p;
  1246  }
  1247  
  1248  struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
  1249  	intgo len = (p != NULL) ? strlen(p) : 0;
  1250  	return __go_byte_array_to_string(p, len);
  1251  }
  1252  
  1253  struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
  1254  	return __go_byte_array_to_string(p, n);
  1255  }
  1256  
  1257  Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
  1258  	struct __go_string s = { (const unsigned char *)p, n };
  1259  	return __go_string_to_byte_array(s);
  1260  }
  1261  
  1262  extern void runtime_throw(const char *);
  1263  void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
  1264          void *p = malloc(n);
  1265          if(p == NULL && n == 0)
  1266                  p = malloc(1);
  1267          if(p == NULL)
  1268                  runtime_throw("runtime: C malloc failed");
  1269          return p;
  1270  }
  1271  `
  1272  
  1273  func (p *Package) gccExportHeaderProlog() string {
  1274  	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
  1275  }
  1276  
  1277  const gccExportHeaderProlog = `
  1278  typedef signed char GoInt8;
  1279  typedef unsigned char GoUint8;
  1280  typedef short GoInt16;
  1281  typedef unsigned short GoUint16;
  1282  typedef int GoInt32;
  1283  typedef unsigned int GoUint32;
  1284  typedef long long GoInt64;
  1285  typedef unsigned long long GoUint64;
  1286  typedef GoIntGOINTBITS GoInt;
  1287  typedef GoUintGOINTBITS GoUint;
  1288  typedef __SIZE_TYPE__ GoUintptr;
  1289  typedef float GoFloat32;
  1290  typedef double GoFloat64;
  1291  typedef __complex float GoComplex64;
  1292  typedef __complex double GoComplex128;
  1293  
  1294  typedef struct { char *p; GoInt n; } GoString;
  1295  typedef void *GoMap;
  1296  typedef void *GoChan;
  1297  typedef struct { void *t; void *v; } GoInterface;
  1298  typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  1299  `