github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 convers 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.  For example,
   533  	// on 386 Windows, gcc wants to 8-align int64s, but 8c does not.
   534  	// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
   535  	// and http://golang.org/issue/5603.
   536  	extraAttr := ""
   537  	if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
   538  		extraAttr = ", __gcc_struct__"
   539  	}
   540  	fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__%v)) *a = v;\n", ctype, extraAttr)
   541  	fmt.Fprintf(fgcc, "\t")
   542  	if t := n.FuncType.Result; t != nil {
   543  		fmt.Fprintf(fgcc, "a->r = ")
   544  		if c := t.C.String(); c[len(c)-1] == '*' {
   545  			fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
   546  		}
   547  	}
   548  	fmt.Fprintf(fgcc, "%s(", n.C)
   549  	for i, t := range n.FuncType.Params {
   550  		if i > 0 {
   551  			fmt.Fprintf(fgcc, ", ")
   552  		}
   553  		// We know the type params are correct, because
   554  		// the Go equivalents had good type params.
   555  		// However, our version of the type omits the magic
   556  		// words const and volatile, which can provoke
   557  		// C compiler warnings.  Silence them by casting
   558  		// all pointers to void*.  (Eventually that will produce
   559  		// other warnings.)
   560  		if c := t.C.String(); c[len(c)-1] == '*' {
   561  			fmt.Fprintf(fgcc, "(void*)")
   562  		}
   563  		fmt.Fprintf(fgcc, "a->p%d", i)
   564  	}
   565  	fmt.Fprintf(fgcc, ");\n")
   566  	if n.AddError {
   567  		fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
   568  	}
   569  	fmt.Fprintf(fgcc, "}\n")
   570  	fmt.Fprintf(fgcc, "\n")
   571  }
   572  
   573  // Write out a wrapper for a function when using gccgo.  This is a
   574  // simple wrapper that just calls the real function.  We only need a
   575  // wrapper to support static functions in the prologue--without a
   576  // wrapper, we can't refer to the function, since the reference is in
   577  // a different file.
   578  func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
   579  	if t := n.FuncType.Result; t != nil {
   580  		fmt.Fprintf(fgcc, "%s\n", t.C.String())
   581  	} else {
   582  		fmt.Fprintf(fgcc, "void\n")
   583  	}
   584  	fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
   585  	for i, t := range n.FuncType.Params {
   586  		if i > 0 {
   587  			fmt.Fprintf(fgcc, ", ")
   588  		}
   589  		c := t.Typedef
   590  		if c == "" {
   591  			c = t.C.String()
   592  		}
   593  		fmt.Fprintf(fgcc, "%s p%d", c, i)
   594  	}
   595  	fmt.Fprintf(fgcc, ")\n")
   596  	fmt.Fprintf(fgcc, "{\n")
   597  	fmt.Fprintf(fgcc, "\t")
   598  	if t := n.FuncType.Result; t != nil {
   599  		fmt.Fprintf(fgcc, "return ")
   600  		// Cast to void* to avoid warnings due to omitted qualifiers.
   601  		if c := t.C.String(); c[len(c)-1] == '*' {
   602  			fmt.Fprintf(fgcc, "(void*)")
   603  		}
   604  	}
   605  	fmt.Fprintf(fgcc, "%s(", n.C)
   606  	for i, t := range n.FuncType.Params {
   607  		if i > 0 {
   608  			fmt.Fprintf(fgcc, ", ")
   609  		}
   610  		// Cast to void* to avoid warnings due to omitted qualifiers.
   611  		if c := t.C.String(); c[len(c)-1] == '*' {
   612  			fmt.Fprintf(fgcc, "(void*)")
   613  		}
   614  		fmt.Fprintf(fgcc, "p%d", i)
   615  	}
   616  	fmt.Fprintf(fgcc, ");\n")
   617  	fmt.Fprintf(fgcc, "}\n")
   618  	fmt.Fprintf(fgcc, "\n")
   619  }
   620  
   621  // Write out the various stubs we need to support functions exported
   622  // from Go so that they are callable from C.
   623  func (p *Package) writeExports(fgo2, fc, fm *os.File) {
   624  	fgcc := creat(*objDir + "_cgo_export.c")
   625  	fgcch := creat(*objDir + "_cgo_export.h")
   626  
   627  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   628  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   629  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   630  
   631  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   632  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   633  
   634  	fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
   635  
   636  	for _, exp := range p.ExpFunc {
   637  		fn := exp.Func
   638  
   639  		// Construct a gcc struct matching the 6c argument and
   640  		// result frame.  The gcc struct will be compiled with
   641  		// __attribute__((packed)) so all padding must be accounted
   642  		// for explicitly.
   643  		ctype := "struct {\n"
   644  		off := int64(0)
   645  		npad := 0
   646  		if fn.Recv != nil {
   647  			t := p.cgoType(fn.Recv.List[0].Type)
   648  			ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
   649  			off += t.Size
   650  		}
   651  		fntype := fn.Type
   652  		forFieldList(fntype.Params,
   653  			func(i int, atype ast.Expr) {
   654  				t := p.cgoType(atype)
   655  				if off%t.Align != 0 {
   656  					pad := t.Align - off%t.Align
   657  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   658  					off += pad
   659  					npad++
   660  				}
   661  				ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
   662  				off += t.Size
   663  			})
   664  		if off%p.PtrSize != 0 {
   665  			pad := p.PtrSize - off%p.PtrSize
   666  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   667  			off += pad
   668  			npad++
   669  		}
   670  		forFieldList(fntype.Results,
   671  			func(i int, atype ast.Expr) {
   672  				t := p.cgoType(atype)
   673  				if off%t.Align != 0 {
   674  					pad := t.Align - off%t.Align
   675  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   676  					off += pad
   677  					npad++
   678  				}
   679  				ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
   680  				off += t.Size
   681  			})
   682  		if off%p.PtrSize != 0 {
   683  			pad := p.PtrSize - off%p.PtrSize
   684  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   685  			off += pad
   686  			npad++
   687  		}
   688  		if ctype == "struct {\n" {
   689  			ctype += "\t\tchar unused;\n" // avoid empty struct
   690  		}
   691  		ctype += "\t}"
   692  
   693  		// Get the return type of the wrapper function
   694  		// compiled by gcc.
   695  		gccResult := ""
   696  		if fntype.Results == nil || len(fntype.Results.List) == 0 {
   697  			gccResult = "void"
   698  		} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   699  			gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
   700  		} else {
   701  			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
   702  			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
   703  			forFieldList(fntype.Results,
   704  				func(i int, atype ast.Expr) {
   705  					fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
   706  				})
   707  			fmt.Fprintf(fgcch, "};\n")
   708  			gccResult = "struct " + exp.ExpName + "_return"
   709  		}
   710  
   711  		// Build the wrapper function compiled by gcc.
   712  		s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
   713  		if fn.Recv != nil {
   714  			s += p.cgoType(fn.Recv.List[0].Type).C.String()
   715  			s += " recv"
   716  		}
   717  		forFieldList(fntype.Params,
   718  			func(i int, atype ast.Expr) {
   719  				if i > 0 || fn.Recv != nil {
   720  					s += ", "
   721  				}
   722  				s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
   723  			})
   724  		s += ")"
   725  		fmt.Fprintf(fgcch, "\nextern %s;\n", s)
   726  
   727  		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
   728  		fmt.Fprintf(fgcc, "\n%s\n", s)
   729  		fmt.Fprintf(fgcc, "{\n")
   730  		fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype)
   731  		if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
   732  			fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
   733  		}
   734  		if fn.Recv != nil {
   735  			fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
   736  		}
   737  		forFieldList(fntype.Params,
   738  			func(i int, atype ast.Expr) {
   739  				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
   740  			})
   741  		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
   742  		if gccResult != "void" {
   743  			if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   744  				fmt.Fprintf(fgcc, "\treturn a.r0;\n")
   745  			} else {
   746  				forFieldList(fntype.Results,
   747  					func(i int, atype ast.Expr) {
   748  						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
   749  					})
   750  				fmt.Fprintf(fgcc, "\treturn r;\n")
   751  			}
   752  		}
   753  		fmt.Fprintf(fgcc, "}\n")
   754  
   755  		// Build the wrapper function compiled by 6c/8c
   756  		goname := exp.Func.Name.Name
   757  		if fn.Recv != nil {
   758  			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
   759  		}
   760  		fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
   761  		fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
   762  		fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
   763  		fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
   764  		fmt.Fprintf(fc, "void\n")
   765  		fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
   766  		fmt.Fprintf(fc, "{\n")
   767  		fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
   768  		fmt.Fprintf(fc, "}\n")
   769  
   770  		fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
   771  
   772  		// Calling a function with a receiver from C requires
   773  		// a Go wrapper function.
   774  		if fn.Recv != nil {
   775  			fmt.Fprintf(fgo2, "func %s(recv ", goname)
   776  			conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   777  			forFieldList(fntype.Params,
   778  				func(i int, atype ast.Expr) {
   779  					fmt.Fprintf(fgo2, ", p%d ", i)
   780  					conf.Fprint(fgo2, fset, atype)
   781  				})
   782  			fmt.Fprintf(fgo2, ")")
   783  			if gccResult != "void" {
   784  				fmt.Fprint(fgo2, " (")
   785  				forFieldList(fntype.Results,
   786  					func(i int, atype ast.Expr) {
   787  						if i > 0 {
   788  							fmt.Fprint(fgo2, ", ")
   789  						}
   790  						conf.Fprint(fgo2, fset, atype)
   791  					})
   792  				fmt.Fprint(fgo2, ")")
   793  			}
   794  			fmt.Fprint(fgo2, " {\n")
   795  			fmt.Fprint(fgo2, "\t")
   796  			if gccResult != "void" {
   797  				fmt.Fprint(fgo2, "return ")
   798  			}
   799  			fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
   800  			forFieldList(fntype.Params,
   801  				func(i int, atype ast.Expr) {
   802  					if i > 0 {
   803  						fmt.Fprint(fgo2, ", ")
   804  					}
   805  					fmt.Fprintf(fgo2, "p%d", i)
   806  				})
   807  			fmt.Fprint(fgo2, ")\n")
   808  			fmt.Fprint(fgo2, "}\n")
   809  		}
   810  	}
   811  }
   812  
   813  // Write out the C header allowing C code to call exported gccgo functions.
   814  func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
   815  	fgcc := creat(*objDir + "_cgo_export.c")
   816  	fgcch := creat(*objDir + "_cgo_export.h")
   817  
   818  	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
   819  
   820  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   821  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   822  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   823  
   824  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   825  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   826  
   827  	fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
   828  
   829  	for _, exp := range p.ExpFunc {
   830  		fn := exp.Func
   831  		fntype := fn.Type
   832  
   833  		cdeclBuf := new(bytes.Buffer)
   834  		resultCount := 0
   835  		forFieldList(fntype.Results,
   836  			func(i int, atype ast.Expr) { resultCount++ })
   837  		switch resultCount {
   838  		case 0:
   839  			fmt.Fprintf(cdeclBuf, "void")
   840  		case 1:
   841  			forFieldList(fntype.Results,
   842  				func(i int, atype ast.Expr) {
   843  					t := p.cgoType(atype)
   844  					fmt.Fprintf(cdeclBuf, "%s", t.C)
   845  				})
   846  		default:
   847  			// Declare a result struct.
   848  			fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
   849  			forFieldList(fntype.Results,
   850  				func(i int, atype ast.Expr) {
   851  					t := p.cgoType(atype)
   852  					fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
   853  				})
   854  			fmt.Fprintf(fgcch, "};\n")
   855  			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
   856  		}
   857  
   858  		cRet := cdeclBuf.String()
   859  
   860  		cdeclBuf = new(bytes.Buffer)
   861  		fmt.Fprintf(cdeclBuf, "(")
   862  		if fn.Recv != nil {
   863  			fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
   864  		}
   865  		// Function parameters.
   866  		forFieldList(fntype.Params,
   867  			func(i int, atype ast.Expr) {
   868  				if i > 0 || fn.Recv != nil {
   869  					fmt.Fprintf(cdeclBuf, ", ")
   870  				}
   871  				t := p.cgoType(atype)
   872  				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
   873  			})
   874  		fmt.Fprintf(cdeclBuf, ")")
   875  		cParams := cdeclBuf.String()
   876  
   877  		goName := "Cgoexp_" + exp.ExpName
   878  		fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
   879  		fmt.Fprint(fgcch, "\n")
   880  
   881  		fmt.Fprint(fgcc, "\n")
   882  		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
   883  		fmt.Fprint(fgcc, "\t")
   884  		if resultCount > 0 {
   885  			fmt.Fprint(fgcc, "return ")
   886  		}
   887  		fmt.Fprintf(fgcc, "%s(", goName)
   888  		if fn.Recv != nil {
   889  			fmt.Fprint(fgcc, "recv")
   890  		}
   891  		forFieldList(fntype.Params,
   892  			func(i int, atype ast.Expr) {
   893  				if i > 0 || fn.Recv != nil {
   894  					fmt.Fprintf(fgcc, ", ")
   895  				}
   896  				fmt.Fprintf(fgcc, "p%d", i)
   897  			})
   898  		fmt.Fprint(fgcc, ");\n")
   899  		fmt.Fprint(fgcc, "}\n")
   900  
   901  		// Dummy declaration for _cgo_main.c
   902  		fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
   903  
   904  		// For gccgo we use a wrapper function in Go, in order
   905  		// to call CgocallBack and CgocallBackDone.
   906  
   907  		// This code uses printer.Fprint, not conf.Fprint,
   908  		// because we don't want //line comments in the middle
   909  		// of the function types.
   910  		fmt.Fprint(fgo2, "\n")
   911  		fmt.Fprintf(fgo2, "func %s(", goName)
   912  		if fn.Recv != nil {
   913  			fmt.Fprint(fgo2, "recv ")
   914  			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   915  		}
   916  		forFieldList(fntype.Params,
   917  			func(i int, atype ast.Expr) {
   918  				if i > 0 || fn.Recv != nil {
   919  					fmt.Fprintf(fgo2, ", ")
   920  				}
   921  				fmt.Fprintf(fgo2, "p%d ", i)
   922  				printer.Fprint(fgo2, fset, atype)
   923  			})
   924  		fmt.Fprintf(fgo2, ")")
   925  		if resultCount > 0 {
   926  			fmt.Fprintf(fgo2, " (")
   927  			forFieldList(fntype.Results,
   928  				func(i int, atype ast.Expr) {
   929  					if i > 0 {
   930  						fmt.Fprint(fgo2, ", ")
   931  					}
   932  					printer.Fprint(fgo2, fset, atype)
   933  				})
   934  			fmt.Fprint(fgo2, ")")
   935  		}
   936  		fmt.Fprint(fgo2, " {\n")
   937  		fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
   938  		fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
   939  		fmt.Fprint(fgo2, "\t")
   940  		if resultCount > 0 {
   941  			fmt.Fprint(fgo2, "return ")
   942  		}
   943  		if fn.Recv != nil {
   944  			fmt.Fprint(fgo2, "recv.")
   945  		}
   946  		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
   947  		forFieldList(fntype.Params,
   948  			func(i int, atype ast.Expr) {
   949  				if i > 0 {
   950  					fmt.Fprint(fgo2, ", ")
   951  				}
   952  				fmt.Fprintf(fgo2, "p%d", i)
   953  			})
   954  		fmt.Fprint(fgo2, ")\n")
   955  		fmt.Fprint(fgo2, "}\n")
   956  	}
   957  }
   958  
   959  // Return the package prefix when using gccgo.
   960  func (p *Package) gccgoSymbolPrefix() string {
   961  	if !*gccgo {
   962  		return ""
   963  	}
   964  
   965  	clean := func(r rune) rune {
   966  		switch {
   967  		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
   968  			'0' <= r && r <= '9':
   969  			return r
   970  		}
   971  		return '_'
   972  	}
   973  
   974  	if *gccgopkgpath != "" {
   975  		return strings.Map(clean, *gccgopkgpath)
   976  	}
   977  	if *gccgoprefix == "" && p.PackageName == "main" {
   978  		return "main"
   979  	}
   980  	prefix := strings.Map(clean, *gccgoprefix)
   981  	if prefix == "" {
   982  		prefix = "go"
   983  	}
   984  	return prefix + "." + p.PackageName
   985  }
   986  
   987  // Call a function for each entry in an ast.FieldList, passing the
   988  // index into the list and the type.
   989  func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
   990  	if fl == nil {
   991  		return
   992  	}
   993  	i := 0
   994  	for _, r := range fl.List {
   995  		if r.Names == nil {
   996  			fn(i, r.Type)
   997  			i++
   998  		} else {
   999  			for _ = range r.Names {
  1000  				fn(i, r.Type)
  1001  				i++
  1002  			}
  1003  		}
  1004  	}
  1005  }
  1006  
  1007  func c(repr string, args ...interface{}) *TypeRepr {
  1008  	return &TypeRepr{repr, args}
  1009  }
  1010  
  1011  // Map predeclared Go types to Type.
  1012  var goTypes = map[string]*Type{
  1013  	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
  1014  	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
  1015  	"int":        {Size: 0, Align: 0, C: c("GoInt")},
  1016  	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
  1017  	"rune":       {Size: 4, Align: 4, C: c("GoInt32")},
  1018  	"int8":       {Size: 1, Align: 1, C: c("GoInt8")},
  1019  	"uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
  1020  	"int16":      {Size: 2, Align: 2, C: c("GoInt16")},
  1021  	"uint16":     {Size: 2, Align: 2, C: c("GoUint16")},
  1022  	"int32":      {Size: 4, Align: 4, C: c("GoInt32")},
  1023  	"uint32":     {Size: 4, Align: 4, C: c("GoUint32")},
  1024  	"int64":      {Size: 8, Align: 8, C: c("GoInt64")},
  1025  	"uint64":     {Size: 8, Align: 8, C: c("GoUint64")},
  1026  	"float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
  1027  	"float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
  1028  	"complex64":  {Size: 8, Align: 8, C: c("GoComplex64")},
  1029  	"complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
  1030  }
  1031  
  1032  // Map an ast type to a Type.
  1033  func (p *Package) cgoType(e ast.Expr) *Type {
  1034  	switch t := e.(type) {
  1035  	case *ast.StarExpr:
  1036  		x := p.cgoType(t.X)
  1037  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
  1038  	case *ast.ArrayType:
  1039  		if t.Len == nil {
  1040  			// Slice: pointer, len, cap.
  1041  			return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")}
  1042  		}
  1043  	case *ast.StructType:
  1044  		// TODO
  1045  	case *ast.FuncType:
  1046  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
  1047  	case *ast.InterfaceType:
  1048  		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
  1049  	case *ast.MapType:
  1050  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
  1051  	case *ast.ChanType:
  1052  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
  1053  	case *ast.Ident:
  1054  		// Look up the type in the top level declarations.
  1055  		// TODO: Handle types defined within a function.
  1056  		for _, d := range p.Decl {
  1057  			gd, ok := d.(*ast.GenDecl)
  1058  			if !ok || gd.Tok != token.TYPE {
  1059  				continue
  1060  			}
  1061  			for _, spec := range gd.Specs {
  1062  				ts, ok := spec.(*ast.TypeSpec)
  1063  				if !ok {
  1064  					continue
  1065  				}
  1066  				if ts.Name.Name == t.Name {
  1067  					return p.cgoType(ts.Type)
  1068  				}
  1069  			}
  1070  		}
  1071  		if def := typedef[t.Name]; def != nil {
  1072  			return def
  1073  		}
  1074  		if t.Name == "uintptr" {
  1075  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
  1076  		}
  1077  		if t.Name == "string" {
  1078  			// The string data is 1 pointer + 1 (pointer-sized) int.
  1079  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
  1080  		}
  1081  		if t.Name == "error" {
  1082  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
  1083  		}
  1084  		if r, ok := goTypes[t.Name]; ok {
  1085  			if r.Size == 0 { // int or uint
  1086  				rr := new(Type)
  1087  				*rr = *r
  1088  				rr.Size = p.IntSize
  1089  				rr.Align = p.IntSize
  1090  				r = rr
  1091  			}
  1092  			if r.Align > p.PtrSize {
  1093  				r.Align = p.PtrSize
  1094  			}
  1095  			return r
  1096  		}
  1097  		error_(e.Pos(), "unrecognized Go type %s", t.Name)
  1098  		return &Type{Size: 4, Align: 4, C: c("int")}
  1099  	case *ast.SelectorExpr:
  1100  		id, ok := t.X.(*ast.Ident)
  1101  		if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
  1102  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
  1103  		}
  1104  	}
  1105  	error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
  1106  	return &Type{Size: 4, Align: 4, C: c("int")}
  1107  }
  1108  
  1109  const gccProlog = `
  1110  // Usual nonsense: if x and y are not equal, the type will be invalid
  1111  // (have a negative array count) and an inscrutable error will come
  1112  // out of the compiler and hopefully mention "name".
  1113  #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
  1114  
  1115  // Check at compile time that the sizes we use match our expectations.
  1116  #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
  1117  
  1118  __cgo_size_assert(char, 1)
  1119  __cgo_size_assert(short, 2)
  1120  __cgo_size_assert(int, 4)
  1121  typedef long long __cgo_long_long;
  1122  __cgo_size_assert(__cgo_long_long, 8)
  1123  __cgo_size_assert(float, 4)
  1124  __cgo_size_assert(double, 8)
  1125  
  1126  #include <errno.h>
  1127  #include <string.h>
  1128  `
  1129  
  1130  const builtinProlog = `
  1131  #include <sys/types.h> /* for size_t below */
  1132  
  1133  /* Define intgo when compiling with GCC.  */
  1134  #ifdef __PTRDIFF_TYPE__
  1135  typedef __PTRDIFF_TYPE__ intgo;
  1136  #elif defined(_LP64)
  1137  typedef long long intgo;
  1138  #else
  1139  typedef int intgo;
  1140  #endif
  1141  
  1142  typedef struct { char *p; intgo n; } _GoString_;
  1143  typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
  1144  _GoString_ GoString(char *p);
  1145  _GoString_ GoStringN(char *p, int l);
  1146  _GoBytes_ GoBytes(void *p, int n);
  1147  char *CString(_GoString_);
  1148  void *_CMalloc(size_t);
  1149  `
  1150  
  1151  const cProlog = `
  1152  #include "runtime.h"
  1153  #include "cgocall.h"
  1154  
  1155  void ·_Cerrno(void*, int32);
  1156  
  1157  void
  1158  ·_Cfunc_GoString(int8 *p, String s)
  1159  {
  1160  	s = runtime·gostring((byte*)p);
  1161  	FLUSH(&s);
  1162  }
  1163  
  1164  void
  1165  ·_Cfunc_GoStringN(int8 *p, int32 l, String s)
  1166  {
  1167  	s = runtime·gostringn((byte*)p, l);
  1168  	FLUSH(&s);
  1169  }
  1170  
  1171  void
  1172  ·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
  1173  {
  1174  	s = runtime·gobytes((byte*)p, l);
  1175  	FLUSH(&s);
  1176  }
  1177  
  1178  void
  1179  ·_Cfunc_CString(String s, int8 *p)
  1180  {
  1181  	p = runtime·cmalloc(s.len+1);
  1182  	runtime·memmove((byte*)p, s.str, s.len);
  1183  	p[s.len] = 0;
  1184  	FLUSH(&p);
  1185  }
  1186  
  1187  void
  1188  ·_Cfunc__CMalloc(uintptr n, int8 *p)
  1189  {
  1190  	p = runtime·cmalloc(n);
  1191  	FLUSH(&p);
  1192  }
  1193  `
  1194  
  1195  func (p *Package) cPrologGccgo() string {
  1196  	return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
  1197  }
  1198  
  1199  const cPrologGccgo = `
  1200  #include <stdint.h>
  1201  #include <stdlib.h>
  1202  #include <string.h>
  1203  
  1204  typedef unsigned char byte;
  1205  typedef intptr_t intgo;
  1206  
  1207  struct __go_string {
  1208  	const unsigned char *__data;
  1209  	intgo __length;
  1210  };
  1211  
  1212  typedef struct __go_open_array {
  1213  	void* __values;
  1214  	intgo __count;
  1215  	intgo __capacity;
  1216  } Slice;
  1217  
  1218  struct __go_string __go_byte_array_to_string(const void* p, intgo len);
  1219  struct __go_open_array __go_string_to_byte_array (struct __go_string str);
  1220  
  1221  const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
  1222  	return strndup((const char*)s.__data, s.__length);
  1223  }
  1224  
  1225  struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
  1226  	intgo len = (p != NULL) ? strlen(p) : 0;
  1227  	return __go_byte_array_to_string(p, len);
  1228  }
  1229  
  1230  struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
  1231  	return __go_byte_array_to_string(p, n);
  1232  }
  1233  
  1234  Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
  1235  	struct __go_string s = { (const unsigned char *)p, n };
  1236  	return __go_string_to_byte_array(s);
  1237  }
  1238  
  1239  extern void runtime_throw(const char *);
  1240  void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
  1241          void *p = malloc(n);
  1242          if(p == NULL && n == 0)
  1243                  p = malloc(1);
  1244          if(p == NULL)
  1245                  runtime_throw("runtime: C malloc failed");
  1246          return p;
  1247  }
  1248  `
  1249  
  1250  func (p *Package) gccExportHeaderProlog() string {
  1251  	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
  1252  }
  1253  
  1254  const gccExportHeaderProlog = `
  1255  typedef signed char GoInt8;
  1256  typedef unsigned char GoUint8;
  1257  typedef short GoInt16;
  1258  typedef unsigned short GoUint16;
  1259  typedef int GoInt32;
  1260  typedef unsigned int GoUint32;
  1261  typedef long long GoInt64;
  1262  typedef unsigned long long GoUint64;
  1263  typedef GoIntGOINTBITS GoInt;
  1264  typedef GoUintGOINTBITS GoUint;
  1265  typedef __SIZE_TYPE__ GoUintptr;
  1266  typedef float GoFloat32;
  1267  typedef double GoFloat64;
  1268  typedef __complex float GoComplex64;
  1269  typedef __complex double GoComplex128;
  1270  
  1271  typedef struct { char *p; GoInt n; } GoString;
  1272  typedef void *GoMap;
  1273  typedef void *GoChan;
  1274  typedef struct { void *t; void *v; } GoInterface;
  1275  typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  1276  `