out.go 57 KB
Newer Older
1
// Copyright 2009 The Go Authors. All rights reserved.
Russ Cox's avatar
Russ Cox committed
2 3 4 5 6 7
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
Russ Cox's avatar
Russ Cox committed
8
	"bytes"
Russ Cox's avatar
Russ Cox committed
9 10
	"debug/elf"
	"debug/macho"
Wei Guangjing's avatar
Wei Guangjing committed
11
	"debug/pe"
12 13 14
	"fmt"
	"go/ast"
	"go/printer"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
15
	"go/token"
16
	"internal/xcoff"
17
	"io"
18
	"io/ioutil"
19
	"os"
20
	"os/exec"
21
	"path/filepath"
22
	"regexp"
23
	"sort"
24
	"strings"
Russ Cox's avatar
Russ Cox committed
25 26
)

27 28 29 30
var (
	conf         = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
	noSourceConf = printer.Config{Tabwidth: 8}
)
31

32
// writeDefs creates output files to be compiled by gc and gcc.
Russ Cox's avatar
Russ Cox committed
33
func (p *Package) writeDefs() {
34 35 36 37 38 39 40 41 42
	var fgo2, fc io.Writer
	f := creat(*objDir + "_cgo_gotypes.go")
	defer f.Close()
	fgo2 = f
	if *gccgo {
		f := creat(*objDir + "_cgo_defun.c")
		defer f.Close()
		fc = f
	}
Russ Cox's avatar
Russ Cox committed
43
	fm := creat(*objDir + "_cgo_main.c")
44

45 46
	var gccgoInit bytes.Buffer

Russ Cox's avatar
Russ Cox committed
47
	fflg := creat(*objDir + "_cgo_flags")
48
	for k, v := range p.CgoFlags {
49
		fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
50
		if k == "LDFLAGS" && !*gccgo {
51
			for _, arg := range v {
52
				fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
53 54
			}
		}
55 56 57
	}
	fflg.Close()

58 59
	// Write C main file for using gcc to resolve imports.
	fmt.Fprintf(fm, "int main() { return 0; }\n")
Russ Cox's avatar
Russ Cox committed
60
	if *importRuntimeCgo {
61
		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
62
		fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void) { return 0; }\n")
63
		fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n")
64
		fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
Russ Cox's avatar
Russ Cox committed
65 66
	} else {
		// If we're not importing runtime/cgo, we *are* runtime/cgo,
67
		// which provides these functions. We just need a prototype.
68
		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n")
69
		fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
70
		fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
Russ Cox's avatar
Russ Cox committed
71
	}
72 73
	fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
	fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
74
	fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
Russ Cox's avatar
Russ Cox committed
75 76 77 78

	// Write second Go output: definitions of _C_xxx.
	// In a separate file so that the import of "unsafe" does not
	// pollute the original file.
79
	fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
Russ Cox's avatar
Russ Cox committed
80
	fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
81
	fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
Russ Cox's avatar
Russ Cox committed
82
	if !*gccgo && *importRuntimeCgo {
83 84
		fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
	}
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
85
	if *importSyscall {
86 87
		fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
		fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
Dmitriy Vyukov's avatar
Dmitriy Vyukov committed
88
	}
89
	fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
Russ Cox's avatar
Russ Cox committed
90

91 92 93 94 95 96 97
	if !*gccgo {
		fmt.Fprintf(fgo2, "//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse\n")
		fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n")
		fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n")
		fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n")
	}

98 99 100 101 102 103 104
	typedefNames := make([]string, 0, len(typedef))
	for name := range typedef {
		typedefNames = append(typedefNames, name)
	}
	sort.Strings(typedefNames)
	for _, name := range typedefNames {
		def := typedef[name]
105
		fmt.Fprintf(fgo2, "type %s ", name)
106 107 108 109 110 111 112 113 114 115 116 117
		// We don't have source info for these types, so write them out without source info.
		// Otherwise types would look like:
		//
		// type _Ctype_struct_cb struct {
		// //line :1
		//        on_test *[0]byte
		// //line :1
		// }
		//
		// Which is not useful. Moreover we never override source info,
		// so subsequent source code uses the same source info.
		// Moreover, empty file name makes compile emit no source debug info at all.
118 119 120 121 122 123 124
		var buf bytes.Buffer
		noSourceConf.Fprint(&buf, fset, def.Go)
		if bytes.HasPrefix(buf.Bytes(), []byte("_Ctype_")) {
			// This typedef is of the form `typedef a b` and should be an alias.
			fmt.Fprintf(fgo2, "= ")
		}
		fmt.Fprintf(fgo2, "%s", buf.Bytes())
125
		fmt.Fprintf(fgo2, "\n\n")
Russ Cox's avatar
Russ Cox committed
126
	}
127 128 129 130 131
	if *gccgo {
		fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
	} else {
		fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n")
	}
Russ Cox's avatar
Russ Cox committed
132

133
	if *gccgo {
134
		fmt.Fprint(fgo2, gccgoGoProlog)
135
		fmt.Fprint(fc, p.cPrologGccgo())
136
	} else {
137
		fmt.Fprint(fgo2, goProlog)
138
	}
Russ Cox's avatar
Russ Cox committed
139

140 141 142 143 144 145 146
	if fc != nil {
		fmt.Fprintf(fc, "#line 1 \"cgo-generated-wrappers\"\n")
	}
	if fm != nil {
		fmt.Fprintf(fm, "#line 1 \"cgo-generated-wrappers\"\n")
	}

147 148
	gccgoSymbolPrefix := p.gccgoSymbolPrefix()

149
	cVars := make(map[string]bool)
150 151
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
152
		if !n.IsVar() {
Russ Cox's avatar
Russ Cox committed
153 154
			continue
		}
Russ Cox's avatar
Russ Cox committed
155

156
		if !cVars[n.C] {
157 158 159
			if *gccgo {
				fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
			} else {
160 161
				fmt.Fprintf(fm, "extern char %s[];\n", n.C)
				fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
162 163 164
				fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
				fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
				fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
165
			}
166 167
			cVars[n.C] = true
		}
168

169 170 171 172 173 174 175 176
		var node ast.Node
		if n.Kind == "var" {
			node = &ast.StarExpr{X: n.Type.Go}
		} else if n.Kind == "fpvar" {
			node = n.Type.Go
		} else {
			panic(fmt.Errorf("invalid var kind %q", n.Kind))
		}
177 178
		if *gccgo {
			fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
179 180
			fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
			fmt.Fprintf(fc, "\n")
181
		}
Russ Cox's avatar
Russ Cox committed
182

Russ Cox's avatar
Russ Cox committed
183
		fmt.Fprintf(fgo2, "var %s ", n.Mangle)
184
		conf.Fprint(fgo2, fset, node)
185 186 187 188 189
		if !*gccgo {
			fmt.Fprintf(fgo2, " = (")
			conf.Fprint(fgo2, fset, node)
			fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
		}
190
		fmt.Fprintf(fgo2, "\n")
Russ Cox's avatar
Russ Cox committed
191
	}
192 193 194
	if *gccgo {
		fmt.Fprintf(fc, "\n")
	}
Russ Cox's avatar
Russ Cox committed
195

196 197
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
Russ Cox's avatar
Russ Cox committed
198
		if n.Const != "" {
199
			fmt.Fprintf(fgo2, "const %s = %s\n", n.Mangle, n.Const)
Russ Cox's avatar
Russ Cox committed
200
		}
201 202 203
	}
	fmt.Fprintf(fgo2, "\n")

204
	callsMalloc := false
205 206
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
Russ Cox's avatar
Russ Cox committed
207
		if n.FuncType != nil {
208
			p.writeDefsFunc(fgo2, n, &callsMalloc)
209
		}
Russ Cox's avatar
Russ Cox committed
210
	}
Russ Cox's avatar
Russ Cox committed
211

212 213
	fgcc := creat(*objDir + "_cgo_export.c")
	fgcch := creat(*objDir + "_cgo_export.h")
214
	if *gccgo {
215
		p.writeGccgoExports(fgo2, fm, fgcc, fgcch)
216
	} else {
217 218
		p.writeExports(fgo2, fm, fgcc, fgcch)
	}
219 220 221 222 223 224

	if callsMalloc && !*gccgo {
		fmt.Fprint(fgo2, strings.Replace(cMallocDefGo, "PREFIX", cPrefix, -1))
		fmt.Fprint(fgcc, strings.Replace(strings.Replace(cMallocDefC, "PREFIX", cPrefix, -1), "PACKED", p.packedAttribute(), -1))
	}

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
	if err := fgcc.Close(); err != nil {
		fatalf("%s", err)
	}
	if err := fgcch.Close(); err != nil {
		fatalf("%s", err)
	}

	if *exportHeader != "" && len(p.ExpFunc) > 0 {
		fexp := creat(*exportHeader)
		fgcch, err := os.Open(*objDir + "_cgo_export.h")
		if err != nil {
			fatalf("%s", err)
		}
		_, err = io.Copy(fexp, fgcch)
		if err != nil {
			fatalf("%s", err)
		}
		if err = fexp.Close(); err != nil {
			fatalf("%s", err)
		}
245
	}
Russ Cox's avatar
Russ Cox committed
246

247 248
	init := gccgoInit.String()
	if init != "" {
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
		// The init function does nothing but simple
		// assignments, so it won't use much stack space, so
		// it's OK to not split the stack. Splitting the stack
		// can run into a bug in clang (as of 2018-11-09):
		// this is a leaf function, and when clang sees a leaf
		// function it won't emit the split stack prologue for
		// the function. However, if this function refers to a
		// non-split-stack function, which will happen if the
		// cgo code refers to a C function not compiled with
		// -fsplit-stack, then the linker will think that it
		// needs to adjust the split stack prologue, but there
		// won't be one. Marking the function explicitly
		// no_split_stack works around this problem by telling
		// the linker that it's OK if there is no split stack
		// prologue.
		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor, no_split_stack));")
265 266 267 268
		fmt.Fprintln(fc, "static void init(void) {")
		fmt.Fprint(fc, init)
		fmt.Fprintln(fc, "}")
	}
Russ Cox's avatar
Russ Cox committed
269 270
}

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
// elfImportedSymbols is like elf.File.ImportedSymbols, but it
// includes weak symbols.
//
// A bug in some versions of LLD (at least LLD 8) cause it to emit
// several pthreads symbols as weak, but we need to import those. See
// issue #31912 or https://bugs.llvm.org/show_bug.cgi?id=42442.
//
// When doing external linking, we hand everything off to the external
// linker, which will create its own dynamic symbol tables. For
// internal linking, this may turn weak imports into strong imports,
// which could cause dynamic linking to fail if a symbol really isn't
// defined. However, the standard library depends on everything it
// imports, and this is the primary use of dynamic symbol tables with
// internal linking.
func elfImportedSymbols(f *elf.File) []elf.ImportedSymbol {
	syms, _ := f.DynamicSymbols()
	var imports []elf.ImportedSymbol
	for _, s := range syms {
		if (elf.ST_BIND(s.Info) == elf.STB_GLOBAL || elf.ST_BIND(s.Info) == elf.STB_WEAK) && s.Section == elf.SHN_UNDEF {
			imports = append(imports, elf.ImportedSymbol{
				Name:    s.Name,
				Library: s.Library,
				Version: s.Version,
			})
		}
	}
	return imports
}

Russ Cox's avatar
Russ Cox committed
300
func dynimport(obj string) {
Russ Cox's avatar
Russ Cox committed
301 302 303 304 305 306 307 308 309
	stdout := os.Stdout
	if *dynout != "" {
		f, err := os.Create(*dynout)
		if err != nil {
			fatalf("%s", err)
		}
		stdout = f
	}

310 311
	fmt.Fprintf(stdout, "package %s\n", *dynpackage)

Russ Cox's avatar
Russ Cox committed
312
	if f, err := elf.Open(obj); err == nil {
313 314
		if *dynlinker {
			// Emit the cgo_dynamic_linker line.
315 316 317
			if sec := f.Section(".interp"); sec != nil {
				if data, err := sec.Data(); err == nil && len(data) > 1 {
					// skip trailing \0 in data
318
					fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
319
				}
320 321
			}
		}
322
		sym := elfImportedSymbols(f)
Russ Cox's avatar
Russ Cox committed
323 324 325
		for _, s := range sym {
			targ := s.Name
			if s.Version != "" {
326
				targ += "#" + s.Version
Wei Guangjing's avatar
Wei Guangjing committed
327
			}
328
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
Russ Cox's avatar
Russ Cox committed
329
		}
330
		lib, _ := f.ImportedLibraries()
Russ Cox's avatar
Russ Cox committed
331
		for _, l := range lib {
332
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
Russ Cox's avatar
Russ Cox committed
333 334
		}
		return
Russ Cox's avatar
Russ Cox committed
335 336
	}

Russ Cox's avatar
Russ Cox committed
337
	if f, err := macho.Open(obj); err == nil {
338
		sym, _ := f.ImportedSymbols()
Russ Cox's avatar
Russ Cox committed
339 340 341
		for _, s := range sym {
			if len(s) > 0 && s[0] == '_' {
				s = s[1:]
Russ Cox's avatar
Russ Cox committed
342
			}
343
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
Russ Cox's avatar
Russ Cox committed
344
		}
345
		lib, _ := f.ImportedLibraries()
Russ Cox's avatar
Russ Cox committed
346
		for _, l := range lib {
347
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
Russ Cox's avatar
Russ Cox committed
348
		}
Russ Cox's avatar
Russ Cox committed
349
		return
Russ Cox's avatar
Russ Cox committed
350 351
	}

Russ Cox's avatar
Russ Cox committed
352
	if f, err := pe.Open(obj); err == nil {
353
		sym, _ := f.ImportedSymbols()
Russ Cox's avatar
Russ Cox committed
354
		for _, s := range sym {
355
			ss := strings.Split(s, ":")
356
			name := strings.Split(ss[0], "@")[0]
357
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
Russ Cox's avatar
Russ Cox committed
358 359
		}
		return
Russ Cox's avatar
Russ Cox committed
360 361
	}

362 363 364 365 366 367
	if f, err := xcoff.Open(obj); err == nil {
		sym, err := f.ImportedSymbols()
		if err != nil {
			fatalf("cannot load imported symbols from XCOFF file %s: %v", obj, err)
		}
		for _, s := range sym {
368 369 370 371 372 373
			if s.Name == "runtime_rt0_go" || s.Name == "_rt0_ppc64_aix_lib" {
				// These symbols are imported by runtime/cgo but
				// must not be added to _cgo_import.go as there are
				// Go symbols.
				continue
			}
374 375 376 377 378 379 380 381 382 383 384 385 386
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library)
		}
		lib, err := f.ImportedLibraries()
		if err != nil {
			fatalf("cannot load imported libraries from XCOFF file %s: %v", obj, err)
		}
		for _, l := range lib {
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
		}
		return
	}

	fatalf("cannot parse %s as ELF, Mach-O, PE or XCOFF", obj)
Russ Cox's avatar
Russ Cox committed
387 388
}

389
// Construct a gcc struct matching the gc argument frame.
Russ Cox's avatar
Russ Cox committed
390 391
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
// These assumptions are checked by the gccProlog.
392
// Also assumes that gc convention is to word-align the
Russ Cox's avatar
Russ Cox committed
393 394 395 396 397 398 399 400 401
// input and output parameters.
func (p *Package) structType(n *Name) (string, int64) {
	var buf bytes.Buffer
	fmt.Fprint(&buf, "struct {\n")
	off := int64(0)
	for i, t := range n.FuncType.Params {
		if off%t.Align != 0 {
			pad := t.Align - off%t.Align
			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
402
			off += pad
Russ Cox's avatar
Russ Cox committed
403
		}
Russ Cox's avatar
Russ Cox committed
404 405 406 407 408
		c := t.Typedef
		if c == "" {
			c = t.C.String()
		}
		fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
Russ Cox's avatar
Russ Cox committed
409 410 411 412 413 414 415 416 417 418 419
		off += t.Size
	}
	if off%p.PtrSize != 0 {
		pad := p.PtrSize - off%p.PtrSize
		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
		off += pad
	}
	if t := n.FuncType.Result; t != nil {
		if off%t.Align != 0 {
			pad := t.Align - off%t.Align
			fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
420
			off += pad
Russ Cox's avatar
Russ Cox committed
421
		}
422
		fmt.Fprintf(&buf, "\t\t%s r;\n", t.C)
Russ Cox's avatar
Russ Cox committed
423 424 425 426 427 428 429 430 431 432
		off += t.Size
	}
	if off%p.PtrSize != 0 {
		pad := p.PtrSize - off%p.PtrSize
		fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
		off += pad
	}
	if off == 0 {
		fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
	}
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
433
	fmt.Fprintf(&buf, "\t}")
Russ Cox's avatar
Russ Cox committed
434 435 436
	return buf.String(), off
}

437
func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name, callsMalloc *bool) {
Russ Cox's avatar
Russ Cox committed
438 439
	name := n.Go
	gtype := n.FuncType.Go
440
	void := gtype.Results == nil || len(gtype.Results.List) == 0
Russ Cox's avatar
Russ Cox committed
441
	if n.AddError {
442
		// Add "error" to return type list.
Russ Cox's avatar
Russ Cox committed
443
		// Type list is known to be 0 or 1 element - it's a C function.
444
		err := &ast.Field{Type: ast.NewIdent("error")}
Russ Cox's avatar
Russ Cox committed
445 446 447 448 449
		l := gtype.Results.List
		if len(l) == 0 {
			l = []*ast.Field{err}
		} else {
			l = []*ast.Field{l[0], err}
Russ Cox's avatar
Russ Cox committed
450
		}
Russ Cox's avatar
Russ Cox committed
451 452 453 454
		t := new(ast.FuncType)
		*t = *gtype
		t.Results = &ast.FieldList{List: l}
		gtype = t
455 456
	}

Russ Cox's avatar
Russ Cox committed
457 458 459 460 461
	// Go func declaration.
	d := &ast.FuncDecl{
		Name: ast.NewIdent(n.Mangle),
		Type: gtype,
	}
462

Ian Lance Taylor's avatar
Ian Lance Taylor committed
463
	// Builtins defined in the C prolog.
464 465 466
	inProlog := builtinDefs[name] != ""
	cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
	paramnames := []string(nil)
467 468 469 470 471 472
	if d.Type.Params != nil {
		for i, param := range d.Type.Params.List {
			paramName := fmt.Sprintf("p%d", i)
			param.Names = []*ast.Ident{ast.NewIdent(paramName)}
			paramnames = append(paramnames, paramName)
		}
473
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
474

475
	if *gccgo {
476
		// Gccgo style hooks.
477 478 479
		fmt.Fprint(fgo2, "\n")
		conf.Fprint(fgo2, fset, d)
		fmt.Fprint(fgo2, " {\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
480 481 482 483
		if !inProlog {
			fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
			fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
		}
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
		if n.AddError {
			fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
		}
		fmt.Fprint(fgo2, "\t")
		if !void {
			fmt.Fprint(fgo2, "r := ")
		}
		fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))

		if n.AddError {
			fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n")
			fmt.Fprint(fgo2, "\tif e != 0 {\n")
			fmt.Fprint(fgo2, "\t\treturn ")
			if !void {
				fmt.Fprint(fgo2, "r, ")
			}
			fmt.Fprint(fgo2, "e\n")
			fmt.Fprint(fgo2, "\t}\n")
			fmt.Fprint(fgo2, "\treturn ")
			if !void {
				fmt.Fprint(fgo2, "r, ")
505
			}
506 507 508 509 510 511 512 513
			fmt.Fprint(fgo2, "nil\n")
		} else if !void {
			fmt.Fprint(fgo2, "\treturn r\n")
		}

		fmt.Fprint(fgo2, "}\n")

		// declare the C function.
514
		fmt.Fprintf(fgo2, "//extern %s\n", cname)
515 516
		d.Name = ast.NewIdent(cname)
		if n.AddError {
517 518 519
			l := d.Type.Results.List
			d.Type.Results.List = l[:len(l)-1]
		}
520 521 522
		conf.Fprint(fgo2, fset, d)
		fmt.Fprint(fgo2, "\n")

523
		return
524
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
525

Ian Lance Taylor's avatar
Ian Lance Taylor committed
526
	if inProlog {
527
		fmt.Fprint(fgo2, builtinDefs[name])
528 529 530
		if strings.Contains(builtinDefs[name], "_cgo_cmalloc") {
			*callsMalloc = true
		}
Russ Cox's avatar
Russ Cox committed
531 532 533
		return
	}

534
	// Wrapper calls into gcc, passing a pointer to the argument frame.
535 536 537 538
	fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
	fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
	fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
	fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
539 540 541 542 543

	nret := 0
	if !void {
		d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")}
		nret = 1
544
	}
545 546
	if n.AddError {
		d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")}
547
	}
548 549

	fmt.Fprint(fgo2, "\n")
550
	fmt.Fprint(fgo2, "//go:cgo_unsafe_args\n")
551 552 553 554 555 556 557 558 559
	conf.Fprint(fgo2, fset, d)
	fmt.Fprint(fgo2, " {\n")

	// NOTE: Using uintptr to hide from escape analysis.
	arg := "0"
	if len(paramnames) > 0 {
		arg = "uintptr(unsafe.Pointer(&p0))"
	} else if !void {
		arg = "uintptr(unsafe.Pointer(&r1))"
560
	}
561 562

	prefix := ""
Russ Cox's avatar
Russ Cox committed
563
	if n.AddError {
564
		prefix = "errno := "
Russ Cox's avatar
Russ Cox committed
565
	}
566
	fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg)
567 568 569
	if n.AddError {
		fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
	}
570
	fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
571 572 573 574
	if d.Type.Params != nil {
		for i := range d.Type.Params.List {
			fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
		}
575 576
	}
	fmt.Fprintf(fgo2, "\t}\n")
577 578
	fmt.Fprintf(fgo2, "\treturn\n")
	fmt.Fprintf(fgo2, "}\n")
579 580
}

581
// writeOutput creates stubs for a specific source file to be compiled by gc
Russ Cox's avatar
Russ Cox committed
582
func (p *Package) writeOutput(f *File, srcfile string) {
583 584 585 586
	base := srcfile
	if strings.HasSuffix(base, ".go") {
		base = base[0 : len(base)-3]
	}
587
	base = filepath.Base(base)
Russ Cox's avatar
Russ Cox committed
588 589
	fgo1 := creat(*objDir + base + ".cgo1.go")
	fgcc := creat(*objDir + base + ".cgo2.c")
590

Russ Cox's avatar
Russ Cox committed
591 592 593
	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
	p.GccFiles = append(p.GccFiles, base+".cgo2.c")

594
	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
595
	fmt.Fprintf(fgo1, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
596
	fmt.Fprintf(fgo1, "//line %s:1:1\n", srcfile)
597
	fgo1.Write(f.Edit.Bytes())
598

599
	// While we process the vars and funcs, also write gcc output.
600
	// Gcc output starts with the preamble.
601
	fmt.Fprintf(fgcc, "%s\n", builtinProlog)
Russ Cox's avatar
Russ Cox committed
602
	fmt.Fprintf(fgcc, "%s\n", f.Preamble)
603
	fmt.Fprintf(fgcc, "%s\n", gccProlog)
604
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
605
	fmt.Fprintf(fgcc, "%s\n", msanProlog)
606

607 608
	for _, key := range nameKeys(f.Name) {
		n := f.Name[key]
Russ Cox's avatar
Russ Cox committed
609 610
		if n.FuncType != nil {
			p.writeOutputFunc(fgcc, n)
Russ Cox's avatar
Russ Cox committed
611 612
		}
	}
Russ Cox's avatar
Russ Cox committed
613

614 615
	fgo1.Close()
	fgcc.Close()
Russ Cox's avatar
Russ Cox committed
616 617
}

Robert Hencke's avatar
Robert Hencke committed
618
// fixGo converts the internal Name.Go field into the name we should show
619 620 621 622 623 624 625 626 627 628 629
// to users in error messages. There's only one for now: on input we rewrite
// C.malloc into C._CMalloc, so change it back here.
func fixGo(name string) string {
	if name == "_CMalloc" {
		return "malloc"
	}
	return name
}

var isBuiltin = map[string]bool{
	"_Cfunc_CString":   true,
James Bardin's avatar
James Bardin committed
630
	"_Cfunc_CBytes":    true,
631 632 633 634 635 636
	"_Cfunc_GoString":  true,
	"_Cfunc_GoStringN": true,
	"_Cfunc_GoBytes":   true,
	"_Cfunc__CMalloc":  true,
}

Russ Cox's avatar
Russ Cox committed
637 638
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
	name := n.Mangle
639
	if isBuiltin[name] || p.Written[name] {
Russ Cox's avatar
Russ Cox committed
640 641 642 643 644 645
		// The builtins are already defined in the C prolog, and we don't
		// want to duplicate function definitions we've already done.
		return
	}
	p.Written[name] = true

646
	if *gccgo {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
647
		p.writeGccgoOutputFunc(fgcc, n)
648 649 650
		return
	}

Shenghou Ma's avatar
Shenghou Ma committed
651
	ctype, _ := p.structType(n)
Russ Cox's avatar
Russ Cox committed
652 653 654

	// Gcc wrapper unpacks the C argument struct
	// and calls the actual C function.
655
	fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
656 657 658 659 660
	if n.AddError {
		fmt.Fprintf(fgcc, "int\n")
	} else {
		fmt.Fprintf(fgcc, "void\n")
	}
661
	fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
Russ Cox's avatar
Russ Cox committed
662 663
	fmt.Fprintf(fgcc, "{\n")
	if n.AddError {
664
		fmt.Fprintf(fgcc, "\tint _cgo_errno;\n")
Russ Cox's avatar
Russ Cox committed
665
	}
666
	// We're trying to write a gcc struct that matches gc's layout.
667
	// Use packed attribute to force no padding in this struct in case
668
	// gcc has different packing requirements.
669
	fmt.Fprintf(fgcc, "\t%s %v *_cgo_a = v;\n", ctype, p.packedAttribute())
670 671
	if n.FuncType.Result != nil {
		// Save the stack top for use below.
672
		fmt.Fprintf(fgcc, "\tchar *_cgo_stktop = _cgo_topofstack();\n")
673
	}
674 675
	tr := n.FuncType.Result
	if tr != nil {
676
		fmt.Fprintf(fgcc, "\t__typeof__(_cgo_a->r) _cgo_r;\n")
677
	}
678
	fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
679 680 681
	if n.AddError {
		fmt.Fprintf(fgcc, "\terrno = 0;\n")
	}
Russ Cox's avatar
Russ Cox committed
682
	fmt.Fprintf(fgcc, "\t")
683
	if tr != nil {
684
		fmt.Fprintf(fgcc, "_cgo_r = ")
685
		if c := tr.C.String(); c[len(c)-1] == '*' {
686
			fmt.Fprint(fgcc, "(__typeof__(_cgo_a->r)) ")
687
		}
Russ Cox's avatar
Russ Cox committed
688
	}
689 690 691 692 693 694 695 696
	if n.Kind == "macro" {
		fmt.Fprintf(fgcc, "%s;\n", n.C)
	} else {
		fmt.Fprintf(fgcc, "%s(", n.C)
		for i := range n.FuncType.Params {
			if i > 0 {
				fmt.Fprintf(fgcc, ", ")
			}
697
			fmt.Fprintf(fgcc, "_cgo_a->p%d", i)
Russ Cox's avatar
Russ Cox committed
698
		}
699
		fmt.Fprintf(fgcc, ");\n")
Russ Cox's avatar
Russ Cox committed
700
	}
701 702 703
	if n.AddError {
		fmt.Fprintf(fgcc, "\t_cgo_errno = errno;\n")
	}
704
	fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
705 706 707
	if n.FuncType.Result != nil {
		// The cgo call may have caused a stack copy (via a callback).
		// Adjust the return value pointer appropriately.
708
		fmt.Fprintf(fgcc, "\t_cgo_a = (void*)((char*)_cgo_a + (_cgo_topofstack() - _cgo_stktop));\n")
709
		// Save the return value.
710
		fmt.Fprintf(fgcc, "\t_cgo_a->r = _cgo_r;\n")
711 712 713 714 715 716 717 718 719 720
		// The return value is on the Go stack. If we are using msan,
		// and if the C value is partially or completely uninitialized,
		// the assignment will mark the Go stack as uninitialized.
		// The Go compiler does not update msan for changes to the
		// stack. It is possible that the stack will remain
		// uninitialized, and then later be used in a way that is
		// visible to msan, possibly leading to a false positive.
		// Mark the stack space as written, to avoid this problem.
		// See issue 26209.
		fmt.Fprintf(fgcc, "\t_cgo_msan_write(&_cgo_a->r, sizeof(_cgo_a->r));\n")
721
	}
Russ Cox's avatar
Russ Cox committed
722
	if n.AddError {
723
		fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
Russ Cox's avatar
Russ Cox committed
724 725 726 727 728
	}
	fmt.Fprintf(fgcc, "}\n")
	fmt.Fprintf(fgcc, "\n")
}

729 730
// Write out a wrapper for a function when using gccgo. This is a
// simple wrapper that just calls the real function. We only need a
Ian Lance Taylor's avatar
Ian Lance Taylor committed
731 732 733 734
// wrapper to support static functions in the prologue--without a
// wrapper, we can't refer to the function, since the reference is in
// a different file.
func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
735
	fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
	if t := n.FuncType.Result; t != nil {
		fmt.Fprintf(fgcc, "%s\n", t.C.String())
	} else {
		fmt.Fprintf(fgcc, "void\n")
	}
	fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
	for i, t := range n.FuncType.Params {
		if i > 0 {
			fmt.Fprintf(fgcc, ", ")
		}
		c := t.Typedef
		if c == "" {
			c = t.C.String()
		}
		fmt.Fprintf(fgcc, "%s p%d", c, i)
	}
	fmt.Fprintf(fgcc, ")\n")
	fmt.Fprintf(fgcc, "{\n")
754
	if t := n.FuncType.Result; t != nil {
755
		fmt.Fprintf(fgcc, "\t%s _cgo_r;\n", t.C.String())
756 757
	}
	fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
758 759
	fmt.Fprintf(fgcc, "\t")
	if t := n.FuncType.Result; t != nil {
760
		fmt.Fprintf(fgcc, "_cgo_r = ")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
761 762 763 764 765
		// Cast to void* to avoid warnings due to omitted qualifiers.
		if c := t.C.String(); c[len(c)-1] == '*' {
			fmt.Fprintf(fgcc, "(void*)")
		}
	}
766 767 768 769 770 771 772 773 774
	if n.Kind == "macro" {
		fmt.Fprintf(fgcc, "%s;\n", n.C)
	} else {
		fmt.Fprintf(fgcc, "%s(", n.C)
		for i := range n.FuncType.Params {
			if i > 0 {
				fmt.Fprintf(fgcc, ", ")
			}
			fmt.Fprintf(fgcc, "p%d", i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
775
		}
776
		fmt.Fprintf(fgcc, ");\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
777
	}
778 779 780 781 782 783 784 785
	fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
	if t := n.FuncType.Result; t != nil {
		fmt.Fprintf(fgcc, "\treturn ")
		// Cast to void* to avoid warnings due to omitted qualifiers
		// and explicit incompatible struct types.
		if c := t.C.String(); c[len(c)-1] == '*' {
			fmt.Fprintf(fgcc, "(void*)")
		}
786
		fmt.Fprintf(fgcc, "_cgo_r;\n")
787
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
788 789 790 791
	fmt.Fprintf(fgcc, "}\n")
	fmt.Fprintf(fgcc, "\n")
}

792
// packedAttribute returns host compiler struct attribute that will be
793 794
// used to match gc's struct layout. For example, on 386 Windows,
// gcc wants to 8-align int64s, but gc does not.
795
// Use __gcc_struct__ to work around https://gcc.gnu.org/PR52991 on x86,
796
// and https://golang.org/issue/5603.
797 798
func (p *Package) packedAttribute() string {
	s := "__attribute__((__packed__"
799
	if !p.GccIsClang && (goarch == "amd64" || goarch == "386") {
800 801 802 803 804
		s += ", __gcc_struct__"
	}
	return s + "))"
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
805 806
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
807
func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
808
	p.writeExportHeader(fgcch)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
809

810
	fmt.Fprintf(fgcc, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n")
811
	fmt.Fprintf(fgcc, "#include <stdlib.h>\n")
812
	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
813

814
	// We use packed structs, but they are always aligned.
815 816
	// The pragmas and address-of-packed-member are only recognized as
	// warning groups in clang 4.0+, so ignore unknown pragmas first.
817
	fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n")
818 819 820
	fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wpragmas\"\n")
	fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Waddress-of-packed-member\"\n")

821
	fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n")
822
	fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
823
	fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
824
	fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
825
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
826
	fmt.Fprintf(fgcc, "%s\n", msanProlog)
827

Russ Cox's avatar
Russ Cox committed
828
	for _, exp := range p.ExpFunc {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
829 830
		fn := exp.Func

831
		// Construct a gcc struct matching the gc argument and
832
		// result frame. The gcc struct will be compiled with
833 834
		// __attribute__((packed)) so all padding must be accounted
		// for explicitly.
Russ Cox's avatar
Russ Cox committed
835
		ctype := "struct {\n"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
836 837 838 839
		off := int64(0)
		npad := 0
		if fn.Recv != nil {
			t := p.cgoType(fn.Recv.List[0].Type)
Russ Cox's avatar
Russ Cox committed
840
			ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
841 842 843 844
			off += t.Size
		}
		fntype := fn.Type
		forFieldList(fntype.Params,
845
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
846 847 848
				t := p.cgoType(atype)
				if off%t.Align != 0 {
					pad := t.Align - off%t.Align
Russ Cox's avatar
Russ Cox committed
849
					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
850 851 852
					off += pad
					npad++
				}
Russ Cox's avatar
Russ Cox committed
853
				ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
854 855 856 857
				off += t.Size
			})
		if off%p.PtrSize != 0 {
			pad := p.PtrSize - off%p.PtrSize
Russ Cox's avatar
Russ Cox committed
858
			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
859 860 861 862
			off += pad
			npad++
		}
		forFieldList(fntype.Results,
863
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
864 865 866
				t := p.cgoType(atype)
				if off%t.Align != 0 {
					pad := t.Align - off%t.Align
867
					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
868 869 870
					off += pad
					npad++
				}
Russ Cox's avatar
Russ Cox committed
871
				ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
872 873 874 875
				off += t.Size
			})
		if off%p.PtrSize != 0 {
			pad := p.PtrSize - off%p.PtrSize
Russ Cox's avatar
Russ Cox committed
876
			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
877 878 879
			off += pad
			npad++
		}
Russ Cox's avatar
Russ Cox committed
880 881
		if ctype == "struct {\n" {
			ctype += "\t\tchar unused;\n" // avoid empty struct
Ian Lance Taylor's avatar
Ian Lance Taylor committed
882
		}
Russ Cox's avatar
Russ Cox committed
883
		ctype += "\t}"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
884 885 886 887 888 889 890

		// Get the return type of the wrapper function
		// compiled by gcc.
		gccResult := ""
		if fntype.Results == nil || len(fntype.Results.List) == 0 {
			gccResult = "void"
		} else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
891
			gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
Ian Lance Taylor's avatar
Ian Lance Taylor committed
892 893 894 895
		} else {
			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
			forFieldList(fntype.Results,
896 897 898 899 900 901
				func(i int, aname string, atype ast.Expr) {
					fmt.Fprintf(fgcch, "\t%s r%d;", p.cgoType(atype).C, i)
					if len(aname) > 0 {
						fmt.Fprintf(fgcch, " /* %s */", aname)
					}
					fmt.Fprint(fgcch, "\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
902 903 904 905 906 907 908 909
				})
			fmt.Fprintf(fgcch, "};\n")
			gccResult = "struct " + exp.ExpName + "_return"
		}

		// Build the wrapper function compiled by gcc.
		s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
		if fn.Recv != nil {
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
910
			s += p.cgoType(fn.Recv.List[0].Type).C.String()
Ian Lance Taylor's avatar
Ian Lance Taylor committed
911 912 913
			s += " recv"
		}
		forFieldList(fntype.Params,
914
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
915 916 917 918 919 920
				if i > 0 || fn.Recv != nil {
					s += ", "
				}
				s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
			})
		s += ")"
921 922 923 924

		if len(exp.Doc) > 0 {
			fmt.Fprintf(fgcch, "\n%s", exp.Doc)
		}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
925 926
		fmt.Fprintf(fgcch, "\nextern %s;\n", s)

927
		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName)
928
		fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
929 930
		fmt.Fprintf(fgcc, "\n%s\n", s)
		fmt.Fprintf(fgcc, "{\n")
931
		fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
932
		fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
Ian Lance Taylor's avatar
Ian Lance Taylor committed
933 934 935 936 937 938 939
		if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
			fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
		}
		if fn.Recv != nil {
			fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
		}
		forFieldList(fntype.Params,
940
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
941 942
				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
			})
943
		fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
944
		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
945
		fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
946
		fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
947 948 949 950 951
		if gccResult != "void" {
			if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
				fmt.Fprintf(fgcc, "\treturn a.r0;\n")
			} else {
				forFieldList(fntype.Results,
952
					func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
953 954 955 956 957 958 959
						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
					})
				fmt.Fprintf(fgcc, "\treturn r;\n")
			}
		}
		fmt.Fprintf(fgcc, "}\n")

960 961
		// Build the wrapper function compiled by cmd/compile.
		goname := "_cgoexpwrap" + cPrefix + "_"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
962
		if fn.Recv != nil {
963
			goname += fn.Recv.List[0].Names[0].Name + "_"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
964
		}
965
		goname += exp.Func.Name.Name
966
		fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName)
967 968 969
		fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
		fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
		fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
970
		fmt.Fprintf(fgo2, "//go:norace\n")  // must not have race detector calls inserted
971
		fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32, ctxt uintptr) {\n", cPrefix, exp.ExpName)
972 973
		fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
		// The indirect here is converting from a Go function pointer to a C function pointer.
974
		fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt);\n")
975
		fmt.Fprintf(fgo2, "}\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
976

977 978
		fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)

979 980 981 982 983 984
		// This code uses printer.Fprint, not conf.Fprint,
		// because we don't want //line comments in the middle
		// of the function types.
		fmt.Fprintf(fgo2, "\n")
		fmt.Fprintf(fgo2, "func %s(", goname)
		comma := false
Ian Lance Taylor's avatar
Ian Lance Taylor committed
985
		if fn.Recv != nil {
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
			fmt.Fprintf(fgo2, "recv ")
			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
			comma = true
		}
		forFieldList(fntype.Params,
			func(i int, aname string, atype ast.Expr) {
				if comma {
					fmt.Fprintf(fgo2, ", ")
				}
				fmt.Fprintf(fgo2, "p%d ", i)
				printer.Fprint(fgo2, fset, atype)
				comma = true
			})
		fmt.Fprintf(fgo2, ")")
		if gccResult != "void" {
			fmt.Fprint(fgo2, " (")
			forFieldList(fntype.Results,
1003
				func(i int, aname string, atype ast.Expr) {
1004 1005 1006 1007 1008
					if i > 0 {
						fmt.Fprint(fgo2, ", ")
					}
					fmt.Fprintf(fgo2, "r%d ", i)
					printer.Fprint(fgo2, fset, atype)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1009
				})
1010 1011 1012 1013
			fmt.Fprint(fgo2, ")")
		}
		fmt.Fprint(fgo2, " {\n")
		if gccResult == "void" {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1014
			fmt.Fprint(fgo2, "\t")
1015 1016 1017 1018 1019
		} else {
			// Verify that any results don't contain any
			// Go pointers.
			addedDefer := false
			forFieldList(fntype.Results,
1020
				func(i int, aname string, atype ast.Expr) {
1021 1022 1023 1024 1025 1026
					if !p.hasPointer(nil, atype, false) {
						return
					}
					if !addedDefer {
						fmt.Fprint(fgo2, "\tdefer func() {\n")
						addedDefer = true
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1027
					}
1028
					fmt.Fprintf(fgo2, "\t\t_cgoCheckResult(r%d)\n", i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1029
				})
1030 1031 1032 1033 1034 1035 1036
			if addedDefer {
				fmt.Fprint(fgo2, "\t}()\n")
			}
			fmt.Fprint(fgo2, "\treturn ")
		}
		if fn.Recv != nil {
			fmt.Fprintf(fgo2, "recv.")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1037
		}
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
		forFieldList(fntype.Params,
			func(i int, aname string, atype ast.Expr) {
				if i > 0 {
					fmt.Fprint(fgo2, ", ")
				}
				fmt.Fprintf(fgo2, "p%d", i)
			})
		fmt.Fprint(fgo2, ")\n")
		fmt.Fprint(fgo2, "}\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1048
	}
1049 1050

	fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1051 1052
}

1053
// Write out the C header allowing C code to call exported gccgo functions.
1054
func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
1055
	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
1056

1057
	p.writeExportHeader(fgcch)
1058

1059
	fmt.Fprintf(fgcc, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n")
1060
	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
1061

1062
	fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
1063
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
1064
	fmt.Fprintf(fgcc, "%s\n", msanProlog)
1065

1066 1067 1068 1069 1070 1071 1072
	for _, exp := range p.ExpFunc {
		fn := exp.Func
		fntype := fn.Type

		cdeclBuf := new(bytes.Buffer)
		resultCount := 0
		forFieldList(fntype.Results,
1073
			func(i int, aname string, atype ast.Expr) { resultCount++ })
1074 1075 1076 1077 1078
		switch resultCount {
		case 0:
			fmt.Fprintf(cdeclBuf, "void")
		case 1:
			forFieldList(fntype.Results,
1079
				func(i int, aname string, atype ast.Expr) {
1080 1081 1082 1083 1084
					t := p.cgoType(atype)
					fmt.Fprintf(cdeclBuf, "%s", t.C)
				})
		default:
			// Declare a result struct.
1085
			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
1086
			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
1087
			forFieldList(fntype.Results,
1088
				func(i int, aname string, atype ast.Expr) {
1089
					t := p.cgoType(atype)
1090 1091 1092 1093 1094
					fmt.Fprintf(fgcch, "\t%s r%d;", t.C, i)
					if len(aname) > 0 {
						fmt.Fprintf(fgcch, " /* %s */", aname)
					}
					fmt.Fprint(fgcch, "\n")
1095 1096
				})
			fmt.Fprintf(fgcch, "};\n")
1097
			fmt.Fprintf(cdeclBuf, "struct %s_return", exp.ExpName)
1098 1099
		}

1100 1101 1102 1103 1104 1105 1106
		cRet := cdeclBuf.String()

		cdeclBuf = new(bytes.Buffer)
		fmt.Fprintf(cdeclBuf, "(")
		if fn.Recv != nil {
			fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String())
		}
1107 1108
		// Function parameters.
		forFieldList(fntype.Params,
1109
			func(i int, aname string, atype ast.Expr) {
1110
				if i > 0 || fn.Recv != nil {
1111 1112 1113 1114 1115 1116
					fmt.Fprintf(cdeclBuf, ", ")
				}
				t := p.cgoType(atype)
				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
			})
		fmt.Fprintf(cdeclBuf, ")")
1117 1118
		cParams := cdeclBuf.String()

1119 1120 1121 1122
		if len(exp.Doc) > 0 {
			fmt.Fprintf(fgcch, "\n%s", exp.Doc)
		}

1123
		fmt.Fprintf(fgcch, "extern %s %s%s;\n", cRet, exp.ExpName, cParams)
1124

1125 1126 1127 1128
		// We need to use a name that will be exported by the
		// Go code; otherwise gccgo will make it static and we
		// will not be able to link against it from the C
		// code.
1129
		goName := "Cgoexp_" + exp.ExpName
1130 1131
		fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
		fmt.Fprint(fgcc, "\n")
1132

1133
		fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
1134
		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
1135 1136 1137
		if resultCount > 0 {
			fmt.Fprintf(fgcc, "\t%s r;\n", cRet)
		}
1138 1139
		fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
		fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
1140
		fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
1141 1142
		fmt.Fprint(fgcc, "\t")
		if resultCount > 0 {
1143
			fmt.Fprint(fgcc, "r = ")
1144 1145 1146 1147 1148 1149
		}
		fmt.Fprintf(fgcc, "%s(", goName)
		if fn.Recv != nil {
			fmt.Fprint(fgcc, "recv")
		}
		forFieldList(fntype.Params,
1150
			func(i int, aname string, atype ast.Expr) {
1151 1152 1153 1154 1155 1156
				if i > 0 || fn.Recv != nil {
					fmt.Fprintf(fgcc, ", ")
				}
				fmt.Fprintf(fgcc, "p%d", i)
			})
		fmt.Fprint(fgcc, ");\n")
1157 1158 1159 1160
		fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
		if resultCount > 0 {
			fmt.Fprint(fgcc, "\treturn r;\n")
		}
1161
		fmt.Fprint(fgcc, "}\n")
1162 1163

		// Dummy declaration for _cgo_main.c
1164 1165
		fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
		fmt.Fprint(fm, "\n")
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179

		// For gccgo we use a wrapper function in Go, in order
		// to call CgocallBack and CgocallBackDone.

		// This code uses printer.Fprint, not conf.Fprint,
		// because we don't want //line comments in the middle
		// of the function types.
		fmt.Fprint(fgo2, "\n")
		fmt.Fprintf(fgo2, "func %s(", goName)
		if fn.Recv != nil {
			fmt.Fprint(fgo2, "recv ")
			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
		}
		forFieldList(fntype.Params,
1180
			func(i int, aname string, atype ast.Expr) {
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
				if i > 0 || fn.Recv != nil {
					fmt.Fprintf(fgo2, ", ")
				}
				fmt.Fprintf(fgo2, "p%d ", i)
				printer.Fprint(fgo2, fset, atype)
			})
		fmt.Fprintf(fgo2, ")")
		if resultCount > 0 {
			fmt.Fprintf(fgo2, " (")
			forFieldList(fntype.Results,
1191
				func(i int, aname string, atype ast.Expr) {
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
					if i > 0 {
						fmt.Fprint(fgo2, ", ")
					}
					printer.Fprint(fgo2, fset, atype)
				})
			fmt.Fprint(fgo2, ")")
		}
		fmt.Fprint(fgo2, " {\n")
		fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n")
		fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n")
		fmt.Fprint(fgo2, "\t")
		if resultCount > 0 {
			fmt.Fprint(fgo2, "return ")
		}
		if fn.Recv != nil {
			fmt.Fprint(fgo2, "recv.")
		}
		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
		forFieldList(fntype.Params,
1211
			func(i int, aname string, atype ast.Expr) {
1212 1213 1214 1215 1216 1217 1218
				if i > 0 {
					fmt.Fprint(fgo2, ", ")
				}
				fmt.Fprintf(fgo2, "p%d", i)
			})
		fmt.Fprint(fgo2, ")\n")
		fmt.Fprint(fgo2, "}\n")
1219
	}
1220 1221

	fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
1222 1223
}

1224 1225
// writeExportHeader writes out the start of the _cgo_export.h file.
func (p *Package) writeExportHeader(fgcch io.Writer) {
1226
	fmt.Fprintf(fgcch, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n")
1227 1228 1229 1230 1231
	pkg := *importPath
	if pkg == "" {
		pkg = p.PackagePath
	}
	fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg)
1232
	fmt.Fprintf(fgcch, "%s\n", builtinExportProlog)
1233

1234 1235 1236 1237 1238 1239 1240
	// Remove absolute paths from #line comments in the preamble.
	// They aren't useful for people using the header file,
	// and they mean that the header files change based on the
	// exact location of GOPATH.
	re := regexp.MustCompile(`(?m)^(#line\s+[0-9]+\s+")[^"]*[/\\]([^"]*")`)
	preamble := re.ReplaceAllString(p.Preamble, "$1$2")

1241
	fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments.  */\n\n")
1242
	fmt.Fprintf(fgcch, "%s\n", preamble)
1243 1244 1245 1246 1247
	fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments.  */\n\n")

	fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
}

1248
// gccgoUsesNewMangling reports whether gccgo uses the new collision-free
1249 1250 1251 1252 1253 1254
// packagepath mangling scheme (see determineGccgoManglingScheme for more
// info).
func gccgoUsesNewMangling() bool {
	if !gccgoMangleCheckDone {
		gccgoNewmanglingInEffect = determineGccgoManglingScheme()
		gccgoMangleCheckDone = true
1255
	}
1256 1257
	return gccgoNewmanglingInEffect
}
1258

1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
const mangleCheckCode = `
package läufer
func Run(x int) int {
  return 1
}
`

// determineGccgoManglingScheme performs a runtime test to see which
// flavor of packagepath mangling gccgo is using. Older versions of
// gccgo use a simple mangling scheme where there can be collisions
// between packages whose paths are different but mangle to the same
// string. More recent versions of gccgo use a new mangler that avoids
// these collisions. Return value is whether gccgo uses the new mangling.
func determineGccgoManglingScheme() bool {

	// Emit a small Go file for gccgo to compile.
	filepat := "*_gccgo_manglecheck.go"
	var f *os.File
	var err error
	if f, err = ioutil.TempFile(*objDir, filepat); err != nil {
		fatalf("%v", err)
	}
	gofilename := f.Name()
	defer os.Remove(gofilename)

	if err = ioutil.WriteFile(gofilename, []byte(mangleCheckCode), 0666); err != nil {
		fatalf("%v", err)
	}

	// Compile with gccgo, capturing generated assembly.
	gccgocmd := os.Getenv("GCCGO")
	if gccgocmd == "" {
		gpath, gerr := exec.LookPath("gccgo")
		if gerr != nil {
			fatalf("unable to locate gccgo: %v", gerr)
		}
		gccgocmd = gpath
	}
	cmd := exec.Command(gccgocmd, "-S", "-o", "-", gofilename)
	buf, cerr := cmd.CombinedOutput()
	if cerr != nil {
1300
		fatalf("%s", cerr)
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
	}

	// New mangling: expect go.l..u00e4ufer.Run
	// Old mangling: expect go.l__ufer.Run
	return regexp.MustCompile(`go\.l\.\.u00e4ufer\.Run`).Match(buf)
}

// gccgoPkgpathToSymbolNew converts a package path to a gccgo-style
// package symbol.
func gccgoPkgpathToSymbolNew(ppath string) string {
	bsl := []byte{}
	changed := false
	for _, c := range []byte(ppath) {
		switch {
		case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
1316
			'0' <= c && c <= '9', c == '_':
1317
			bsl = append(bsl, c)
1318 1319
		case c == '.':
			bsl = append(bsl, ".x2e"...)
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
		default:
			changed = true
			encbytes := []byte(fmt.Sprintf("..z%02x", c))
			bsl = append(bsl, encbytes...)
		}
	}
	if !changed {
		return ppath
	}
	return string(bsl)
}

// gccgoPkgpathToSymbolOld converts a package path to a gccgo-style
// package symbol using the older mangling scheme.
func gccgoPkgpathToSymbolOld(ppath string) string {
1335 1336 1337 1338 1339 1340 1341 1342
	clean := func(r rune) rune {
		switch {
		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
			'0' <= r && r <= '9':
			return r
		}
		return '_'
	}
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
	return strings.Map(clean, ppath)
}

// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
// symbol.
func gccgoPkgpathToSymbol(ppath string) string {
	if gccgoUsesNewMangling() {
		return gccgoPkgpathToSymbolNew(ppath)
	} else {
		return gccgoPkgpathToSymbolOld(ppath)
	}
}

// Return the package prefix when using gccgo.
func (p *Package) gccgoSymbolPrefix() string {
	if !*gccgo {
		return ""
	}
1361 1362

	if *gccgopkgpath != "" {
1363
		return gccgoPkgpathToSymbol(*gccgopkgpath)
1364 1365 1366 1367
	}
	if *gccgoprefix == "" && p.PackageName == "main" {
		return "main"
	}
1368
	prefix := gccgoPkgpathToSymbol(*gccgoprefix)
1369 1370 1371 1372 1373 1374
	if prefix == "" {
		prefix = "go"
	}
	return prefix + "." + p.PackageName
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
1375
// Call a function for each entry in an ast.FieldList, passing the
1376 1377
// index into the list, the name if any, and the type.
func forFieldList(fl *ast.FieldList, fn func(int, string, ast.Expr)) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1378 1379 1380 1381 1382 1383
	if fl == nil {
		return
	}
	i := 0
	for _, r := range fl.List {
		if r.Names == nil {
1384
			fn(i, "", r.Type)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1385 1386
			i++
		} else {
1387 1388
			for _, n := range r.Names {
				fn(i, n.Name, r.Type)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1389 1390 1391 1392 1393 1394
				i++
			}
		}
	}
}

Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1395 1396 1397 1398
func c(repr string, args ...interface{}) *TypeRepr {
	return &TypeRepr{repr, args}
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
1399 1400
// Map predeclared Go types to Type.
var goTypes = map[string]*Type{
1401 1402
	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
Russ Cox's avatar
Russ Cox committed
1403 1404
	"int":        {Size: 0, Align: 0, C: c("GoInt")},
	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
1405 1406 1407 1408 1409 1410 1411 1412 1413
	"rune":       {Size: 4, Align: 4, C: c("GoInt32")},
	"int8":       {Size: 1, Align: 1, C: c("GoInt8")},
	"uint8":      {Size: 1, Align: 1, C: c("GoUint8")},
	"int16":      {Size: 2, Align: 2, C: c("GoInt16")},
	"uint16":     {Size: 2, Align: 2, C: c("GoUint16")},
	"int32":      {Size: 4, Align: 4, C: c("GoInt32")},
	"uint32":     {Size: 4, Align: 4, C: c("GoUint32")},
	"int64":      {Size: 8, Align: 8, C: c("GoInt64")},
	"uint64":     {Size: 8, Align: 8, C: c("GoUint64")},
1414 1415
	"float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
	"float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
1416 1417
	"complex64":  {Size: 8, Align: 4, C: c("GoComplex64")},
	"complex128": {Size: 16, Align: 8, C: c("GoComplex128")},
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1418 1419 1420
}

// Map an ast type to a Type.
Russ Cox's avatar
Russ Cox committed
1421
func (p *Package) cgoType(e ast.Expr) *Type {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1422 1423 1424
	switch t := e.(type) {
	case *ast.StarExpr:
		x := p.cgoType(t.X)
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1425
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1426 1427
	case *ast.ArrayType:
		if t.Len == nil {
1428 1429
			// Slice: pointer, len, cap.
			return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1430
		}
1431
		// Non-slice array types are not supported.
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1432
	case *ast.StructType:
1433
		// Not supported.
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1434
	case *ast.FuncType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1435
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1436
	case *ast.InterfaceType:
1437
		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1438
	case *ast.MapType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1439
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1440
	case *ast.ChanType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1441
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1442 1443 1444
	case *ast.Ident:
		// Look up the type in the top level declarations.
		// TODO: Handle types defined within a function.
Russ Cox's avatar
Russ Cox committed
1445
		for _, d := range p.Decl {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1446 1447 1448 1449 1450 1451 1452 1453 1454
			gd, ok := d.(*ast.GenDecl)
			if !ok || gd.Tok != token.TYPE {
				continue
			}
			for _, spec := range gd.Specs {
				ts, ok := spec.(*ast.TypeSpec)
				if !ok {
					continue
				}
1455
				if ts.Name.Name == t.Name {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1456 1457 1458 1459
					return p.cgoType(ts.Type)
				}
			}
		}
Russ Cox's avatar
Russ Cox committed
1460 1461
		if def := typedef[t.Name]; def != nil {
			return def
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1462
		}
1463
		if t.Name == "uintptr" {
1464
			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1465
		}
1466
		if t.Name == "string" {
1467
			// The string data is 1 pointer + 1 (pointer-sized) int.
Russ Cox's avatar
Russ Cox committed
1468
			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1469
		}
1470 1471 1472
		if t.Name == "error" {
			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
		}
1473
		if r, ok := goTypes[t.Name]; ok {
Russ Cox's avatar
Russ Cox committed
1474 1475 1476 1477 1478 1479 1480
			if r.Size == 0 { // int or uint
				rr := new(Type)
				*rr = *r
				rr.Size = p.IntSize
				rr.Align = p.IntSize
				r = rr
			}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1481 1482 1483 1484 1485
			if r.Align > p.PtrSize {
				r.Align = p.PtrSize
			}
			return r
		}
1486
		error_(e.Pos(), "unrecognized Go type %s", t.Name)
Russ Cox's avatar
Russ Cox committed
1487
		return &Type{Size: 4, Align: 4, C: c("int")}
1488 1489 1490
	case *ast.SelectorExpr:
		id, ok := t.X.(*ast.Ident)
		if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" {
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1491
			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
1492
		}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1493
	}
Russ Cox's avatar
Russ Cox committed
1494
	error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1495
	return &Type{Size: 4, Align: 4, C: c("int")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1496 1497
}

Russ Cox's avatar
Russ Cox committed
1498
const gccProlog = `
1499
#line 1 "cgo-gcc-prolog"
1500 1501 1502 1503 1504
/*
  If x and y are not equal, the type will be invalid
  (have a negative array count) and an inscrutable error will come
  out of the compiler and hopefully mention "name".
*/
Russ Cox's avatar
Russ Cox committed
1505 1506
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];

1507
/* Check at compile time that the sizes we use match our expectations. */
Russ Cox's avatar
Russ Cox committed
1508 1509 1510 1511 1512 1513 1514 1515 1516
#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)

__cgo_size_assert(char, 1)
__cgo_size_assert(short, 2)
__cgo_size_assert(int, 4)
typedef long long __cgo_long_long;
__cgo_size_assert(__cgo_long_long, 8)
__cgo_size_assert(float, 4)
__cgo_size_assert(double, 8)
Russ Cox's avatar
Russ Cox committed
1517

1518
extern char* _cgo_topofstack(void);
1519

1520 1521 1522 1523 1524
/*
  We use packed structs, but they are always aligned.
  The pragmas and address-of-packed-member are only recognized as warning
  groups in clang 4.0+, so ignore unknown pragmas first.
*/
1525
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
1526 1527 1528
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"

Russ Cox's avatar
Russ Cox committed
1529 1530
#include <errno.h>
#include <string.h>
Russ Cox's avatar
Russ Cox committed
1531 1532
`

1533
// Prologue defining TSAN functions in C.
1534
const noTsanProlog = `
1535
#define CGO_NO_SANITIZE_THREAD
1536 1537
#define _cgo_tsan_acquire()
#define _cgo_tsan_release()
1538
`
1539

1540
// This must match the TSAN code in runtime/cgo/libcgo.h.
1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
// This is used when the code is built with the C/C++ Thread SANitizer,
// which is not the same as the Go race detector.
// __tsan_acquire tells TSAN that we are acquiring a lock on a variable,
// in this case _cgo_sync. __tsan_release releases the lock.
// (There is no actual lock, we are just telling TSAN that there is.)
//
// When we call from Go to C we call _cgo_tsan_acquire.
// When the C function returns we call _cgo_tsan_release.
// Similarly, when C calls back into Go we call _cgo_tsan_release
// and then call _cgo_tsan_acquire when we return to C.
// These calls tell TSAN that there is a serialization point at the C call.
//
// This is necessary because TSAN, which is a C/C++ tool, can not see
// the synchronization in the Go code. Without these calls, when
// multiple goroutines call into C code, TSAN does not understand
// that the calls are properly synchronized on the Go side.
//
// To be clear, if the calls are not properly synchronized on the Go side,
// we will be hiding races. But when using TSAN on mixed Go C/C++ code
// it is more important to avoid false positives, which reduce confidence
// in the tool, than to avoid false negatives.
1562
const yesTsanProlog = `
1563
#line 1 "cgo-tsan-prolog"
1564 1565
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))

1566 1567 1568 1569 1570
long long _cgo_sync __attribute__ ((common));

extern void __tsan_acquire(void*);
extern void __tsan_release(void*);

1571
__attribute__ ((unused))
1572 1573 1574 1575
static void _cgo_tsan_acquire() {
	__tsan_acquire(&_cgo_sync);
}

1576
__attribute__ ((unused))
1577 1578 1579 1580 1581
static void _cgo_tsan_release() {
	__tsan_release(&_cgo_sync);
}
`

1582 1583 1584
// Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc.
var tsanProlog = noTsanProlog

1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603
// noMsanProlog is a prologue defining an MSAN function in C.
// This is used when not compiling with -fsanitize=memory.
const noMsanProlog = `
#define _cgo_msan_write(addr, sz)
`

// yesMsanProlog is a prologue defining an MSAN function in C.
// This is used when compiling with -fsanitize=memory.
// See the comment above where _cgo_msan_write is called.
const yesMsanProlog = `
extern void __msan_unpoison(const volatile void *, size_t);

#define _cgo_msan_write(addr, sz) __msan_unpoison((addr), (sz))
`

// msanProlog is set to yesMsanProlog if we see -fsanitize=memory in the flags
// for the C compiler.
var msanProlog = noMsanProlog

Russ Cox's avatar
Russ Cox committed
1604
const builtinProlog = `
1605
#line 1 "cgo-builtin-prolog"
1606
#include <stddef.h> /* for ptrdiff_t and size_t below */
1607

1608
/* Define intgo when compiling with GCC.  */
1609
typedef ptrdiff_t intgo;
1610

1611
#define GO_CGO_GOSTRING_TYPEDEF
1612
typedef struct { const char *p; intgo n; } _GoString_;
1613
typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
Russ Cox's avatar
Russ Cox committed
1614
_GoString_ GoString(char *p);
1615 1616
_GoString_ GoStringN(char *p, int l);
_GoBytes_ GoBytes(void *p, int n);
Russ Cox's avatar
Russ Cox committed
1617
char *CString(_GoString_);
James Bardin's avatar
James Bardin committed
1618
void *CBytes(_GoBytes_);
1619
void *_CMalloc(size_t);
1620 1621

__attribute__ ((unused))
1622
static size_t _GoStringLen(_GoString_ s) { return (size_t)s.n; }
1623 1624 1625

__attribute__ ((unused))
static const char *_GoStringPtr(_GoString_ s) { return s.p; }
Russ Cox's avatar
Russ Cox committed
1626 1627
`

1628
const goProlog = `
1629 1630
//go:linkname _cgo_runtime_cgocall runtime.cgocall
func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
1631 1632

//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
1633
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
1634 1635

//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
1636
func _cgoCheckPointer(interface{}, interface{})
1637 1638 1639

//go:linkname _cgoCheckResult runtime.cgoCheckResult
func _cgoCheckResult(interface{})
1640 1641
`

1642
const gccgoGoProlog = `
1643
func _cgoCheckPointer(interface{}, interface{})
1644 1645 1646 1647

func _cgoCheckResult(interface{})
`

1648
const goStringDef = `
1649 1650 1651
//go:linkname _cgo_runtime_gostring runtime.gostring
func _cgo_runtime_gostring(*_Ctype_char) string

1652 1653
func _Cfunc_GoString(p *_Ctype_char) string {
	return _cgo_runtime_gostring(p)
Russ Cox's avatar
Russ Cox committed
1654
}
1655
`
Russ Cox's avatar
Russ Cox committed
1656

1657
const goStringNDef = `
1658 1659 1660
//go:linkname _cgo_runtime_gostringn runtime.gostringn
func _cgo_runtime_gostringn(*_Ctype_char, int) string

1661 1662
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
	return _cgo_runtime_gostringn(p, int(l))
Eric Clark's avatar
Eric Clark committed
1663
}
1664
`
Eric Clark's avatar
Eric Clark committed
1665

1666
const goBytesDef = `
1667 1668 1669
//go:linkname _cgo_runtime_gobytes runtime.gobytes
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte

1670 1671
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
	return _cgo_runtime_gobytes(p, int(l))
Russ Cox's avatar
Russ Cox committed
1672
}
1673
`
Russ Cox's avatar
Russ Cox committed
1674

1675 1676
const cStringDef = `
func _Cfunc_CString(s string) *_Ctype_char {
1677
	p := _cgo_cmalloc(uint64(len(s)+1))
1678 1679 1680 1681
	pp := (*[1<<30]byte)(p)
	copy(pp[:], s)
	pp[len(s)] = 0
	return (*_Ctype_char)(p)
Russ Cox's avatar
Russ Cox committed
1682
}
1683
`
1684

James Bardin's avatar
James Bardin committed
1685 1686
const cBytesDef = `
func _Cfunc_CBytes(b []byte) unsafe.Pointer {
1687
	p := _cgo_cmalloc(uint64(len(b)))
James Bardin's avatar
James Bardin committed
1688 1689 1690 1691 1692 1693
	pp := (*[1<<30]byte)(p)
	copy(pp[:], b)
	return p
}
`

1694 1695
const cMallocDef = `
func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
1696
	return _cgo_cmalloc(uint64(n))
1697
}
Russ Cox's avatar
Russ Cox committed
1698
`
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1699

1700 1701 1702 1703 1704
var builtinDefs = map[string]string{
	"GoString":  goStringDef,
	"GoStringN": goStringNDef,
	"GoBytes":   goBytesDef,
	"CString":   cStringDef,
James Bardin's avatar
James Bardin committed
1705
	"CBytes":    cBytesDef,
1706 1707 1708
	"_CMalloc":  cMallocDef,
}

1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
// Definitions for C.malloc in Go and in C. We define it ourselves
// since we call it from functions we define, such as C.CString.
// Also, we have historically ensured that C.malloc does not return
// nil even for an allocation of 0.

const cMallocDefGo = `
//go:cgo_import_static _cgoPREFIX_Cfunc__Cmalloc
//go:linkname __cgofn__cgoPREFIX_Cfunc__Cmalloc _cgoPREFIX_Cfunc__Cmalloc
var __cgofn__cgoPREFIX_Cfunc__Cmalloc byte
var _cgoPREFIX_Cfunc__Cmalloc = unsafe.Pointer(&__cgofn__cgoPREFIX_Cfunc__Cmalloc)

1720 1721 1722
//go:linkname runtime_throw runtime.throw
func runtime_throw(string)

1723 1724 1725
//go:cgo_unsafe_args
func _cgo_cmalloc(p0 uint64) (r1 unsafe.Pointer) {
	_cgo_runtime_cgocall(_cgoPREFIX_Cfunc__Cmalloc, uintptr(unsafe.Pointer(&p0)))
1726 1727 1728
	if r1 == nil {
		runtime_throw("runtime: C malloc failed")
	}
1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758
	return
}
`

// cMallocDefC defines the C version of C.malloc for the gc compiler.
// It is defined here because C.CString and friends need a definition.
// We define it by hand, rather than simply inventing a reference to
// C.malloc, because <stdlib.h> may not have been included.
// This is approximately what writeOutputFunc would generate, but
// skips the cgo_topofstack code (which is only needed if the C code
// calls back into Go). This also avoids returning nil for an
// allocation of 0 bytes.
const cMallocDefC = `
CGO_NO_SANITIZE_THREAD
void _cgoPREFIX_Cfunc__Cmalloc(void *v) {
	struct {
		unsigned long long p0;
		void *r1;
	} PACKED *a = v;
	void *ret;
	_cgo_tsan_acquire();
	ret = malloc(a->p0);
	if (ret == 0 && a->p0 == 0) {
		ret = malloc(1);
	}
	a->r1 = ret;
	_cgo_tsan_release();
}
`

1759
func (p *Package) cPrologGccgo() string {
1760 1761
	return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
		"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
1762 1763
}

1764
const cPrologGccgo = `
1765
#line 1 "cgo-c-prolog-gccgo"
1766
#include <stdint.h>
1767
#include <stdlib.h>
1768 1769
#include <string.h>

1770
typedef unsigned char byte;
1771
typedef intptr_t intgo;
1772

1773 1774
struct __go_string {
	const unsigned char *__data;
1775
	intgo __length;
1776 1777 1778 1779
};

typedef struct __go_open_array {
	void* __values;
1780 1781
	intgo __count;
	intgo __capacity;
1782 1783
} Slice;

1784
struct __go_string __go_byte_array_to_string(const void* p, intgo len);
1785 1786
struct __go_open_array __go_string_to_byte_array (struct __go_string str);

1787
const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
1788 1789 1790 1791
	char *p = malloc(s.__length+1);
	memmove(p, s.__data, s.__length);
	p[s.__length] = 0;
	return p;
1792 1793
}

James Bardin's avatar
James Bardin committed
1794 1795
void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) {
	char *p = malloc(b.__count);
1796
	memmove(p, b.__values, b.__count);
James Bardin's avatar
James Bardin committed
1797 1798 1799
	return p;
}

1800
struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
1801
	intgo len = (p != NULL) ? strlen(p) : 0;
1802
	return __go_byte_array_to_string(p, len);
1803 1804
}

1805
struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
1806 1807 1808
	return __go_byte_array_to_string(p, n);
}

1809
Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
1810
	struct __go_string s = { (const unsigned char *)p, n };
1811 1812
	return __go_string_to_byte_array(s);
}
1813

1814 1815
extern void runtime_throw(const char *);
void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
1816
        void *p = malloc(n);
Russ Cox's avatar
Russ Cox committed
1817 1818
        if(p == NULL && n == 0)
                p = malloc(1);
1819 1820 1821 1822
        if(p == NULL)
                runtime_throw("runtime: C malloc failed");
        return p;
}
1823 1824 1825 1826 1827 1828 1829

struct __go_type_descriptor;
typedef struct __go_empty_interface {
	const struct __go_type_descriptor *__type_descriptor;
	void *__object;
} Eface;

1830
extern void runtimeCgoCheckPointer(Eface, Eface)
1831 1832 1833
	__asm__("runtime.cgoCheckPointer")
	__attribute__((weak));

1834
extern void localCgoCheckPointer(Eface, Eface)
1835 1836
	__asm__("GCCGOSYMBOLPREF._cgoCheckPointer");

1837
void localCgoCheckPointer(Eface ptr, Eface arg) {
1838
	if(runtimeCgoCheckPointer) {
1839
		runtimeCgoCheckPointer(ptr, arg);
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854
	}
}

extern void runtimeCgoCheckResult(Eface)
	__asm__("runtime.cgoCheckResult")
	__attribute__((weak));

extern void localCgoCheckResult(Eface)
	__asm__("GCCGOSYMBOLPREF._cgoCheckResult");

void localCgoCheckResult(Eface val) {
	if(runtimeCgoCheckResult) {
		runtimeCgoCheckResult(val);
	}
}
1855 1856
`

1857 1858 1859 1860 1861 1862
// builtinExportProlog is a shorter version of builtinProlog,
// to be put into the _cgo_export.h file.
// For historical reasons we can't use builtinProlog in _cgo_export.h,
// because _cgo_export.h defines GoString as a struct while builtinProlog
// defines it as a function. We don't change this to avoid unnecessarily
// breaking existing code.
1863 1864 1865
// The test of GO_CGO_GOSTRING_TYPEDEF avoids a duplicate definition
// error if a Go file with a cgo comment #include's the export header
// generated by a different package.
1866
const builtinExportProlog = `
1867
#line 1 "cgo-builtin-export-prolog"
1868 1869 1870 1871 1872 1873

#include <stddef.h> /* for ptrdiff_t below */

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

1874
#ifndef GO_CGO_GOSTRING_TYPEDEF
1875
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
1876
#endif
1877 1878 1879 1880

#endif
`

Russ Cox's avatar
Russ Cox committed
1881 1882 1883 1884
func (p *Package) gccExportHeaderProlog() string {
	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
}

1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897
// gccExportHeaderProlog is written to the exported header, after the
// import "C" comment preamble but before the generated declarations
// of exported functions. This permits the generated declarations to
// use the type names that appear in goTypes, above.
//
// The test of GO_CGO_GOSTRING_TYPEDEF avoids a duplicate definition
// error if a Go file with a cgo comment #include's the export header
// generated by a different package. Unfortunately GoString means two
// different things: in this prolog it means a C name for the Go type,
// while in the prolog written into the start of the C code generated
// from a cgo-using Go file it means the C.GoString function. There is
// no way to resolve this conflict, but it also doesn't make much
// difference, as Go code never wants to refer to the latter meaning.
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1898
const gccExportHeaderProlog = `
1899
/* Start of boilerplate cgo prologue.  */
1900
#line 1 "cgo-gcc-export-header-prolog"
1901

1902 1903 1904
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoIntGOINTBITS GoInt;
typedef GoUintGOINTBITS GoUint;
1915 1916 1917
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
1918 1919
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1920

1921 1922 1923 1924
/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
1925 1926
typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];

1927
#ifndef GO_CGO_GOSTRING_TYPEDEF
1928
typedef _GoString_ GoString;
1929
#endif
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1930 1931 1932
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
1933
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
1934

1935 1936
#endif

1937
/* End of boilerplate cgo prologue.  */
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948

#ifdef __cplusplus
extern "C" {
#endif
`

// gccExportHeaderEpilog goes at the end of the generated header file.
const gccExportHeaderEpilog = `
#ifdef __cplusplus
}
#endif
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1949
`
1950 1951 1952 1953 1954 1955

// gccgoExportFileProlog is written to the _cgo_export.c file when
// using gccgo.
// We use weak declarations, and test the addresses, so that this code
// works with older versions of gccgo.
const gccgoExportFileProlog = `
1956
#line 1 "cgo-gccgo-export-file-prolog"
1957 1958 1959 1960 1961 1962 1963 1964
extern _Bool runtime_iscgo __attribute__ ((weak));

static void GoInit(void) __attribute__ ((constructor));
static void GoInit(void) {
	if(&runtime_iscgo)
		runtime_iscgo = 1;
}

1965
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void) __attribute__ ((weak));
1966
`