github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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" {
    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);")
    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, 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.Kind != "var" {
   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  			fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
   109  			fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
   110  
   111  			cVars[n.C] = true
   112  		}
   113  
   114  		if *gccgo {
   115  			fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
   116  			fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
   117  		} else {
   118  			fmt.Fprintf(fc, "void *·%s = &%s;\n", n.Mangle, n.C)
   119  		}
   120  		fmt.Fprintf(fc, "\n")
   121  
   122  		fmt.Fprintf(fgo2, "var %s ", n.Mangle)
   123  		conf.Fprint(fgo2, fset, &ast.StarExpr{X: n.Type.Go})
   124  		fmt.Fprintf(fgo2, "\n")
   125  	}
   126  	fmt.Fprintf(fc, "\n")
   127  
   128  	for _, key := range nameKeys(p.Name) {
   129  		n := p.Name[key]
   130  		if n.Const != "" {
   131  			fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
   132  		}
   133  	}
   134  	fmt.Fprintf(fgo2, "\n")
   135  
   136  	for _, key := range nameKeys(p.Name) {
   137  		n := p.Name[key]
   138  		if n.FuncType != nil {
   139  			p.writeDefsFunc(fc, fgo2, n)
   140  		}
   141  	}
   142  
   143  	if *gccgo {
   144  		p.writeGccgoExports(fgo2, fc, fm)
   145  	} else {
   146  		p.writeExports(fgo2, fc, fm)
   147  	}
   148  
   149  	init := gccgoInit.String()
   150  	if init != "" {
   151  		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
   152  		fmt.Fprintln(fc, "static void init(void) {")
   153  		fmt.Fprint(fc, init)
   154  		fmt.Fprintln(fc, "}")
   155  	}
   156  
   157  	fgo2.Close()
   158  	fc.Close()
   159  }
   160  
   161  func dynimport(obj string) {
   162  	stdout := os.Stdout
   163  	if *dynout != "" {
   164  		f, err := os.Create(*dynout)
   165  		if err != nil {
   166  			fatalf("%s", err)
   167  		}
   168  		stdout = f
   169  	}
   170  
   171  	if f, err := elf.Open(obj); err == nil {
   172  		if *dynlinker {
   173  			// Emit the cgo_dynamic_linker line.
   174  			if sec := f.Section(".interp"); sec != nil {
   175  				if data, err := sec.Data(); err == nil && len(data) > 1 {
   176  					// skip trailing \0 in data
   177  					fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
   178  				}
   179  			}
   180  		}
   181  		sym, err := f.ImportedSymbols()
   182  		if err != nil {
   183  			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
   184  		}
   185  		for _, s := range sym {
   186  			targ := s.Name
   187  			if s.Version != "" {
   188  				targ += "#" + s.Version
   189  			}
   190  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
   191  		}
   192  		lib, err := f.ImportedLibraries()
   193  		if err != nil {
   194  			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
   195  		}
   196  		for _, l := range lib {
   197  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
   198  		}
   199  		return
   200  	}
   201  
   202  	if f, err := macho.Open(obj); err == nil {
   203  		sym, err := f.ImportedSymbols()
   204  		if err != nil {
   205  			fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
   206  		}
   207  		for _, s := range sym {
   208  			if len(s) > 0 && s[0] == '_' {
   209  				s = s[1:]
   210  			}
   211  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
   212  		}
   213  		lib, err := f.ImportedLibraries()
   214  		if err != nil {
   215  			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
   216  		}
   217  		for _, l := range lib {
   218  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
   219  		}
   220  		return
   221  	}
   222  
   223  	if f, err := pe.Open(obj); err == nil {
   224  		sym, err := f.ImportedSymbols()
   225  		if err != nil {
   226  			fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
   227  		}
   228  		for _, s := range sym {
   229  			ss := strings.Split(s, ":")
   230  			name := strings.Split(ss[0], "@")[0]
   231  			fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
   232  		}
   233  		return
   234  	}
   235  
   236  	fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
   237  }
   238  
   239  // Construct a gcc struct matching the 6c argument frame.
   240  // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
   241  // These assumptions are checked by the gccProlog.
   242  // Also assumes that 6c convention is to word-align the
   243  // input and output parameters.
   244  func (p *Package) structType(n *Name) (string, int64) {
   245  	var buf bytes.Buffer
   246  	fmt.Fprint(&buf, "struct {\n")
   247  	off := int64(0)
   248  	for i, t := range n.FuncType.Params {
   249  		if off%t.Align != 0 {
   250  			pad := t.Align - off%t.Align
   251  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   252  			off += pad
   253  		}
   254  		c := t.Typedef
   255  		if c == "" {
   256  			c = t.C.String()
   257  		}
   258  		fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
   259  		off += t.Size
   260  	}
   261  	if off%p.PtrSize != 0 {
   262  		pad := p.PtrSize - off%p.PtrSize
   263  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   264  		off += pad
   265  	}
   266  	if t := n.FuncType.Result; t != nil {
   267  		if off%t.Align != 0 {
   268  			pad := t.Align - off%t.Align
   269  			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   270  			off += pad
   271  		}
   272  		qual := ""
   273  		if c := t.C.String(); c[len(c)-1] == '*' {
   274  			qual = "const "
   275  		}
   276  		fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
   277  		off += t.Size
   278  	}
   279  	if off%p.PtrSize != 0 {
   280  		pad := p.PtrSize - off%p.PtrSize
   281  		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
   282  		off += pad
   283  	}
   284  	if n.AddError {
   285  		fmt.Fprint(&buf, "\t\tvoid *e[2]; /* error */\n")
   286  		off += 2 * p.PtrSize
   287  	}
   288  	if off == 0 {
   289  		fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
   290  	}
   291  	fmt.Fprintf(&buf, "\t}")
   292  	return buf.String(), off
   293  }
   294  
   295  func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
   296  	name := n.Go
   297  	gtype := n.FuncType.Go
   298  	void := gtype.Results == nil || len(gtype.Results.List) == 0
   299  	if n.AddError {
   300  		// Add "error" to return type list.
   301  		// Type list is known to be 0 or 1 element - it's a C function.
   302  		err := &ast.Field{Type: ast.NewIdent("error")}
   303  		l := gtype.Results.List
   304  		if len(l) == 0 {
   305  			l = []*ast.Field{err}
   306  		} else {
   307  			l = []*ast.Field{l[0], err}
   308  		}
   309  		t := new(ast.FuncType)
   310  		*t = *gtype
   311  		t.Results = &ast.FieldList{List: l}
   312  		gtype = t
   313  	}
   314  
   315  	// Go func declaration.
   316  	d := &ast.FuncDecl{
   317  		Name: ast.NewIdent(n.Mangle),
   318  		Type: gtype,
   319  	}
   320  
   321  	if *gccgo {
   322  		// Gccgo style hooks.
   323  		fmt.Fprint(fgo2, "\n")
   324  		cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
   325  		paramnames := []string(nil)
   326  		for i, param := range d.Type.Params.List {
   327  			paramName := fmt.Sprintf("p%d", i)
   328  			param.Names = []*ast.Ident{ast.NewIdent(paramName)}
   329  			paramnames = append(paramnames, paramName)
   330  		}
   331  
   332  		conf.Fprint(fgo2, fset, d)
   333  		fmt.Fprint(fgo2, " {\n")
   334  		fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
   335  		fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
   336  		if n.AddError {
   337  			fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
   338  		}
   339  		fmt.Fprint(fgo2, "\t")
   340  		if !void {
   341  			fmt.Fprint(fgo2, "r := ")
   342  		}
   343  		fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
   344  
   345  		if n.AddError {
   346  			fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
   347  			fmt.Fprint(fgo2, "\tif e != 0 {\n")
   348  			fmt.Fprint(fgo2, "\t\treturn ")
   349  			if !void {
   350  				fmt.Fprint(fgo2, "r, ")
   351  			}
   352  			fmt.Fprint(fgo2, "e\n")
   353  			fmt.Fprint(fgo2, "\t}\n")
   354  			fmt.Fprint(fgo2, "\treturn ")
   355  			if !void {
   356  				fmt.Fprint(fgo2, "r, ")
   357  			}
   358  			fmt.Fprint(fgo2, "nil\n")
   359  		} else if !void {
   360  			fmt.Fprint(fgo2, "\treturn r\n")
   361  		}
   362  
   363  		fmt.Fprint(fgo2, "}\n")
   364  
   365  		// declare the C function.
   366  		fmt.Fprintf(fgo2, "//extern %s\n", n.C)
   367  		d.Name = ast.NewIdent(cname)
   368  		if n.AddError {
   369  			l := d.Type.Results.List
   370  			d.Type.Results.List = l[:len(l)-1]
   371  		}
   372  		conf.Fprint(fgo2, fset, d)
   373  		fmt.Fprint(fgo2, "\n")
   374  
   375  		return
   376  	}
   377  	conf.Fprint(fgo2, fset, d)
   378  	fmt.Fprint(fgo2, "\n")
   379  
   380  	if name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" {
   381  		// The builtins are already defined in the C prolog.
   382  		return
   383  	}
   384  
   385  	var argSize int64
   386  	_, argSize = p.structType(n)
   387  
   388  	// C wrapper calls into gcc, passing a pointer to the argument frame.
   389  	fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangle)
   390  	fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
   391  	fmt.Fprintf(fc, "\n")
   392  	fmt.Fprintf(fc, "void\n")
   393  	if argSize == 0 {
   394  		argSize++
   395  	}
   396  	fmt.Fprintf(fc, "·%s(struct{uint8 x[%d];}p)\n", n.Mangle, argSize)
   397  	fmt.Fprintf(fc, "{\n")
   398  	fmt.Fprintf(fc, "\truntime·cgocall(_cgo%s%s, &p);\n", cPrefix, n.Mangle)
   399  	if n.AddError {
   400  		// gcc leaves errno in first word of interface at end of p.
   401  		// check whether it is zero; if so, turn interface into nil.
   402  		// if not, turn interface into errno.
   403  		// Go init function initializes ·_Cerrno with an os.Errno
   404  		// for us to copy.
   405  		fmt.Fprintln(fc, `	{
   406  			int32 e;
   407  			void **v;
   408  			v = (void**)(&p+1) - 2;	/* v = final two void* of p */
   409  			e = *(int32*)v;
   410  			v[0] = (void*)0xdeadbeef;
   411  			v[1] = (void*)0xdeadbeef;
   412  			if(e == 0) {
   413  				/* nil interface */
   414  				v[0] = 0;
   415  				v[1] = 0;
   416  			} else {
   417  				·_Cerrno(v, e);	/* fill in v as error for errno e */
   418  			}
   419  		}`)
   420  	}
   421  	fmt.Fprintf(fc, "}\n")
   422  	fmt.Fprintf(fc, "\n")
   423  }
   424  
   425  // writeOutput creates stubs for a specific source file to be compiled by 6g
   426  // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
   427  func (p *Package) writeOutput(f *File, srcfile string) {
   428  	base := srcfile
   429  	if strings.HasSuffix(base, ".go") {
   430  		base = base[0 : len(base)-3]
   431  	}
   432  	base = strings.Map(slashToUnderscore, base)
   433  	fgo1 := creat(*objDir + base + ".cgo1.go")
   434  	fgcc := creat(*objDir + base + ".cgo2.c")
   435  
   436  	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
   437  	p.GccFiles = append(p.GccFiles, base+".cgo2.c")
   438  
   439  	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
   440  	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
   441  	conf.Fprint(fgo1, fset, f.AST)
   442  
   443  	// While we process the vars and funcs, also write 6c and gcc output.
   444  	// Gcc output starts with the preamble.
   445  	fmt.Fprintf(fgcc, "%s\n", f.Preamble)
   446  	fmt.Fprintf(fgcc, "%s\n", gccProlog)
   447  
   448  	for _, key := range nameKeys(f.Name) {
   449  		n := f.Name[key]
   450  		if n.FuncType != nil {
   451  			p.writeOutputFunc(fgcc, n)
   452  		}
   453  	}
   454  
   455  	fgo1.Close()
   456  	fgcc.Close()
   457  }
   458  
   459  func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
   460  	name := n.Mangle
   461  	if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] {
   462  		// The builtins are already defined in the C prolog, and we don't
   463  		// want to duplicate function definitions we've already done.
   464  		return
   465  	}
   466  	p.Written[name] = true
   467  
   468  	if *gccgo {
   469  		// we don't use wrappers with gccgo.
   470  		return
   471  	}
   472  
   473  	ctype, _ := p.structType(n)
   474  
   475  	// Gcc wrapper unpacks the C argument struct
   476  	// and calls the actual C function.
   477  	fmt.Fprintf(fgcc, "void\n")
   478  	fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
   479  	fmt.Fprintf(fgcc, "{\n")
   480  	if n.AddError {
   481  		fmt.Fprintf(fgcc, "\tint e;\n") // assuming 32 bit (see comment above structType)
   482  		fmt.Fprintf(fgcc, "\terrno = 0;\n")
   483  	}
   484  	// We're trying to write a gcc struct that matches 6c/8c/5c's layout.
   485  	// Use packed attribute to force no padding in this struct in case
   486  	// gcc has different packing requirements.  For example,
   487  	// on 386 Windows, gcc wants to 8-align int64s, but 8c does not.
   488  	fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__)) *a = v;\n", ctype)
   489  	fmt.Fprintf(fgcc, "\t")
   490  	if t := n.FuncType.Result; t != nil {
   491  		fmt.Fprintf(fgcc, "a->r = ")
   492  		if c := t.C.String(); c[len(c)-1] == '*' {
   493  			fmt.Fprintf(fgcc, "(const %s) ", t.C)
   494  		}
   495  	}
   496  	fmt.Fprintf(fgcc, "%s(", n.C)
   497  	for i, t := range n.FuncType.Params {
   498  		if i > 0 {
   499  			fmt.Fprintf(fgcc, ", ")
   500  		}
   501  		// We know the type params are correct, because
   502  		// the Go equivalents had good type params.
   503  		// However, our version of the type omits the magic
   504  		// words const and volatile, which can provoke
   505  		// C compiler warnings.  Silence them by casting
   506  		// all pointers to void*.  (Eventually that will produce
   507  		// other warnings.)
   508  		if c := t.C.String(); c[len(c)-1] == '*' {
   509  			fmt.Fprintf(fgcc, "(void*)")
   510  		}
   511  		fmt.Fprintf(fgcc, "a->p%d", i)
   512  	}
   513  	fmt.Fprintf(fgcc, ");\n")
   514  	if n.AddError {
   515  		fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
   516  	}
   517  	fmt.Fprintf(fgcc, "}\n")
   518  	fmt.Fprintf(fgcc, "\n")
   519  }
   520  
   521  // Write out the various stubs we need to support functions exported
   522  // from Go so that they are callable from C.
   523  func (p *Package) writeExports(fgo2, fc, fm *os.File) {
   524  	fgcc := creat(*objDir + "_cgo_export.c")
   525  	fgcch := creat(*objDir + "_cgo_export.h")
   526  
   527  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   528  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   529  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   530  
   531  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   532  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   533  
   534  	fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n")
   535  
   536  	for _, exp := range p.ExpFunc {
   537  		fn := exp.Func
   538  
   539  		// Construct a gcc struct matching the 6c argument and
   540  		// result frame.  The gcc struct will be compiled with
   541  		// __attribute__((packed)) so all padding must be accounted
   542  		// for explicitly.
   543  		ctype := "struct {\n"
   544  		off := int64(0)
   545  		npad := 0
   546  		if fn.Recv != nil {
   547  			t := p.cgoType(fn.Recv.List[0].Type)
   548  			ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
   549  			off += t.Size
   550  		}
   551  		fntype := fn.Type
   552  		forFieldList(fntype.Params,
   553  			func(i int, atype ast.Expr) {
   554  				t := p.cgoType(atype)
   555  				if off%t.Align != 0 {
   556  					pad := t.Align - off%t.Align
   557  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   558  					off += pad
   559  					npad++
   560  				}
   561  				ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
   562  				off += t.Size
   563  			})
   564  		if off%p.PtrSize != 0 {
   565  			pad := p.PtrSize - off%p.PtrSize
   566  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   567  			off += pad
   568  			npad++
   569  		}
   570  		forFieldList(fntype.Results,
   571  			func(i int, atype ast.Expr) {
   572  				t := p.cgoType(atype)
   573  				if off%t.Align != 0 {
   574  					pad := t.Align - off%t.Align
   575  					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   576  					off += pad
   577  					npad++
   578  				}
   579  				ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
   580  				off += t.Size
   581  			})
   582  		if off%p.PtrSize != 0 {
   583  			pad := p.PtrSize - off%p.PtrSize
   584  			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
   585  			off += pad
   586  			npad++
   587  		}
   588  		if ctype == "struct {\n" {
   589  			ctype += "\t\tchar unused;\n" // avoid empty struct
   590  		}
   591  		ctype += "\t}"
   592  
   593  		// Get the return type of the wrapper function
   594  		// compiled by gcc.
   595  		gccResult := ""
   596  		if fntype.Results == nil || len(fntype.Results.List) == 0 {
   597  			gccResult = "void"
   598  		} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   599  			gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
   600  		} else {
   601  			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
   602  			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
   603  			forFieldList(fntype.Results,
   604  				func(i int, atype ast.Expr) {
   605  					fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
   606  				})
   607  			fmt.Fprintf(fgcch, "};\n")
   608  			gccResult = "struct " + exp.ExpName + "_return"
   609  		}
   610  
   611  		// Build the wrapper function compiled by gcc.
   612  		s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
   613  		if fn.Recv != nil {
   614  			s += p.cgoType(fn.Recv.List[0].Type).C.String()
   615  			s += " recv"
   616  		}
   617  		forFieldList(fntype.Params,
   618  			func(i int, atype ast.Expr) {
   619  				if i > 0 || fn.Recv != nil {
   620  					s += ", "
   621  				}
   622  				s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
   623  			})
   624  		s += ")"
   625  		fmt.Fprintf(fgcch, "\nextern %s;\n", s)
   626  
   627  		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName)
   628  		fmt.Fprintf(fgcc, "\n%s\n", s)
   629  		fmt.Fprintf(fgcc, "{\n")
   630  		fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype)
   631  		if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
   632  			fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
   633  		}
   634  		if fn.Recv != nil {
   635  			fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
   636  		}
   637  		forFieldList(fntype.Params,
   638  			func(i int, atype ast.Expr) {
   639  				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
   640  			})
   641  		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
   642  		if gccResult != "void" {
   643  			if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
   644  				fmt.Fprintf(fgcc, "\treturn a.r0;\n")
   645  			} else {
   646  				forFieldList(fntype.Results,
   647  					func(i int, atype ast.Expr) {
   648  						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
   649  					})
   650  				fmt.Fprintf(fgcc, "\treturn r;\n")
   651  			}
   652  		}
   653  		fmt.Fprintf(fgcc, "}\n")
   654  
   655  		// Build the wrapper function compiled by 6c/8c
   656  		goname := exp.Func.Name.Name
   657  		if fn.Recv != nil {
   658  			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
   659  		}
   660  		fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
   661  		fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
   662  		fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
   663  		fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
   664  		fmt.Fprintf(fc, "void\n")
   665  		fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
   666  		fmt.Fprintf(fc, "{\n")
   667  		fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
   668  		fmt.Fprintf(fc, "}\n")
   669  
   670  		fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
   671  
   672  		// Calling a function with a receiver from C requires
   673  		// a Go wrapper function.
   674  		if fn.Recv != nil {
   675  			fmt.Fprintf(fgo2, "func %s(recv ", goname)
   676  			conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   677  			forFieldList(fntype.Params,
   678  				func(i int, atype ast.Expr) {
   679  					fmt.Fprintf(fgo2, ", p%d ", i)
   680  					conf.Fprint(fgo2, fset, atype)
   681  				})
   682  			fmt.Fprintf(fgo2, ")")
   683  			if gccResult != "void" {
   684  				fmt.Fprint(fgo2, " (")
   685  				forFieldList(fntype.Results,
   686  					func(i int, atype ast.Expr) {
   687  						if i > 0 {
   688  							fmt.Fprint(fgo2, ", ")
   689  						}
   690  						conf.Fprint(fgo2, fset, atype)
   691  					})
   692  				fmt.Fprint(fgo2, ")")
   693  			}
   694  			fmt.Fprint(fgo2, " {\n")
   695  			fmt.Fprint(fgo2, "\t")
   696  			if gccResult != "void" {
   697  				fmt.Fprint(fgo2, "return ")
   698  			}
   699  			fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
   700  			forFieldList(fntype.Params,
   701  				func(i int, atype ast.Expr) {
   702  					if i > 0 {
   703  						fmt.Fprint(fgo2, ", ")
   704  					}
   705  					fmt.Fprintf(fgo2, "p%d", i)
   706  				})
   707  			fmt.Fprint(fgo2, ")\n")
   708  			fmt.Fprint(fgo2, "}\n")
   709  		}
   710  	}
   711  }
   712  
   713  // Write out the C header allowing C code to call exported gccgo functions.
   714  func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
   715  	fgcc := creat(*objDir + "_cgo_export.c")
   716  	fgcch := creat(*objDir + "_cgo_export.h")
   717  
   718  	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
   719  
   720  	fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n")
   721  	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
   722  	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
   723  
   724  	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
   725  	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
   726  
   727  	fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n")
   728  
   729  	for _, exp := range p.ExpFunc {
   730  		fn := exp.Func
   731  		fntype := fn.Type
   732  
   733  		cdeclBuf := new(bytes.Buffer)
   734  		resultCount := 0
   735  		forFieldList(fntype.Results,
   736  			func(i int, atype ast.Expr) { resultCount++ })
   737  		switch resultCount {
   738  		case 0:
   739  			fmt.Fprintf(cdeclBuf, "void")
   740  		case 1:
   741  			forFieldList(fntype.Results,
   742  				func(i int, atype ast.Expr) {
   743  					t := p.cgoType(atype)
   744  					fmt.Fprintf(cdeclBuf, "%s", t.C)
   745  				})
   746  		default:
   747  			// Declare a result struct.
   748  			fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
   749  			forFieldList(fntype.Results,
   750  				func(i int, atype ast.Expr) {
   751  					t := p.cgoType(atype)
   752  					fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
   753  				})
   754  			fmt.Fprintf(fgcch, "};\n")
   755  			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
   756  		}
   757  
   758  		cRet := cdeclBuf.String()
   759  
   760  		cdeclBuf = new(bytes.Buffer)
   761  		fmt.Fprintf(cdeclBuf, "(")
   762  		if fn.Recv != nil {
   763  			fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
   764  		}
   765  		// Function parameters.
   766  		forFieldList(fntype.Params,
   767  			func(i int, atype ast.Expr) {
   768  				if i > 0 || fn.Recv != nil {
   769  					fmt.Fprintf(cdeclBuf, ", ")
   770  				}
   771  				t := p.cgoType(atype)
   772  				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
   773  			})
   774  		fmt.Fprintf(cdeclBuf, ")")
   775  		cParams := cdeclBuf.String()
   776  
   777  		goName := "Cgoexp_" + exp.ExpName
   778  		fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
   779  		fmt.Fprint(fgcch, "\n")
   780  
   781  		fmt.Fprint(fgcc, "\n")
   782  		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
   783  		fmt.Fprint(fgcc, "\t")
   784  		if resultCount > 0 {
   785  			fmt.Fprint(fgcc, "return ")
   786  		}
   787  		fmt.Fprintf(fgcc, "%s(", goName)
   788  		if fn.Recv != nil {
   789  			fmt.Fprint(fgcc, "recv")
   790  		}
   791  		forFieldList(fntype.Params,
   792  			func(i int, atype ast.Expr) {
   793  				if i > 0 || fn.Recv != nil {
   794  					fmt.Fprintf(fgcc, ", ")
   795  				}
   796  				fmt.Fprintf(fgcc, "p%d", i)
   797  			})
   798  		fmt.Fprint(fgcc, ");\n")
   799  		fmt.Fprint(fgcc, "}\n")
   800  
   801  		// Dummy declaration for _cgo_main.c
   802  		fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams)
   803  
   804  		// For gccgo we use a wrapper function in Go, in order
   805  		// to call CgocallBack and CgocallBackDone.
   806  
   807  		// This code uses printer.Fprint, not conf.Fprint,
   808  		// because we don't want //line comments in the middle
   809  		// of the function types.
   810  		fmt.Fprint(fgo2, "\n")
   811  		fmt.Fprintf(fgo2, "func %s(", goName)
   812  		if fn.Recv != nil {
   813  			fmt.Fprint(fgo2, "recv ")
   814  			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
   815  		}
   816  		forFieldList(fntype.Params,
   817  			func(i int, atype ast.Expr) {
   818  				if i > 0 || fn.Recv != nil {
   819  					fmt.Fprintf(fgo2, ", ")
   820  				}
   821  				fmt.Fprintf(fgo2, "p%d ", i)
   822  				printer.Fprint(fgo2, fset, atype)
   823  			})
   824  		fmt.Fprintf(fgo2, ")")
   825  		if resultCount > 0 {
   826  			fmt.Fprintf(fgo2, " (")
   827  			forFieldList(fntype.Results,
   828  				func(i int, atype ast.Expr) {
   829  					if i > 0 {
   830  						fmt.Fprint(fgo2, ", ")
   831  					}
   832  					printer.Fprint(fgo2, fset, atype)
   833  				})
   834  			fmt.Fprint(fgo2, ")")
   835  		}
   836  		fmt.Fprint(fgo2, " {\n")
   837  		fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
   838  		fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
   839  		fmt.Fprint(fgo2, "\t")
   840  		if resultCount > 0 {
   841  			fmt.Fprint(fgo2, "return ")
   842  		}
   843  		if fn.Recv != nil {
   844  			fmt.Fprint(fgo2, "recv.")
   845  		}
   846  		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
   847  		forFieldList(fntype.Params,
   848  			func(i int, atype ast.Expr) {
   849  				if i > 0 {
   850  					fmt.Fprint(fgo2, ", ")
   851  				}
   852  				fmt.Fprintf(fgo2, "p%d", i)
   853  			})
   854  		fmt.Fprint(fgo2, ")\n")
   855  		fmt.Fprint(fgo2, "}\n")
   856  	}
   857  }
   858  
   859  // Return the package prefix when using gccgo.
   860  func (p *Package) gccgoSymbolPrefix() string {
   861  	if !*gccgo {
   862  		return ""
   863  	}
   864  
   865  	clean := func(r rune) rune {
   866  		switch {
   867  		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
   868  			'0' <= r && r <= '9':
   869  			return r
   870  		}
   871  		return '_'
   872  	}
   873  
   874  	if *gccgopkgpath != "" {
   875  		return strings.Map(clean, *gccgopkgpath)
   876  	}
   877  	if *gccgoprefix == "" && p.PackageName == "main" {
   878  		return "main"
   879  	}
   880  	prefix := strings.Map(clean, *gccgoprefix)
   881  	if prefix == "" {
   882  		prefix = "go"
   883  	}
   884  	return prefix + "." + p.PackageName
   885  }
   886  
   887  // Call a function for each entry in an ast.FieldList, passing the
   888  // index into the list and the type.
   889  func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
   890  	if fl == nil {
   891  		return
   892  	}
   893  	i := 0
   894  	for _, r := range fl.List {
   895  		if r.Names == nil {
   896  			fn(i, r.Type)
   897  			i++
   898  		} else {
   899  			for _ = range r.Names {
   900  				fn(i, r.Type)
   901  				i++
   902  			}
   903  		}
   904  	}
   905  }
   906  
   907  func c(repr string, args ...interface{}) *TypeRepr {
   908  	return &TypeRepr{repr, args}
   909  }
   910  
   911  // Map predeclared Go types to Type.
   912  var goTypes = map[string]*Type{
   913  	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
   914  	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
   915  	"int":        {Size: 0, Align: 0, C: c("GoInt")},
   916  	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
   917  	"rune":       {Size: 4, Align: 4, C: c("GoInt32")},
   918  	"int8":       {Size: 1, Align: 1, C: c("GoInt8")},
   919  	"uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
   920  	"int16":      {Size: 2, Align: 2, C: c("GoInt16")},
   921  	"uint16":     {Size: 2, Align: 2, C: c("GoUint16")},
   922  	"int32":      {Size: 4, Align: 4, C: c("GoInt32")},
   923  	"uint32":     {Size: 4, Align: 4, C: c("GoUint32")},
   924  	"int64":      {Size: 8, Align: 8, C: c("GoInt64")},
   925  	"uint64":     {Size: 8, Align: 8, C: c("GoUint64")},
   926  	"float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
   927  	"float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
   928  	"complex64":  {Size: 8, Align: 8, C: c("GoComplex64")},
   929  	"complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
   930  }
   931  
   932  // Map an ast type to a Type.
   933  func (p *Package) cgoType(e ast.Expr) *Type {
   934  	switch t := e.(type) {
   935  	case *ast.StarExpr:
   936  		x := p.cgoType(t.X)
   937  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
   938  	case *ast.ArrayType:
   939  		if t.Len == nil {
   940  			return &Type{Size: p.PtrSize + 8, Align: p.PtrSize, C: c("GoSlice")}
   941  		}
   942  	case *ast.StructType:
   943  		// TODO
   944  	case *ast.FuncType:
   945  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
   946  	case *ast.InterfaceType:
   947  		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
   948  	case *ast.MapType:
   949  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
   950  	case *ast.ChanType:
   951  		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
   952  	case *ast.Ident:
   953  		// Look up the type in the top level declarations.
   954  		// TODO: Handle types defined within a function.
   955  		for _, d := range p.Decl {
   956  			gd, ok := d.(*ast.GenDecl)
   957  			if !ok || gd.Tok != token.TYPE {
   958  				continue
   959  			}
   960  			for _, spec := range gd.Specs {
   961  				ts, ok := spec.(*ast.TypeSpec)
   962  				if !ok {
   963  					continue
   964  				}
   965  				if ts.Name.Name == t.Name {
   966  					return p.cgoType(ts.Type)
   967  				}
   968  			}
   969  		}
   970  		if def := typedef[t.Name]; def != nil {
   971  			return def
   972  		}
   973  		if t.Name == "uintptr" {
   974  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
   975  		}
   976  		if t.Name == "string" {
   977  			// The string data is 1 pointer + 1 int, but this always
   978  			// rounds to 2 pointers due to alignment.
   979  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
   980  		}
   981  		if t.Name == "error" {
   982  			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
   983  		}
   984  		if r, ok := goTypes[t.Name]; ok {
   985  			if r.Size == 0 { // int or uint
   986  				rr := new(Type)
   987  				*rr = *r
   988  				rr.Size = p.IntSize
   989  				rr.Align = p.IntSize
   990  				r = rr
   991  			}
   992  			if r.Align > p.PtrSize {
   993  				r.Align = p.PtrSize
   994  			}
   995  			return r
   996  		}
   997  		error_(e.Pos(), "unrecognized Go type %s", t.Name)
   998  		return &Type{Size: 4, Align: 4, C: c("int")}
   999  	case *ast.SelectorExpr:
  1000  		id, ok := t.X.(*ast.Ident)
  1001  		if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
  1002  			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
  1003  		}
  1004  	}
  1005  	error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
  1006  	return &Type{Size: 4, Align: 4, C: c("int")}
  1007  }
  1008  
  1009  const gccProlog = `
  1010  // Usual nonsense: if x and y are not equal, the type will be invalid
  1011  // (have a negative array count) and an inscrutable error will come
  1012  // out of the compiler and hopefully mention "name".
  1013  #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
  1014  
  1015  // Check at compile time that the sizes we use match our expectations.
  1016  #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
  1017  
  1018  __cgo_size_assert(char, 1)
  1019  __cgo_size_assert(short, 2)
  1020  __cgo_size_assert(int, 4)
  1021  typedef long long __cgo_long_long;
  1022  __cgo_size_assert(__cgo_long_long, 8)
  1023  __cgo_size_assert(float, 4)
  1024  __cgo_size_assert(double, 8)
  1025  
  1026  #include <errno.h>
  1027  #include <string.h>
  1028  `
  1029  
  1030  const builtinProlog = `
  1031  typedef struct { char *p; int n; } _GoString_;
  1032  typedef struct { char *p; int n; int c; } _GoBytes_;
  1033  _GoString_ GoString(char *p);
  1034  _GoString_ GoStringN(char *p, int l);
  1035  _GoBytes_ GoBytes(void *p, int n);
  1036  char *CString(_GoString_);
  1037  `
  1038  
  1039  const cProlog = `
  1040  #include "runtime.h"
  1041  #include "cgocall.h"
  1042  
  1043  void ·_Cerrno(void*, int32);
  1044  
  1045  void
  1046  ·_Cfunc_GoString(int8 *p, String s)
  1047  {
  1048  	s = runtime·gostring((byte*)p);
  1049  	FLUSH(&s);
  1050  }
  1051  
  1052  void
  1053  ·_Cfunc_GoStringN(int8 *p, int32 l, String s)
  1054  {
  1055  	s = runtime·gostringn((byte*)p, l);
  1056  	FLUSH(&s);
  1057  }
  1058  
  1059  void
  1060  ·_Cfunc_GoBytes(int8 *p, int32 l, Slice s)
  1061  {
  1062  	s = runtime·gobytes((byte*)p, l);
  1063  	FLUSH(&s);
  1064  }
  1065  
  1066  void
  1067  ·_Cfunc_CString(String s, int8 *p)
  1068  {
  1069  	p = runtime·cmalloc(s.len+1);
  1070  	runtime·memmove((byte*)p, s.str, s.len);
  1071  	p[s.len] = 0;
  1072  	FLUSH(&p);
  1073  }
  1074  `
  1075  
  1076  const cPrologGccgo = `
  1077  #include <stdint.h>
  1078  #include <string.h>
  1079  
  1080  typedef unsigned char byte;
  1081  typedef intptr_t intgo;
  1082  
  1083  struct __go_string {
  1084  	const unsigned char *__data;
  1085  	intgo __length;
  1086  };
  1087  
  1088  typedef struct __go_open_array {
  1089  	void* __values;
  1090  	intgo __count;
  1091  	intgo __capacity;
  1092  } Slice;
  1093  
  1094  struct __go_string __go_byte_array_to_string(const void* p, intgo len);
  1095  struct __go_open_array __go_string_to_byte_array (struct __go_string str);
  1096  
  1097  const char *CString(struct __go_string s) {
  1098  	return strndup((const char*)s.__data, s.__length);
  1099  }
  1100  
  1101  struct __go_string GoString(char *p) {
  1102  	intgo len = (p != NULL) ? strlen(p) : 0;
  1103  	return __go_byte_array_to_string(p, len);
  1104  }
  1105  
  1106  struct __go_string GoStringN(char *p, intgo n) {
  1107  	return __go_byte_array_to_string(p, n);
  1108  }
  1109  
  1110  Slice GoBytes(char *p, intgo n) {
  1111  	struct __go_string s = { (const unsigned char *)p, n };
  1112  	return __go_string_to_byte_array(s);
  1113  }
  1114  `
  1115  
  1116  func (p *Package) gccExportHeaderProlog() string {
  1117  	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
  1118  }
  1119  
  1120  const gccExportHeaderProlog = `
  1121  typedef signed char GoInt8;
  1122  typedef unsigned char GoUint8;
  1123  typedef short GoInt16;
  1124  typedef unsigned short GoUint16;
  1125  typedef int GoInt32;
  1126  typedef unsigned int GoUint32;
  1127  typedef long long GoInt64;
  1128  typedef unsigned long long GoUint64;
  1129  typedef GoIntGOINTBITS GoInt;
  1130  typedef GoUintGOINTBITS GoUint;
  1131  typedef __SIZE_TYPE__ GoUintptr;
  1132  typedef float GoFloat32;
  1133  typedef double GoFloat64;
  1134  typedef __complex float GoComplex64;
  1135  typedef __complex double GoComplex128;
  1136  
  1137  typedef struct { char *p; int n; } GoString;
  1138  typedef void *GoMap;
  1139  typedef void *GoChan;
  1140  typedef struct { void *t; void *v; } GoInterface;
  1141  typedef struct { void *data; int len; int cap; } GoSlice;
  1142  `