out.go 47.5 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
	"io"
17
	"os"
18
	"sort"
19
	"strings"
Russ Cox's avatar
Russ Cox committed
20 21
)

22 23 24 25
var (
	conf         = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
	noSourceConf = printer.Config{Tabwidth: 8}
)
26

27
// writeDefs creates output files to be compiled by gc and gcc.
Russ Cox's avatar
Russ Cox committed
28
func (p *Package) writeDefs() {
29 30 31 32 33 34 35 36 37
	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
38
	fm := creat(*objDir + "_cgo_main.c")
39

40 41
	var gccgoInit bytes.Buffer

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

53 54
	// 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
55
	if *importRuntimeCgo {
56 57 58
		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
		fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; }\n")
		fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n")
59
		fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
Russ Cox's avatar
Russ Cox committed
60 61
	} else {
		// If we're not importing runtime/cgo, we *are* runtime/cgo,
62
		// which provides these functions. We just need a prototype.
63 64 65
		fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n")
		fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
		fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
Russ Cox's avatar
Russ Cox committed
66
	}
67 68
	fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
	fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
69
	fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n")
Russ Cox's avatar
Russ Cox committed
70 71 72 73

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

86 87 88 89 90 91 92
	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")
	}

93 94 95 96 97 98 99
	typedefNames := make([]string, 0, len(typedef))
	for name := range typedef {
		typedefNames = append(typedefNames, name)
	}
	sort.Strings(typedefNames)
	for _, name := range typedefNames {
		def := typedef[name]
100
		fmt.Fprintf(fgo2, "type %s ", name)
101 102 103 104 105 106 107 108 109 110 111 112
		// 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.
113 114 115 116 117 118 119
		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())
120
		fmt.Fprintf(fgo2, "\n\n")
Russ Cox's avatar
Russ Cox committed
121
	}
122 123 124 125 126
	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
127

128
	if *gccgo {
129
		fmt.Fprint(fgo2, gccgoGoProlog)
130
		fmt.Fprint(fc, p.cPrologGccgo())
131
	} else {
132
		fmt.Fprint(fgo2, goProlog)
133
	}
Russ Cox's avatar
Russ Cox committed
134

135 136 137 138 139 140 141
	if fc != nil {
		fmt.Fprintf(fc, "#line 1 \"cgo-generated-wrappers\"\n")
	}
	if fm != nil {
		fmt.Fprintf(fm, "#line 1 \"cgo-generated-wrappers\"\n")
	}

142 143
	gccgoSymbolPrefix := p.gccgoSymbolPrefix()

144
	cVars := make(map[string]bool)
145 146
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
147
		if !n.IsVar() {
Russ Cox's avatar
Russ Cox committed
148 149
			continue
		}
Russ Cox's avatar
Russ Cox committed
150

151
		if !cVars[n.C] {
152 153 154
			if *gccgo {
				fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
			} else {
155 156
				fmt.Fprintf(fm, "extern char %s[];\n", n.C)
				fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
157 158 159
				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)
160
			}
161 162
			cVars[n.C] = true
		}
163

164 165 166 167 168 169 170 171
		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))
		}
172 173
		if *gccgo {
			fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
174 175
			fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
			fmt.Fprintf(fc, "\n")
176
		}
Russ Cox's avatar
Russ Cox committed
177

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

191 192
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
Russ Cox's avatar
Russ Cox committed
193
		if n.Const != "" {
194
			fmt.Fprintf(fgo2, "const %s = %s\n", n.Mangle, n.Const)
Russ Cox's avatar
Russ Cox committed
195
		}
196 197 198
	}
	fmt.Fprintf(fgo2, "\n")

199
	callsMalloc := false
200 201
	for _, key := range nameKeys(p.Name) {
		n := p.Name[key]
Russ Cox's avatar
Russ Cox committed
202
		if n.FuncType != nil {
203
			p.writeDefsFunc(fgo2, n, &callsMalloc)
204
		}
Russ Cox's avatar
Russ Cox committed
205
	}
Russ Cox's avatar
Russ Cox committed
206

207 208
	fgcc := creat(*objDir + "_cgo_export.c")
	fgcch := creat(*objDir + "_cgo_export.h")
209
	if *gccgo {
210
		p.writeGccgoExports(fgo2, fm, fgcc, fgcch)
211
	} else {
212 213
		p.writeExports(fgo2, fm, fgcc, fgcch)
	}
214 215 216 217 218 219

	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))
	}

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
	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)
		}
240
	}
Russ Cox's avatar
Russ Cox committed
241

242 243 244 245 246 247 248
	init := gccgoInit.String()
	if init != "" {
		fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));")
		fmt.Fprintln(fc, "static void init(void) {")
		fmt.Fprint(fc, init)
		fmt.Fprintln(fc, "}")
	}
Russ Cox's avatar
Russ Cox committed
249 250
}

Russ Cox's avatar
Russ Cox committed
251
func dynimport(obj string) {
Russ Cox's avatar
Russ Cox committed
252 253 254 255 256 257 258 259 260
	stdout := os.Stdout
	if *dynout != "" {
		f, err := os.Create(*dynout)
		if err != nil {
			fatalf("%s", err)
		}
		stdout = f
	}

261 262
	fmt.Fprintf(stdout, "package %s\n", *dynpackage)

Russ Cox's avatar
Russ Cox committed
263
	if f, err := elf.Open(obj); err == nil {
264 265
		if *dynlinker {
			// Emit the cgo_dynamic_linker line.
266 267 268
			if sec := f.Section(".interp"); sec != nil {
				if data, err := sec.Data(); err == nil && len(data) > 1 {
					// skip trailing \0 in data
269
					fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
270
				}
271 272
			}
		}
Russ Cox's avatar
Russ Cox committed
273 274 275 276 277 278 279
		sym, err := f.ImportedSymbols()
		if err != nil {
			fatalf("cannot load imported symbols from ELF file %s: %v", obj, err)
		}
		for _, s := range sym {
			targ := s.Name
			if s.Version != "" {
280
				targ += "#" + s.Version
Wei Guangjing's avatar
Wei Guangjing committed
281
			}
282
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
Russ Cox's avatar
Russ Cox committed
283 284 285 286
		}
		lib, err := f.ImportedLibraries()
		if err != nil {
			fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
Russ Cox's avatar
Russ Cox committed
287
		}
Russ Cox's avatar
Russ Cox committed
288
		for _, l := range lib {
289
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
Russ Cox's avatar
Russ Cox committed
290 291
		}
		return
Russ Cox's avatar
Russ Cox committed
292 293
	}

Russ Cox's avatar
Russ Cox committed
294 295 296 297 298 299 300 301
	if f, err := macho.Open(obj); err == nil {
		sym, err := f.ImportedSymbols()
		if err != nil {
			fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err)
		}
		for _, s := range sym {
			if len(s) > 0 && s[0] == '_' {
				s = s[1:]
Russ Cox's avatar
Russ Cox committed
302
			}
303
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
Russ Cox's avatar
Russ Cox committed
304 305 306 307 308 309
		}
		lib, err := f.ImportedLibraries()
		if err != nil {
			fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
		}
		for _, l := range lib {
310
			fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
Russ Cox's avatar
Russ Cox committed
311
		}
Russ Cox's avatar
Russ Cox committed
312
		return
Russ Cox's avatar
Russ Cox committed
313 314
	}

Russ Cox's avatar
Russ Cox committed
315 316 317
	if f, err := pe.Open(obj); err == nil {
		sym, err := f.ImportedSymbols()
		if err != nil {
Robert Hencke's avatar
Robert Hencke committed
318
			fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
Russ Cox's avatar
Russ Cox committed
319 320
		}
		for _, s := range sym {
321
			ss := strings.Split(s, ":")
322
			name := strings.Split(ss[0], "@")[0]
323
			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
324 325
		}
		return
Russ Cox's avatar
Russ Cox committed
326 327
	}

Russ Cox's avatar
Russ Cox committed
328
	fatalf("cannot parse %s as ELF, Mach-O or PE", obj)
Russ Cox's avatar
Russ Cox committed
329 330
}

331
// Construct a gcc struct matching the gc argument frame.
Russ Cox's avatar
Russ Cox committed
332 333
// 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.
334
// Also assumes that gc convention is to word-align the
Russ Cox's avatar
Russ Cox committed
335 336 337 338 339 340 341 342 343
// 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)
344
			off += pad
Russ Cox's avatar
Russ Cox committed
345
		}
Russ Cox's avatar
Russ Cox committed
346 347 348 349 350
		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
351 352 353 354 355 356 357 358 359 360 361
		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)
362
			off += pad
Russ Cox's avatar
Russ Cox committed
363
		}
364
		fmt.Fprintf(&buf, "\t\t%s r;\n", t.C)
Russ Cox's avatar
Russ Cox committed
365 366 367 368 369 370 371 372 373 374
		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
375
	fmt.Fprintf(&buf, "\t}")
Russ Cox's avatar
Russ Cox committed
376 377 378
	return buf.String(), off
}

379
func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name, callsMalloc *bool) {
Russ Cox's avatar
Russ Cox committed
380 381
	name := n.Go
	gtype := n.FuncType.Go
382
	void := gtype.Results == nil || len(gtype.Results.List) == 0
Russ Cox's avatar
Russ Cox committed
383
	if n.AddError {
384
		// Add "error" to return type list.
Russ Cox's avatar
Russ Cox committed
385
		// Type list is known to be 0 or 1 element - it's a C function.
386
		err := &ast.Field{Type: ast.NewIdent("error")}
Russ Cox's avatar
Russ Cox committed
387 388 389 390 391
		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
392
		}
Russ Cox's avatar
Russ Cox committed
393 394 395 396
		t := new(ast.FuncType)
		*t = *gtype
		t.Results = &ast.FieldList{List: l}
		gtype = t
397 398
	}

Russ Cox's avatar
Russ Cox committed
399 400 401 402 403
	// Go func declaration.
	d := &ast.FuncDecl{
		Name: ast.NewIdent(n.Mangle),
		Type: gtype,
	}
404

Ian Lance Taylor's avatar
Ian Lance Taylor committed
405
	// Builtins defined in the C prolog.
406 407 408
	inProlog := builtinDefs[name] != ""
	cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
	paramnames := []string(nil)
409 410 411 412 413 414
	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)
		}
415
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
416

417
	if *gccgo {
418
		// Gccgo style hooks.
419 420 421
		fmt.Fprint(fgo2, "\n")
		conf.Fprint(fgo2, fset, d)
		fmt.Fprint(fgo2, " {\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
422 423 424 425
		if !inProlog {
			fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
			fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
		}
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
		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, ")
447
			}
448 449 450 451 452 453 454 455
			fmt.Fprint(fgo2, "nil\n")
		} else if !void {
			fmt.Fprint(fgo2, "\treturn r\n")
		}

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

		// declare the C function.
456
		fmt.Fprintf(fgo2, "//extern %s\n", cname)
457 458
		d.Name = ast.NewIdent(cname)
		if n.AddError {
459 460 461
			l := d.Type.Results.List
			d.Type.Results.List = l[:len(l)-1]
		}
462 463 464
		conf.Fprint(fgo2, fset, d)
		fmt.Fprint(fgo2, "\n")

465
		return
466
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
467

Ian Lance Taylor's avatar
Ian Lance Taylor committed
468
	if inProlog {
469
		fmt.Fprint(fgo2, builtinDefs[name])
470 471 472
		if strings.Contains(builtinDefs[name], "_cgo_cmalloc") {
			*callsMalloc = true
		}
Russ Cox's avatar
Russ Cox committed
473 474 475
		return
	}

476
	// Wrapper calls into gcc, passing a pointer to the argument frame.
477 478 479 480
	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)
481 482 483 484 485

	nret := 0
	if !void {
		d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")}
		nret = 1
486
	}
487 488
	if n.AddError {
		d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")}
489
	}
490 491

	fmt.Fprint(fgo2, "\n")
492
	fmt.Fprint(fgo2, "//go:cgo_unsafe_args\n")
493 494 495 496 497 498 499 500 501
	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))"
502
	}
503 504

	prefix := ""
Russ Cox's avatar
Russ Cox committed
505
	if n.AddError {
506
		prefix = "errno := "
Russ Cox's avatar
Russ Cox committed
507
	}
508
	fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg)
509 510 511
	if n.AddError {
		fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n")
	}
512
	fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n")
513 514 515 516
	if d.Type.Params != nil {
		for i := range d.Type.Params.List {
			fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i)
		}
517 518
	}
	fmt.Fprintf(fgo2, "\t}\n")
519 520
	fmt.Fprintf(fgo2, "\treturn\n")
	fmt.Fprintf(fgo2, "}\n")
521 522
}

523
// writeOutput creates stubs for a specific source file to be compiled by gc
Russ Cox's avatar
Russ Cox committed
524
func (p *Package) writeOutput(f *File, srcfile string) {
525 526 527 528
	base := srcfile
	if strings.HasSuffix(base, ".go") {
		base = base[0 : len(base)-3]
	}
Russ Cox's avatar
Russ Cox committed
529
	base = strings.Map(slashToUnderscore, base)
Russ Cox's avatar
Russ Cox committed
530 531
	fgo1 := creat(*objDir + base + ".cgo1.go")
	fgcc := creat(*objDir + base + ".cgo2.c")
532

Russ Cox's avatar
Russ Cox committed
533 534 535
	p.GoFiles = append(p.GoFiles, base+".cgo1.go")
	p.GccFiles = append(p.GccFiles, base+".cgo2.c")

536
	// Write Go output: Go input with rewrites of C.xxx to _C_xxx.
537
	fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n")
538
	conf.Fprint(fgo1, fset, f.AST)
539

540
	// While we process the vars and funcs, also write gcc output.
541
	// Gcc output starts with the preamble.
Russ Cox's avatar
Russ Cox committed
542
	fmt.Fprintf(fgcc, "%s\n", f.Preamble)
543
	fmt.Fprintf(fgcc, "%s\n", gccProlog)
544
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
545

546 547
	for _, key := range nameKeys(f.Name) {
		n := f.Name[key]
Russ Cox's avatar
Russ Cox committed
548 549
		if n.FuncType != nil {
			p.writeOutputFunc(fgcc, n)
Russ Cox's avatar
Russ Cox committed
550 551
		}
	}
Russ Cox's avatar
Russ Cox committed
552

553 554
	fgo1.Close()
	fgcc.Close()
Russ Cox's avatar
Russ Cox committed
555 556
}

Robert Hencke's avatar
Robert Hencke committed
557
// fixGo converts the internal Name.Go field into the name we should show
558 559 560 561 562 563 564 565 566 567 568
// 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
569
	"_Cfunc_CBytes":    true,
570 571 572 573 574 575
	"_Cfunc_GoString":  true,
	"_Cfunc_GoStringN": true,
	"_Cfunc_GoBytes":   true,
	"_Cfunc__CMalloc":  true,
}

Russ Cox's avatar
Russ Cox committed
576 577
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
	name := n.Mangle
578
	if isBuiltin[name] || p.Written[name] {
Russ Cox's avatar
Russ Cox committed
579 580 581 582 583 584
		// 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

585
	if *gccgo {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
586
		p.writeGccgoOutputFunc(fgcc, n)
587 588 589
		return
	}

Shenghou Ma's avatar
Shenghou Ma committed
590
	ctype, _ := p.structType(n)
Russ Cox's avatar
Russ Cox committed
591 592 593

	// Gcc wrapper unpacks the C argument struct
	// and calls the actual C function.
594
	fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
595 596 597 598 599
	if n.AddError {
		fmt.Fprintf(fgcc, "int\n")
	} else {
		fmt.Fprintf(fgcc, "void\n")
	}
600
	fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
Russ Cox's avatar
Russ Cox committed
601 602
	fmt.Fprintf(fgcc, "{\n")
	if n.AddError {
603
		fmt.Fprintf(fgcc, "\tint _cgo_errno;\n")
Russ Cox's avatar
Russ Cox committed
604
	}
605
	// We're trying to write a gcc struct that matches gc's layout.
606
	// Use packed attribute to force no padding in this struct in case
607
	// gcc has different packing requirements.
Shenghou Ma's avatar
Shenghou Ma committed
608
	fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
609 610
	if n.FuncType.Result != nil {
		// Save the stack top for use below.
611
		fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n")
612
	}
613 614 615 616
	tr := n.FuncType.Result
	if tr != nil {
		fmt.Fprintf(fgcc, "\t__typeof__(a->r) r;\n")
	}
617
	fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
618 619 620
	if n.AddError {
		fmt.Fprintf(fgcc, "\terrno = 0;\n")
	}
Russ Cox's avatar
Russ Cox committed
621
	fmt.Fprintf(fgcc, "\t")
622 623 624
	if tr != nil {
		fmt.Fprintf(fgcc, "r = ")
		if c := tr.C.String(); c[len(c)-1] == '*' {
625
			fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
626
		}
Russ Cox's avatar
Russ Cox committed
627
	}
628 629 630 631 632 633 634 635 636
	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, "a->p%d", i)
Russ Cox's avatar
Russ Cox committed
637
		}
638
		fmt.Fprintf(fgcc, ");\n")
Russ Cox's avatar
Russ Cox committed
639
	}
640 641 642
	if n.AddError {
		fmt.Fprintf(fgcc, "\t_cgo_errno = errno;\n")
	}
643
	fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
644 645 646
	if n.FuncType.Result != nil {
		// The cgo call may have caused a stack copy (via a callback).
		// Adjust the return value pointer appropriately.
647
		fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n")
648 649 650
		// Save the return value.
		fmt.Fprintf(fgcc, "\ta->r = r;\n")
	}
Russ Cox's avatar
Russ Cox committed
651
	if n.AddError {
652
		fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n")
Russ Cox's avatar
Russ Cox committed
653 654 655 656 657
	}
	fmt.Fprintf(fgcc, "}\n")
	fmt.Fprintf(fgcc, "\n")
}

658 659
// 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
660 661 662 663
// 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) {
664
	fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
	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")
683 684 685 686
	if t := n.FuncType.Result; t != nil {
		fmt.Fprintf(fgcc, "\t%s r;\n", t.C.String())
	}
	fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
687 688
	fmt.Fprintf(fgcc, "\t")
	if t := n.FuncType.Result; t != nil {
689
		fmt.Fprintf(fgcc, "r = ")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
690 691 692 693 694 695
		// Cast to void* to avoid warnings due to omitted qualifiers.
		if c := t.C.String(); c[len(c)-1] == '*' {
			fmt.Fprintf(fgcc, "(void*)")
		}
	}
	fmt.Fprintf(fgcc, "%s(", n.C)
696
	for i := range n.FuncType.Params {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
697 698 699 700 701 702
		if i > 0 {
			fmt.Fprintf(fgcc, ", ")
		}
		fmt.Fprintf(fgcc, "p%d", i)
	}
	fmt.Fprintf(fgcc, ");\n")
703 704 705 706 707 708 709 710 711 712
	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*)")
		}
		fmt.Fprintf(fgcc, "r;\n")
	}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
713 714 715 716
	fmt.Fprintf(fgcc, "}\n")
	fmt.Fprintf(fgcc, "\n")
}

717
// packedAttribute returns host compiler struct attribute that will be
718 719
// used to match gc's struct layout. For example, on 386 Windows,
// gcc wants to 8-align int64s, but gc does not.
720
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
721
// and https://golang.org/issue/5603.
722 723
func (p *Package) packedAttribute() string {
	s := "__attribute__((__packed__"
724
	if !p.GccIsClang && (goarch == "amd64" || goarch == "386") {
725 726 727 728 729
		s += ", __gcc_struct__"
	}
	return s + "))"
}

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

	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
736
	fmt.Fprintf(fgcc, "#include <stdlib.h>\n")
737
	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
738

739 740 741
	fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n")
	fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
	fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
742
	fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
743
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
744

Russ Cox's avatar
Russ Cox committed
745
	for _, exp := range p.ExpFunc {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
746 747
		fn := exp.Func

748
		// Construct a gcc struct matching the gc argument and
749
		// result frame. The gcc struct will be compiled with
750 751
		// __attribute__((packed)) so all padding must be accounted
		// for explicitly.
Russ Cox's avatar
Russ Cox committed
752
		ctype := "struct {\n"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
753 754 755 756
		off := int64(0)
		npad := 0
		if fn.Recv != nil {
			t := p.cgoType(fn.Recv.List[0].Type)
Russ Cox's avatar
Russ Cox committed
757
			ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
758 759 760 761
			off += t.Size
		}
		fntype := fn.Type
		forFieldList(fntype.Params,
762
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
763 764 765
				t := p.cgoType(atype)
				if off%t.Align != 0 {
					pad := t.Align - off%t.Align
Russ Cox's avatar
Russ Cox committed
766
					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
767 768 769
					off += pad
					npad++
				}
Russ Cox's avatar
Russ Cox committed
770
				ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
771 772 773 774
				off += t.Size
			})
		if off%p.PtrSize != 0 {
			pad := p.PtrSize - off%p.PtrSize
Russ Cox's avatar
Russ Cox committed
775
			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
776 777 778 779
			off += pad
			npad++
		}
		forFieldList(fntype.Results,
780
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
781 782 783
				t := p.cgoType(atype)
				if off%t.Align != 0 {
					pad := t.Align - off%t.Align
784
					ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
785 786 787
					off += pad
					npad++
				}
Russ Cox's avatar
Russ Cox committed
788
				ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
789 790 791 792
				off += t.Size
			})
		if off%p.PtrSize != 0 {
			pad := p.PtrSize - off%p.PtrSize
Russ Cox's avatar
Russ Cox committed
793
			ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
794 795 796
			off += pad
			npad++
		}
Russ Cox's avatar
Russ Cox committed
797 798
		if ctype == "struct {\n" {
			ctype += "\t\tchar unused;\n" // avoid empty struct
Ian Lance Taylor's avatar
Ian Lance Taylor committed
799
		}
Russ Cox's avatar
Russ Cox committed
800
		ctype += "\t}"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
801 802 803 804 805 806 807

		// 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
808
			gccResult = p.cgoType(fntype.Results.List[0].Type).C.String()
Ian Lance Taylor's avatar
Ian Lance Taylor committed
809 810 811 812
		} else {
			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
			forFieldList(fntype.Results,
813 814 815 816 817 818
				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
819 820 821 822 823 824 825 826
				})
			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
827
			s += p.cgoType(fn.Recv.List[0].Type).C.String()
Ian Lance Taylor's avatar
Ian Lance Taylor committed
828 829 830
			s += " recv"
		}
		forFieldList(fntype.Params,
831
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
832 833 834 835 836 837
				if i > 0 || fn.Recv != nil {
					s += ", "
				}
				s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
			})
		s += ")"
838 839 840 841

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

844
		fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName)
845
		fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
846 847
		fmt.Fprintf(fgcc, "\n%s\n", s)
		fmt.Fprintf(fgcc, "{\n")
848
		fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
849
		fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
Ian Lance Taylor's avatar
Ian Lance Taylor committed
850 851 852 853 854 855 856
		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,
857
			func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
858 859
				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
			})
860
		fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
861
		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
862
		fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
863
		fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
864 865 866 867 868
		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,
869
					func(i int, aname string, atype ast.Expr) {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
870 871 872 873 874 875 876
						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
					})
				fmt.Fprintf(fgcc, "\treturn r;\n")
			}
		}
		fmt.Fprintf(fgcc, "}\n")

877 878
		// Build the wrapper function compiled by cmd/compile.
		goname := "_cgoexpwrap" + cPrefix + "_"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
879
		if fn.Recv != nil {
880
			goname += fn.Recv.List[0].Names[0].Name + "_"
Ian Lance Taylor's avatar
Ian Lance Taylor committed
881
		}
882
		goname += exp.Func.Name.Name
883
		fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName)
884 885 886
		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
887
		fmt.Fprintf(fgo2, "//go:norace\n")  // must not have race detector calls inserted
888
		fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32, ctxt uintptr) {\n", cPrefix, exp.ExpName)
889 890
		fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
		// The indirect here is converting from a Go function pointer to a C function pointer.
891
		fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt);\n")
892
		fmt.Fprintf(fgo2, "}\n")
Ian Lance Taylor's avatar
Ian Lance Taylor committed
893

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

896 897 898 899 900 901
		// 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
902
		if fn.Recv != nil {
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
			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,
920
				func(i int, aname string, atype ast.Expr) {
921 922 923 924 925
					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
926
				})
927 928 929 930
			fmt.Fprint(fgo2, ")")
		}
		fmt.Fprint(fgo2, " {\n")
		if gccResult == "void" {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
931
			fmt.Fprint(fgo2, "\t")
932 933 934 935 936
		} else {
			// Verify that any results don't contain any
			// Go pointers.
			addedDefer := false
			forFieldList(fntype.Results,
937
				func(i int, aname string, atype ast.Expr) {
938 939 940 941 942 943
					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
944
					}
945
					fmt.Fprintf(fgo2, "\t\t_cgoCheckResult(r%d)\n", i)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
946
				})
947 948 949 950 951 952 953
			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
954
		}
955 956 957 958 959 960 961 962 963 964
		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
965
	}
966 967

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

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

974
	p.writeExportHeader(fgcch)
975

976 977
	fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n")
	fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n")
978

979
	fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog)
980
	fmt.Fprintf(fgcc, "%s\n", tsanProlog)
981

982 983 984 985 986 987 988
	for _, exp := range p.ExpFunc {
		fn := exp.Func
		fntype := fn.Type

		cdeclBuf := new(bytes.Buffer)
		resultCount := 0
		forFieldList(fntype.Results,
989
			func(i int, aname string, atype ast.Expr) { resultCount++ })
990 991 992 993 994
		switch resultCount {
		case 0:
			fmt.Fprintf(cdeclBuf, "void")
		case 1:
			forFieldList(fntype.Results,
995
				func(i int, aname string, atype ast.Expr) {
996 997 998 999 1000
					t := p.cgoType(atype)
					fmt.Fprintf(cdeclBuf, "%s", t.C)
				})
		default:
			// Declare a result struct.
1001
			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
1002
			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
1003
			forFieldList(fntype.Results,
1004
				func(i int, aname string, atype ast.Expr) {
1005
					t := p.cgoType(atype)
1006 1007 1008 1009 1010
					fmt.Fprintf(fgcch, "\t%s r%d;", t.C, i)
					if len(aname) > 0 {
						fmt.Fprintf(fgcch, " /* %s */", aname)
					}
					fmt.Fprint(fgcch, "\n")
1011 1012
				})
			fmt.Fprintf(fgcch, "};\n")
1013
			fmt.Fprintf(cdeclBuf, "struct %s_return", exp.ExpName)
1014 1015
		}

1016 1017 1018 1019 1020 1021 1022
		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())
		}
1023 1024
		// Function parameters.
		forFieldList(fntype.Params,
1025
			func(i int, aname string, atype ast.Expr) {
1026
				if i > 0 || fn.Recv != nil {
1027 1028 1029 1030 1031 1032
					fmt.Fprintf(cdeclBuf, ", ")
				}
				t := p.cgoType(atype)
				fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i)
			})
		fmt.Fprintf(cdeclBuf, ")")
1033 1034
		cParams := cdeclBuf.String()

1035 1036 1037 1038
		if len(exp.Doc) > 0 {
			fmt.Fprintf(fgcch, "\n%s", exp.Doc)
		}

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

1041 1042 1043 1044
		// 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.
1045
		goName := "Cgoexp_" + exp.ExpName
1046 1047
		fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
		fmt.Fprint(fgcc, "\n")
1048

1049
		fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
1050
		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
1051 1052 1053
		if resultCount > 0 {
			fmt.Fprintf(fgcc, "\t%s r;\n", cRet)
		}
1054 1055
		fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n")
		fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n")
1056
		fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
1057 1058
		fmt.Fprint(fgcc, "\t")
		if resultCount > 0 {
1059
			fmt.Fprint(fgcc, "r = ")
1060 1061 1062 1063 1064 1065
		}
		fmt.Fprintf(fgcc, "%s(", goName)
		if fn.Recv != nil {
			fmt.Fprint(fgcc, "recv")
		}
		forFieldList(fntype.Params,
1066
			func(i int, aname string, atype ast.Expr) {
1067 1068 1069 1070 1071 1072
				if i > 0 || fn.Recv != nil {
					fmt.Fprintf(fgcc, ", ")
				}
				fmt.Fprintf(fgcc, "p%d", i)
			})
		fmt.Fprint(fgcc, ");\n")
1073 1074 1075 1076
		fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
		if resultCount > 0 {
			fmt.Fprint(fgcc, "\treturn r;\n")
		}
1077
		fmt.Fprint(fgcc, "}\n")
1078 1079

		// Dummy declaration for _cgo_main.c
1080 1081
		fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
		fmt.Fprint(fm, "\n")
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095

		// 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,
1096
			func(i int, aname string, atype ast.Expr) {
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
				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,
1107
				func(i int, aname string, atype ast.Expr) {
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
					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,
1127
			func(i int, aname string, atype ast.Expr) {
1128 1129 1130 1131 1132 1133 1134
				if i > 0 {
					fmt.Fprint(fgo2, ", ")
				}
				fmt.Fprintf(fgo2, "p%d", i)
			})
		fmt.Fprint(fgo2, ")\n")
		fmt.Fprint(fgo2, "}\n")
1135
	}
1136 1137

	fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
1138 1139
}

1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
// writeExportHeader writes out the start of the _cgo_export.h file.
func (p *Package) writeExportHeader(fgcch io.Writer) {
	fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n")
	pkg := *importPath
	if pkg == "" {
		pkg = p.PackagePath
	}
	fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg)

	fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments.  */\n\n")
	fmt.Fprintf(fgcch, "%s\n", p.Preamble)
	fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments.  */\n\n")

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

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
// Return the package prefix when using gccgo.
func (p *Package) gccgoSymbolPrefix() string {
	if !*gccgo {
		return ""
	}

	clean := func(r rune) rune {
		switch {
		case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
			'0' <= r && r <= '9':
			return r
		}
		return '_'
	}

	if *gccgopkgpath != "" {
		return strings.Map(clean, *gccgopkgpath)
	}
	if *gccgoprefix == "" && p.PackageName == "main" {
		return "main"
	}
	prefix := strings.Map(clean, *gccgoprefix)
	if prefix == "" {
		prefix = "go"
	}
	return prefix + "." + p.PackageName
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
1184
// Call a function for each entry in an ast.FieldList, passing the
1185 1186
// 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
1187 1188 1189 1190 1191 1192
	if fl == nil {
		return
	}
	i := 0
	for _, r := range fl.List {
		if r.Names == nil {
1193
			fn(i, "", r.Type)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1194 1195
			i++
		} else {
1196 1197
			for _, n := range r.Names {
				fn(i, n.Name, r.Type)
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1198 1199 1200 1201 1202 1203
				i++
			}
		}
	}
}

Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1204 1205 1206 1207
func c(repr string, args ...interface{}) *TypeRepr {
	return &TypeRepr{repr, args}
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
1208 1209
// Map predeclared Go types to Type.
var goTypes = map[string]*Type{
1210 1211
	"bool":       {Size: 1, Align: 1, C: c("GoUint8")},
	"byte":       {Size: 1, Align: 1, C: c("GoUint8")},
Russ Cox's avatar
Russ Cox committed
1212 1213
	"int":        {Size: 0, Align: 0, C: c("GoInt")},
	"uint":       {Size: 0, Align: 0, C: c("GoUint")},
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
	"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")},
	"float32":    {Size: 4, Align: 4, C: c("GoFloat32")},
	"float64":    {Size: 8, Align: 8, C: c("GoFloat64")},
1225 1226
	"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
1227 1228 1229
}

// Map an ast type to a Type.
Russ Cox's avatar
Russ Cox committed
1230
func (p *Package) cgoType(e ast.Expr) *Type {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1231 1232 1233
	switch t := e.(type) {
	case *ast.StarExpr:
		x := p.cgoType(t.X)
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1234
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1235 1236
	case *ast.ArrayType:
		if t.Len == nil {
1237 1238
			// 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
1239
		}
1240
		// Non-slice array types are not supported.
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1241
	case *ast.StructType:
1242
		// Not supported.
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1243
	case *ast.FuncType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1244
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1245
	case *ast.InterfaceType:
1246
		return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1247
	case *ast.MapType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1248
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1249
	case *ast.ChanType:
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1250
		return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1251 1252 1253
	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
1254
		for _, d := range p.Decl {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1255 1256 1257 1258 1259 1260 1261 1262 1263
			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
				}
1264
				if ts.Name.Name == t.Name {
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1265 1266 1267 1268
					return p.cgoType(ts.Type)
				}
			}
		}
Russ Cox's avatar
Russ Cox committed
1269 1270
		if def := typedef[t.Name]; def != nil {
			return def
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1271
		}
1272
		if t.Name == "uintptr" {
1273
			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1274
		}
1275
		if t.Name == "string" {
1276
			// The string data is 1 pointer + 1 (pointer-sized) int.
Russ Cox's avatar
Russ Cox committed
1277
			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1278
		}
1279 1280 1281
		if t.Name == "error" {
			return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
		}
1282
		if r, ok := goTypes[t.Name]; ok {
Russ Cox's avatar
Russ Cox committed
1283 1284 1285 1286 1287 1288 1289
			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
1290 1291 1292 1293 1294
			if r.Align > p.PtrSize {
				r.Align = p.PtrSize
			}
			return r
		}
1295
		error_(e.Pos(), "unrecognized Go type %s", t.Name)
Russ Cox's avatar
Russ Cox committed
1296
		return &Type{Size: 4, Align: 4, C: c("int")}
1297 1298 1299
	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
1300
			return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")}
1301
		}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1302
	}
Russ Cox's avatar
Russ Cox committed
1303
	error_(e.Pos(), "Go type not supported in export: %s", gofmt(e))
Gustavo Niemeyer's avatar
Gustavo Niemeyer committed
1304
	return &Type{Size: 4, Align: 4, C: c("int")}
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1305 1306
}

Russ Cox's avatar
Russ Cox committed
1307
const gccProlog = `
1308
#line 1 "cgo-gcc-prolog"
1309 1310 1311 1312 1313
/*
  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
1314 1315
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];

1316
/* Check at compile time that the sizes we use match our expectations. */
Russ Cox's avatar
Russ Cox committed
1317 1318 1319 1320 1321 1322 1323 1324 1325
#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
1326

1327
extern char* _cgo_topofstack(void);
1328

Russ Cox's avatar
Russ Cox committed
1329 1330
#include <errno.h>
#include <string.h>
Russ Cox's avatar
Russ Cox committed
1331 1332
`

1333
// Prologue defining TSAN functions in C.
1334
const noTsanProlog = `
1335
#define CGO_NO_SANITIZE_THREAD
1336 1337
#define _cgo_tsan_acquire()
#define _cgo_tsan_release()
1338
`
1339

1340
// This must match the TSAN code in runtime/cgo/libcgo.h.
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
// 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.
1362
const yesTsanProlog = `
1363
#line 1 "cgo-tsan-prolog"
1364 1365
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))

1366 1367 1368 1369 1370
long long _cgo_sync __attribute__ ((common));

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

1371
__attribute__ ((unused))
1372 1373 1374 1375
static void _cgo_tsan_acquire() {
	__tsan_acquire(&_cgo_sync);
}

1376
__attribute__ ((unused))
1377 1378 1379 1380 1381
static void _cgo_tsan_release() {
	__tsan_release(&_cgo_sync);
}
`

1382 1383 1384
// Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc.
var tsanProlog = noTsanProlog

Russ Cox's avatar
Russ Cox committed
1385
const builtinProlog = `
1386
#line 1 "cgo-builtin-prolog"
1387
#include <stddef.h> /* for ptrdiff_t and size_t below */
1388

1389
/* Define intgo when compiling with GCC.  */
1390
typedef ptrdiff_t intgo;
1391 1392 1393

typedef struct { char *p; intgo n; } _GoString_;
typedef struct { char *p; intgo n; intgo c; } _GoBytes_;
Russ Cox's avatar
Russ Cox committed
1394
_GoString_ GoString(char *p);
1395 1396
_GoString_ GoStringN(char *p, int l);
_GoBytes_ GoBytes(void *p, int n);
Russ Cox's avatar
Russ Cox committed
1397
char *CString(_GoString_);
James Bardin's avatar
James Bardin committed
1398
void *CBytes(_GoBytes_);
1399
void *_CMalloc(size_t);
Russ Cox's avatar
Russ Cox committed
1400 1401
`

1402
const goProlog = `
1403 1404
//go:linkname _cgo_runtime_cgocall runtime.cgocall
func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
1405 1406

//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
1407
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
1408 1409

//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
1410
func _cgoCheckPointer(interface{}, ...interface{})
1411 1412 1413

//go:linkname _cgoCheckResult runtime.cgoCheckResult
func _cgoCheckResult(interface{})
1414 1415
`

1416
const gccgoGoProlog = `
1417
func _cgoCheckPointer(interface{}, ...interface{})
1418 1419 1420 1421

func _cgoCheckResult(interface{})
`

1422
const goStringDef = `
1423 1424 1425
//go:linkname _cgo_runtime_gostring runtime.gostring
func _cgo_runtime_gostring(*_Ctype_char) string

1426 1427
func _Cfunc_GoString(p *_Ctype_char) string {
	return _cgo_runtime_gostring(p)
Russ Cox's avatar
Russ Cox committed
1428
}
1429
`
Russ Cox's avatar
Russ Cox committed
1430

1431
const goStringNDef = `
1432 1433 1434
//go:linkname _cgo_runtime_gostringn runtime.gostringn
func _cgo_runtime_gostringn(*_Ctype_char, int) string

1435 1436
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
	return _cgo_runtime_gostringn(p, int(l))
Eric Clark's avatar
Eric Clark committed
1437
}
1438
`
Eric Clark's avatar
Eric Clark committed
1439

1440
const goBytesDef = `
1441 1442 1443
//go:linkname _cgo_runtime_gobytes runtime.gobytes
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte

1444 1445
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
	return _cgo_runtime_gobytes(p, int(l))
Russ Cox's avatar
Russ Cox committed
1446
}
1447
`
Russ Cox's avatar
Russ Cox committed
1448

1449 1450
const cStringDef = `
func _Cfunc_CString(s string) *_Ctype_char {
1451
	p := _cgo_cmalloc(uint64(len(s)+1))
1452 1453 1454 1455
	pp := (*[1<<30]byte)(p)
	copy(pp[:], s)
	pp[len(s)] = 0
	return (*_Ctype_char)(p)
Russ Cox's avatar
Russ Cox committed
1456
}
1457
`
1458

James Bardin's avatar
James Bardin committed
1459 1460
const cBytesDef = `
func _Cfunc_CBytes(b []byte) unsafe.Pointer {
1461
	p := _cgo_cmalloc(uint64(len(b)))
James Bardin's avatar
James Bardin committed
1462 1463 1464 1465 1466 1467
	pp := (*[1<<30]byte)(p)
	copy(pp[:], b)
	return p
}
`

1468 1469
const cMallocDef = `
func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer {
1470
	return _cgo_cmalloc(uint64(n))
1471
}
Russ Cox's avatar
Russ Cox committed
1472
`
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1473

1474 1475 1476 1477 1478
var builtinDefs = map[string]string{
	"GoString":  goStringDef,
	"GoStringN": goStringNDef,
	"GoBytes":   goBytesDef,
	"CString":   cStringDef,
James Bardin's avatar
James Bardin committed
1479
	"CBytes":    cBytesDef,
1480 1481 1482
	"_CMalloc":  cMallocDef,
}

1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
// 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)

1494 1495 1496
//go:linkname runtime_throw runtime.throw
func runtime_throw(string)

1497 1498 1499
//go:cgo_unsafe_args
func _cgo_cmalloc(p0 uint64) (r1 unsafe.Pointer) {
	_cgo_runtime_cgocall(_cgoPREFIX_Cfunc__Cmalloc, uintptr(unsafe.Pointer(&p0)))
1500 1501 1502
	if r1 == nil {
		runtime_throw("runtime: C malloc failed")
	}
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
	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();
}
`

1533
func (p *Package) cPrologGccgo() string {
1534 1535
	return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
		"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
1536 1537
}

1538
const cPrologGccgo = `
1539
#line 1 "cgo-c-prolog-gccgo"
1540
#include <stdint.h>
1541
#include <stdlib.h>
1542 1543
#include <string.h>

1544
typedef unsigned char byte;
1545
typedef intptr_t intgo;
1546

1547 1548
struct __go_string {
	const unsigned char *__data;
1549
	intgo __length;
1550 1551 1552 1553
};

typedef struct __go_open_array {
	void* __values;
1554 1555
	intgo __count;
	intgo __capacity;
1556 1557
} Slice;

1558
struct __go_string __go_byte_array_to_string(const void* p, intgo len);
1559 1560
struct __go_open_array __go_string_to_byte_array (struct __go_string str);

1561
const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) {
1562 1563 1564 1565
	char *p = malloc(s.__length+1);
	memmove(p, s.__data, s.__length);
	p[s.__length] = 0;
	return p;
1566 1567
}

James Bardin's avatar
James Bardin committed
1568 1569
void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) {
	char *p = malloc(b.__count);
1570
	memmove(p, b.__values, b.__count);
James Bardin's avatar
James Bardin committed
1571 1572 1573
	return p;
}

1574
struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) {
1575
	intgo len = (p != NULL) ? strlen(p) : 0;
1576
	return __go_byte_array_to_string(p, len);
1577 1578
}

1579
struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) {
1580 1581 1582
	return __go_byte_array_to_string(p, n);
}

1583
Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) {
1584
	struct __go_string s = { (const unsigned char *)p, n };
1585 1586
	return __go_string_to_byte_array(s);
}
1587

1588 1589
extern void runtime_throw(const char *);
void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
1590
        void *p = malloc(n);
Russ Cox's avatar
Russ Cox committed
1591 1592
        if(p == NULL && n == 0)
                p = malloc(1);
1593 1594 1595 1596
        if(p == NULL)
                runtime_throw("runtime: C malloc failed");
        return p;
}
1597 1598 1599 1600 1601 1602 1603

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

1604
extern void runtimeCgoCheckPointer(Eface, Slice)
1605 1606 1607
	__asm__("runtime.cgoCheckPointer")
	__attribute__((weak));

1608
extern void localCgoCheckPointer(Eface, Slice)
1609 1610
	__asm__("GCCGOSYMBOLPREF._cgoCheckPointer");

1611
void localCgoCheckPointer(Eface ptr, Slice args) {
1612
	if(runtimeCgoCheckPointer) {
1613
		runtimeCgoCheckPointer(ptr, args);
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
	}
}

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

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

void localCgoCheckResult(Eface val) {
	if(runtimeCgoCheckResult) {
		runtimeCgoCheckResult(val);
	}
}
1629 1630
`

Russ Cox's avatar
Russ Cox committed
1631 1632 1633 1634
func (p *Package) gccExportHeaderProlog() string {
	return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1)
}

Ian Lance Taylor's avatar
Ian Lance Taylor committed
1635
const gccExportHeaderProlog = `
1636
/* Start of boilerplate cgo prologue.  */
1637
#line 1 "cgo-gcc-export-header-prolog"
1638

1639 1640 1641
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

1642 1643 1644 1645 1646 1647 1648 1649
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;
Russ Cox's avatar
Russ Cox committed
1650 1651
typedef GoIntGOINTBITS GoInt;
typedef GoUintGOINTBITS GoUint;
1652 1653 1654
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
1655 1656
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1657

1658 1659 1660 1661
/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
1662 1663
typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];

1664
typedef struct { const char *p; GoInt n; } GoString;
Ian Lance Taylor's avatar
Ian Lance Taylor committed
1665 1666 1667
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
1668
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
1669

1670 1671
#endif

1672
/* End of boilerplate cgo prologue.  */
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683

#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
1684
`
1685 1686 1687 1688 1689 1690

// 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 = `
1691
#line 1 "cgo-gccgo-export-file-prolog"
1692 1693 1694 1695 1696 1697 1698 1699
extern _Bool runtime_iscgo __attribute__ ((weak));

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

1700
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done() __attribute__ ((weak));
1701
`