github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/cgo/out.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "debug/elf" 10 "debug/macho" 11 "debug/pe" 12 "fmt" 13 "go/ast" 14 "go/printer" 15 "go/token" 16 "io" 17 "os" 18 "sort" 19 "strings" 20 ) 21 22 var ( 23 conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8} 24 noSourceConf = printer.Config{Tabwidth: 8} 25 ) 26 27 // writeDefs creates output files to be compiled by gc and gcc. 28 func (p *Package) writeDefs() { 29 var fgo2, fc io.Writer 30 f := creat(*objDir + "_cgo_gotypes.go") 31 defer f.Close() 32 fgo2 = f 33 if *gccgo { 34 f := creat(*objDir + "_cgo_defun.c") 35 defer f.Close() 36 fc = f 37 } 38 fm := creat(*objDir + "_cgo_main.c") 39 40 var gccgoInit bytes.Buffer 41 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 fflg.Close() 52 53 // Write C main file for using gcc to resolve imports. 54 fmt.Fprintf(fm, "int main() { return 0; }\n") 55 if *importRuntimeCgo { 56 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n") 57 fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; }\n") 58 fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n") 59 fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n") 60 } else { 61 // If we're not importing runtime/cgo, we *are* runtime/cgo, 62 // which provides these functions. We just need a prototype. 63 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n") 64 fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done();\n") 65 fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n") 66 } 67 fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") 68 fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") 69 fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n") 70 71 // Write second Go output: definitions of _C_xxx. 72 // In a separate file so that the import of "unsafe" does not 73 // pollute the original file. 74 fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") 75 fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) 76 fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") 77 if !*gccgo && *importRuntimeCgo { 78 fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") 79 } 80 if *importSyscall { 81 fmt.Fprintf(fgo2, "import \"syscall\"\n\n") 82 fmt.Fprintf(fgo2, "var _ syscall.Errno\n") 83 } 84 fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") 85 86 if !*gccgo { 87 fmt.Fprintf(fgo2, "//go:linkname _Cgo_always_false runtime.cgoAlwaysFalse\n") 88 fmt.Fprintf(fgo2, "var _Cgo_always_false bool\n") 89 fmt.Fprintf(fgo2, "//go:linkname _Cgo_use runtime.cgoUse\n") 90 fmt.Fprintf(fgo2, "func _Cgo_use(interface{})\n") 91 } 92 93 typedefNames := make([]string, 0, len(typedef)) 94 for name := range typedef { 95 typedefNames = append(typedefNames, name) 96 } 97 sort.Strings(typedefNames) 98 for _, name := range typedefNames { 99 def := typedef[name] 100 fmt.Fprintf(fgo2, "type %s ", name) 101 // We don't have source info for these types, so write them out without source info. 102 // Otherwise types would look like: 103 // 104 // type _Ctype_struct_cb struct { 105 // //line :1 106 // on_test *[0]byte 107 // //line :1 108 // } 109 // 110 // Which is not useful. Moreover we never override source info, 111 // so subsequent source code uses the same source info. 112 // Moreover, empty file name makes compile emit no source debug info at all. 113 noSourceConf.Fprint(fgo2, fset, def.Go) 114 fmt.Fprintf(fgo2, "\n\n") 115 } 116 if *gccgo { 117 fmt.Fprintf(fgo2, "type _Ctype_void byte\n") 118 } else { 119 fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n") 120 } 121 122 if *gccgo { 123 fmt.Fprint(fgo2, gccgoGoProlog) 124 fmt.Fprint(fc, p.cPrologGccgo()) 125 } else { 126 fmt.Fprint(fgo2, goProlog) 127 } 128 129 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 130 131 cVars := make(map[string]bool) 132 for _, key := range nameKeys(p.Name) { 133 n := p.Name[key] 134 if !n.IsVar() { 135 continue 136 } 137 138 if !cVars[n.C] { 139 if *gccgo { 140 fmt.Fprintf(fc, "extern byte *%s;\n", n.C) 141 } else { 142 fmt.Fprintf(fm, "extern char %s[];\n", n.C) 143 fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) 144 fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C) 145 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C) 146 fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C) 147 } 148 cVars[n.C] = true 149 } 150 151 var node ast.Node 152 if n.Kind == "var" { 153 node = &ast.StarExpr{X: n.Type.Go} 154 } else if n.Kind == "fpvar" { 155 node = n.Type.Go 156 } else { 157 panic(fmt.Errorf("invalid var kind %q", n.Kind)) 158 } 159 if *gccgo { 160 fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) 161 fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C) 162 fmt.Fprintf(fc, "\n") 163 } 164 165 fmt.Fprintf(fgo2, "var %s ", n.Mangle) 166 conf.Fprint(fgo2, fset, node) 167 if !*gccgo { 168 fmt.Fprintf(fgo2, " = (") 169 conf.Fprint(fgo2, fset, node) 170 fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C) 171 } 172 fmt.Fprintf(fgo2, "\n") 173 } 174 if *gccgo { 175 fmt.Fprintf(fc, "\n") 176 } 177 178 for _, key := range nameKeys(p.Name) { 179 n := p.Name[key] 180 if n.Const != "" { 181 fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const) 182 } 183 } 184 fmt.Fprintf(fgo2, "\n") 185 186 callsMalloc := false 187 for _, key := range nameKeys(p.Name) { 188 n := p.Name[key] 189 if n.FuncType != nil { 190 p.writeDefsFunc(fgo2, n, &callsMalloc) 191 } 192 } 193 194 fgcc := creat(*objDir + "_cgo_export.c") 195 fgcch := creat(*objDir + "_cgo_export.h") 196 if *gccgo { 197 p.writeGccgoExports(fgo2, fm, fgcc, fgcch) 198 } else { 199 p.writeExports(fgo2, fm, fgcc, fgcch) 200 } 201 202 if callsMalloc && !*gccgo { 203 fmt.Fprint(fgo2, strings.Replace(cMallocDefGo, "PREFIX", cPrefix, -1)) 204 fmt.Fprint(fgcc, strings.Replace(strings.Replace(cMallocDefC, "PREFIX", cPrefix, -1), "PACKED", p.packedAttribute(), -1)) 205 } 206 207 if err := fgcc.Close(); err != nil { 208 fatalf("%s", err) 209 } 210 if err := fgcch.Close(); err != nil { 211 fatalf("%s", err) 212 } 213 214 if *exportHeader != "" && len(p.ExpFunc) > 0 { 215 fexp := creat(*exportHeader) 216 fgcch, err := os.Open(*objDir + "_cgo_export.h") 217 if err != nil { 218 fatalf("%s", err) 219 } 220 _, err = io.Copy(fexp, fgcch) 221 if err != nil { 222 fatalf("%s", err) 223 } 224 if err = fexp.Close(); err != nil { 225 fatalf("%s", err) 226 } 227 } 228 229 init := gccgoInit.String() 230 if init != "" { 231 fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));") 232 fmt.Fprintln(fc, "static void init(void) {") 233 fmt.Fprint(fc, init) 234 fmt.Fprintln(fc, "}") 235 } 236 } 237 238 func dynimport(obj string) { 239 stdout := os.Stdout 240 if *dynout != "" { 241 f, err := os.Create(*dynout) 242 if err != nil { 243 fatalf("%s", err) 244 } 245 stdout = f 246 } 247 248 fmt.Fprintf(stdout, "package %s\n", *dynpackage) 249 250 if f, err := elf.Open(obj); err == nil { 251 if *dynlinker { 252 // Emit the cgo_dynamic_linker line. 253 if sec := f.Section(".interp"); sec != nil { 254 if data, err := sec.Data(); err == nil && len(data) > 1 { 255 // skip trailing \0 in data 256 fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1])) 257 } 258 } 259 } 260 sym, err := f.ImportedSymbols() 261 if err != nil { 262 fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) 263 } 264 for _, s := range sym { 265 targ := s.Name 266 if s.Version != "" { 267 targ += "#" + s.Version 268 } 269 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) 270 } 271 lib, err := f.ImportedLibraries() 272 if err != nil { 273 fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) 274 } 275 for _, l := range lib { 276 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 277 } 278 return 279 } 280 281 if f, err := macho.Open(obj); err == nil { 282 sym, err := f.ImportedSymbols() 283 if err != nil { 284 fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) 285 } 286 for _, s := range sym { 287 if len(s) > 0 && s[0] == '_' { 288 s = s[1:] 289 } 290 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "") 291 } 292 lib, err := f.ImportedLibraries() 293 if err != nil { 294 fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) 295 } 296 for _, l := range lib { 297 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 298 } 299 return 300 } 301 302 if f, err := pe.Open(obj); err == nil { 303 sym, err := f.ImportedSymbols() 304 if err != nil { 305 fatalf("cannot load imported symbols from PE file %s: %v", obj, err) 306 } 307 for _, s := range sym { 308 ss := strings.Split(s, ":") 309 name := strings.Split(ss[0], "@")[0] 310 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) 311 } 312 return 313 } 314 315 fatalf("cannot parse %s as ELF, Mach-O or PE", obj) 316 } 317 318 // Construct a gcc struct matching the gc argument frame. 319 // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. 320 // These assumptions are checked by the gccProlog. 321 // Also assumes that gc convention is to word-align the 322 // input and output parameters. 323 func (p *Package) structType(n *Name) (string, int64) { 324 var buf bytes.Buffer 325 fmt.Fprint(&buf, "struct {\n") 326 off := int64(0) 327 for i, t := range n.FuncType.Params { 328 if off%t.Align != 0 { 329 pad := t.Align - off%t.Align 330 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 331 off += pad 332 } 333 c := t.Typedef 334 if c == "" { 335 c = t.C.String() 336 } 337 fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i) 338 off += t.Size 339 } 340 if off%p.PtrSize != 0 { 341 pad := p.PtrSize - off%p.PtrSize 342 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 343 off += pad 344 } 345 if t := n.FuncType.Result; t != nil { 346 if off%t.Align != 0 { 347 pad := t.Align - off%t.Align 348 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 349 off += pad 350 } 351 qual := "" 352 if c := t.C.String(); c[len(c)-1] == '*' { 353 qual = "const " 354 } 355 fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) 356 off += t.Size 357 } 358 if off%p.PtrSize != 0 { 359 pad := p.PtrSize - off%p.PtrSize 360 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 361 off += pad 362 } 363 if off == 0 { 364 fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct 365 } 366 fmt.Fprintf(&buf, "\t}") 367 return buf.String(), off 368 } 369 370 func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name, callsMalloc *bool) { 371 name := n.Go 372 gtype := n.FuncType.Go 373 void := gtype.Results == nil || len(gtype.Results.List) == 0 374 if n.AddError { 375 // Add "error" to return type list. 376 // Type list is known to be 0 or 1 element - it's a C function. 377 err := &ast.Field{Type: ast.NewIdent("error")} 378 l := gtype.Results.List 379 if len(l) == 0 { 380 l = []*ast.Field{err} 381 } else { 382 l = []*ast.Field{l[0], err} 383 } 384 t := new(ast.FuncType) 385 *t = *gtype 386 t.Results = &ast.FieldList{List: l} 387 gtype = t 388 } 389 390 // Go func declaration. 391 d := &ast.FuncDecl{ 392 Name: ast.NewIdent(n.Mangle), 393 Type: gtype, 394 } 395 396 // Builtins defined in the C prolog. 397 inProlog := builtinDefs[name] != "" 398 cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) 399 paramnames := []string(nil) 400 for i, param := range d.Type.Params.List { 401 paramName := fmt.Sprintf("p%d", i) 402 param.Names = []*ast.Ident{ast.NewIdent(paramName)} 403 paramnames = append(paramnames, paramName) 404 } 405 406 if *gccgo { 407 // Gccgo style hooks. 408 fmt.Fprint(fgo2, "\n") 409 conf.Fprint(fgo2, fset, d) 410 fmt.Fprint(fgo2, " {\n") 411 if !inProlog { 412 fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n") 413 fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n") 414 } 415 if n.AddError { 416 fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n") 417 } 418 fmt.Fprint(fgo2, "\t") 419 if !void { 420 fmt.Fprint(fgo2, "r := ") 421 } 422 fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", ")) 423 424 if n.AddError { 425 fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n") 426 fmt.Fprint(fgo2, "\tif e != 0 {\n") 427 fmt.Fprint(fgo2, "\t\treturn ") 428 if !void { 429 fmt.Fprint(fgo2, "r, ") 430 } 431 fmt.Fprint(fgo2, "e\n") 432 fmt.Fprint(fgo2, "\t}\n") 433 fmt.Fprint(fgo2, "\treturn ") 434 if !void { 435 fmt.Fprint(fgo2, "r, ") 436 } 437 fmt.Fprint(fgo2, "nil\n") 438 } else if !void { 439 fmt.Fprint(fgo2, "\treturn r\n") 440 } 441 442 fmt.Fprint(fgo2, "}\n") 443 444 // declare the C function. 445 fmt.Fprintf(fgo2, "//extern %s\n", cname) 446 d.Name = ast.NewIdent(cname) 447 if n.AddError { 448 l := d.Type.Results.List 449 d.Type.Results.List = l[:len(l)-1] 450 } 451 conf.Fprint(fgo2, fset, d) 452 fmt.Fprint(fgo2, "\n") 453 454 return 455 } 456 457 if inProlog { 458 fmt.Fprint(fgo2, builtinDefs[name]) 459 if strings.Contains(builtinDefs[name], "_cgo_cmalloc") { 460 *callsMalloc = true 461 } 462 return 463 } 464 465 // Wrapper calls into gcc, passing a pointer to the argument frame. 466 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname) 467 fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname) 468 fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname) 469 fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname) 470 471 nret := 0 472 if !void { 473 d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")} 474 nret = 1 475 } 476 if n.AddError { 477 d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")} 478 } 479 480 fmt.Fprint(fgo2, "\n") 481 fmt.Fprint(fgo2, "//go:cgo_unsafe_args\n") 482 conf.Fprint(fgo2, fset, d) 483 fmt.Fprint(fgo2, " {\n") 484 485 // NOTE: Using uintptr to hide from escape analysis. 486 arg := "0" 487 if len(paramnames) > 0 { 488 arg = "uintptr(unsafe.Pointer(&p0))" 489 } else if !void { 490 arg = "uintptr(unsafe.Pointer(&r1))" 491 } 492 493 prefix := "" 494 if n.AddError { 495 prefix = "errno := " 496 } 497 fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall(%s, %s)\n", prefix, cname, arg) 498 if n.AddError { 499 fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") 500 } 501 fmt.Fprintf(fgo2, "\tif _Cgo_always_false {\n") 502 for i := range d.Type.Params.List { 503 fmt.Fprintf(fgo2, "\t\t_Cgo_use(p%d)\n", i) 504 } 505 fmt.Fprintf(fgo2, "\t}\n") 506 fmt.Fprintf(fgo2, "\treturn\n") 507 fmt.Fprintf(fgo2, "}\n") 508 } 509 510 // writeOutput creates stubs for a specific source file to be compiled by gc 511 func (p *Package) writeOutput(f *File, srcfile string) { 512 base := srcfile 513 if strings.HasSuffix(base, ".go") { 514 base = base[0 : len(base)-3] 515 } 516 base = strings.Map(slashToUnderscore, base) 517 fgo1 := creat(*objDir + base + ".cgo1.go") 518 fgcc := creat(*objDir + base + ".cgo2.c") 519 520 p.GoFiles = append(p.GoFiles, base+".cgo1.go") 521 p.GccFiles = append(p.GccFiles, base+".cgo2.c") 522 523 // Write Go output: Go input with rewrites of C.xxx to _C_xxx. 524 fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") 525 conf.Fprint(fgo1, fset, f.AST) 526 527 // While we process the vars and funcs, also write gcc output. 528 // Gcc output starts with the preamble. 529 fmt.Fprintf(fgcc, "%s\n", f.Preamble) 530 fmt.Fprintf(fgcc, "%s\n", gccProlog) 531 fmt.Fprintf(fgcc, "%s\n", tsanProlog) 532 533 for _, key := range nameKeys(f.Name) { 534 n := f.Name[key] 535 if n.FuncType != nil { 536 p.writeOutputFunc(fgcc, n) 537 } 538 } 539 540 fgo1.Close() 541 fgcc.Close() 542 } 543 544 // fixGo converts the internal Name.Go field into the name we should show 545 // to users in error messages. There's only one for now: on input we rewrite 546 // C.malloc into C._CMalloc, so change it back here. 547 func fixGo(name string) string { 548 if name == "_CMalloc" { 549 return "malloc" 550 } 551 return name 552 } 553 554 var isBuiltin = map[string]bool{ 555 "_Cfunc_CString": true, 556 "_Cfunc_CBytes": true, 557 "_Cfunc_GoString": true, 558 "_Cfunc_GoStringN": true, 559 "_Cfunc_GoBytes": true, 560 "_Cfunc__CMalloc": true, 561 } 562 563 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { 564 name := n.Mangle 565 if isBuiltin[name] || p.Written[name] { 566 // The builtins are already defined in the C prolog, and we don't 567 // want to duplicate function definitions we've already done. 568 return 569 } 570 p.Written[name] = true 571 572 if *gccgo { 573 p.writeGccgoOutputFunc(fgcc, n) 574 return 575 } 576 577 ctype, _ := p.structType(n) 578 579 // Gcc wrapper unpacks the C argument struct 580 // and calls the actual C function. 581 fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n") 582 if n.AddError { 583 fmt.Fprintf(fgcc, "int\n") 584 } else { 585 fmt.Fprintf(fgcc, "void\n") 586 } 587 fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) 588 fmt.Fprintf(fgcc, "{\n") 589 if n.AddError { 590 fmt.Fprintf(fgcc, "\tint _cgo_errno;\n") 591 } 592 // We're trying to write a gcc struct that matches gc's layout. 593 // Use packed attribute to force no padding in this struct in case 594 // gcc has different packing requirements. 595 fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) 596 if n.FuncType.Result != nil { 597 // Save the stack top for use below. 598 fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") 599 } 600 tr := n.FuncType.Result 601 if tr != nil { 602 fmt.Fprintf(fgcc, "\t__typeof__(a->r) r;\n") 603 } 604 fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") 605 if n.AddError { 606 fmt.Fprintf(fgcc, "\terrno = 0;\n") 607 } 608 fmt.Fprintf(fgcc, "\t") 609 if tr != nil { 610 fmt.Fprintf(fgcc, "r = ") 611 if c := tr.C.String(); c[len(c)-1] == '*' { 612 fmt.Fprint(fgcc, "(__typeof__(a->r)) ") 613 } 614 } 615 fmt.Fprintf(fgcc, "%s(", n.C) 616 for i, t := range n.FuncType.Params { 617 if i > 0 { 618 fmt.Fprintf(fgcc, ", ") 619 } 620 // We know the type params are correct, because 621 // the Go equivalents had good type params. 622 // However, our version of the type omits the magic 623 // words const and volatile, which can provoke 624 // C compiler warnings. Silence them by casting 625 // all pointers to void*. (Eventually that will produce 626 // other warnings.) 627 if c := t.C.String(); c[len(c)-1] == '*' { 628 fmt.Fprintf(fgcc, "(void*)") 629 } 630 fmt.Fprintf(fgcc, "a->p%d", i) 631 } 632 fmt.Fprintf(fgcc, ");\n") 633 if n.AddError { 634 fmt.Fprintf(fgcc, "\t_cgo_errno = errno;\n") 635 } 636 fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n") 637 if n.FuncType.Result != nil { 638 // The cgo call may have caused a stack copy (via a callback). 639 // Adjust the return value pointer appropriately. 640 fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") 641 // Save the return value. 642 fmt.Fprintf(fgcc, "\ta->r = r;\n") 643 } 644 if n.AddError { 645 fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n") 646 } 647 fmt.Fprintf(fgcc, "}\n") 648 fmt.Fprintf(fgcc, "\n") 649 } 650 651 // Write out a wrapper for a function when using gccgo. This is a 652 // simple wrapper that just calls the real function. We only need a 653 // wrapper to support static functions in the prologue--without a 654 // wrapper, we can't refer to the function, since the reference is in 655 // a different file. 656 func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { 657 fmt.Fprintf(fgcc, "CGO_NO_SANITIZE_THREAD\n") 658 if t := n.FuncType.Result; t != nil { 659 fmt.Fprintf(fgcc, "%s\n", t.C.String()) 660 } else { 661 fmt.Fprintf(fgcc, "void\n") 662 } 663 fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle) 664 for i, t := range n.FuncType.Params { 665 if i > 0 { 666 fmt.Fprintf(fgcc, ", ") 667 } 668 c := t.Typedef 669 if c == "" { 670 c = t.C.String() 671 } 672 fmt.Fprintf(fgcc, "%s p%d", c, i) 673 } 674 fmt.Fprintf(fgcc, ")\n") 675 fmt.Fprintf(fgcc, "{\n") 676 if t := n.FuncType.Result; t != nil { 677 fmt.Fprintf(fgcc, "\t%s r;\n", t.C.String()) 678 } 679 fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") 680 fmt.Fprintf(fgcc, "\t") 681 if t := n.FuncType.Result; t != nil { 682 fmt.Fprintf(fgcc, "r = ") 683 // Cast to void* to avoid warnings due to omitted qualifiers. 684 if c := t.C.String(); c[len(c)-1] == '*' { 685 fmt.Fprintf(fgcc, "(void*)") 686 } 687 } 688 fmt.Fprintf(fgcc, "%s(", n.C) 689 for i, t := range n.FuncType.Params { 690 if i > 0 { 691 fmt.Fprintf(fgcc, ", ") 692 } 693 // Cast to void* to avoid warnings due to omitted qualifiers. 694 if c := t.C.String(); c[len(c)-1] == '*' { 695 fmt.Fprintf(fgcc, "(void*)") 696 } 697 fmt.Fprintf(fgcc, "p%d", i) 698 } 699 fmt.Fprintf(fgcc, ");\n") 700 fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n") 701 if t := n.FuncType.Result; t != nil { 702 fmt.Fprintf(fgcc, "\treturn ") 703 // Cast to void* to avoid warnings due to omitted qualifiers 704 // and explicit incompatible struct types. 705 if c := t.C.String(); c[len(c)-1] == '*' { 706 fmt.Fprintf(fgcc, "(void*)") 707 } 708 fmt.Fprintf(fgcc, "r;\n") 709 } 710 fmt.Fprintf(fgcc, "}\n") 711 fmt.Fprintf(fgcc, "\n") 712 } 713 714 // packedAttribute returns host compiler struct attribute that will be 715 // used to match gc's struct layout. For example, on 386 Windows, 716 // gcc wants to 8-align int64s, but gc does not. 717 // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, 718 // and https://golang.org/issue/5603. 719 func (p *Package) packedAttribute() string { 720 s := "__attribute__((__packed__" 721 if !p.GccIsClang && (goarch == "amd64" || goarch == "386") { 722 s += ", __gcc_struct__" 723 } 724 return s + "))" 725 } 726 727 // Write out the various stubs we need to support functions exported 728 // from Go so that they are callable from C. 729 func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { 730 p.writeExportHeader(fgcch) 731 732 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 733 fmt.Fprintf(fgcc, "#include <stdlib.h>\n") 734 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n") 735 736 fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n") 737 fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done();\n") 738 fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n") 739 fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);") 740 fmt.Fprintf(fgcc, "%s\n", tsanProlog) 741 742 for _, exp := range p.ExpFunc { 743 fn := exp.Func 744 745 // Construct a gcc struct matching the gc argument and 746 // result frame. The gcc struct will be compiled with 747 // __attribute__((packed)) so all padding must be accounted 748 // for explicitly. 749 ctype := "struct {\n" 750 off := int64(0) 751 npad := 0 752 if fn.Recv != nil { 753 t := p.cgoType(fn.Recv.List[0].Type) 754 ctype += fmt.Sprintf("\t\t%s recv;\n", t.C) 755 off += t.Size 756 } 757 fntype := fn.Type 758 forFieldList(fntype.Params, 759 func(i int, aname string, atype ast.Expr) { 760 t := p.cgoType(atype) 761 if off%t.Align != 0 { 762 pad := t.Align - off%t.Align 763 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 764 off += pad 765 npad++ 766 } 767 ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i) 768 off += t.Size 769 }) 770 if off%p.PtrSize != 0 { 771 pad := p.PtrSize - off%p.PtrSize 772 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 773 off += pad 774 npad++ 775 } 776 forFieldList(fntype.Results, 777 func(i int, aname string, atype ast.Expr) { 778 t := p.cgoType(atype) 779 if off%t.Align != 0 { 780 pad := t.Align - off%t.Align 781 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 782 off += pad 783 npad++ 784 } 785 ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i) 786 off += t.Size 787 }) 788 if off%p.PtrSize != 0 { 789 pad := p.PtrSize - off%p.PtrSize 790 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 791 off += pad 792 npad++ 793 } 794 if ctype == "struct {\n" { 795 ctype += "\t\tchar unused;\n" // avoid empty struct 796 } 797 ctype += "\t}" 798 799 // Get the return type of the wrapper function 800 // compiled by gcc. 801 gccResult := "" 802 if fntype.Results == nil || len(fntype.Results.List) == 0 { 803 gccResult = "void" 804 } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 805 gccResult = p.cgoType(fntype.Results.List[0].Type).C.String() 806 } else { 807 fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) 808 fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName) 809 forFieldList(fntype.Results, 810 func(i int, aname string, atype ast.Expr) { 811 fmt.Fprintf(fgcch, "\t%s r%d;", p.cgoType(atype).C, i) 812 if len(aname) > 0 { 813 fmt.Fprintf(fgcch, " /* %s */", aname) 814 } 815 fmt.Fprint(fgcch, "\n") 816 }) 817 fmt.Fprintf(fgcch, "};\n") 818 gccResult = "struct " + exp.ExpName + "_return" 819 } 820 821 // Build the wrapper function compiled by gcc. 822 s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) 823 if fn.Recv != nil { 824 s += p.cgoType(fn.Recv.List[0].Type).C.String() 825 s += " recv" 826 } 827 forFieldList(fntype.Params, 828 func(i int, aname string, atype ast.Expr) { 829 if i > 0 || fn.Recv != nil { 830 s += ", " 831 } 832 s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) 833 }) 834 s += ")" 835 836 if len(exp.Doc) > 0 { 837 fmt.Fprintf(fgcch, "\n%s", exp.Doc) 838 } 839 fmt.Fprintf(fgcch, "\nextern %s;\n", s) 840 841 fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName) 842 fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD") 843 fmt.Fprintf(fgcc, "\n%s\n", s) 844 fmt.Fprintf(fgcc, "{\n") 845 fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n") 846 fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) 847 if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { 848 fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) 849 } 850 if fn.Recv != nil { 851 fmt.Fprintf(fgcc, "\ta.recv = recv;\n") 852 } 853 forFieldList(fntype.Params, 854 func(i int, aname string, atype ast.Expr) { 855 fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) 856 }) 857 fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n") 858 fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off) 859 fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") 860 fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n") 861 if gccResult != "void" { 862 if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 863 fmt.Fprintf(fgcc, "\treturn a.r0;\n") 864 } else { 865 forFieldList(fntype.Results, 866 func(i int, aname string, atype ast.Expr) { 867 fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i) 868 }) 869 fmt.Fprintf(fgcc, "\treturn r;\n") 870 } 871 } 872 fmt.Fprintf(fgcc, "}\n") 873 874 // Build the wrapper function compiled by cmd/compile. 875 goname := "_cgoexpwrap" + cPrefix + "_" 876 if fn.Recv != nil { 877 goname += fn.Recv.List[0].Names[0].Name + "_" 878 } 879 goname += exp.Func.Name.Name 880 fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName) 881 fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName) 882 fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) 883 fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g 884 fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted 885 fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32, ctxt uintptr) {\n", cPrefix, exp.ExpName) 886 fmt.Fprintf(fgo2, "\tfn := %s\n", goname) 887 // The indirect here is converting from a Go function pointer to a C function pointer. 888 fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt);\n") 889 fmt.Fprintf(fgo2, "}\n") 890 891 fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) 892 893 // This code uses printer.Fprint, not conf.Fprint, 894 // because we don't want //line comments in the middle 895 // of the function types. 896 fmt.Fprintf(fgo2, "\n") 897 fmt.Fprintf(fgo2, "func %s(", goname) 898 comma := false 899 if fn.Recv != nil { 900 fmt.Fprintf(fgo2, "recv ") 901 printer.Fprint(fgo2, fset, fn.Recv.List[0].Type) 902 comma = true 903 } 904 forFieldList(fntype.Params, 905 func(i int, aname string, atype ast.Expr) { 906 if comma { 907 fmt.Fprintf(fgo2, ", ") 908 } 909 fmt.Fprintf(fgo2, "p%d ", i) 910 printer.Fprint(fgo2, fset, atype) 911 comma = true 912 }) 913 fmt.Fprintf(fgo2, ")") 914 if gccResult != "void" { 915 fmt.Fprint(fgo2, " (") 916 forFieldList(fntype.Results, 917 func(i int, aname string, atype ast.Expr) { 918 if i > 0 { 919 fmt.Fprint(fgo2, ", ") 920 } 921 fmt.Fprintf(fgo2, "r%d ", i) 922 printer.Fprint(fgo2, fset, atype) 923 }) 924 fmt.Fprint(fgo2, ")") 925 } 926 fmt.Fprint(fgo2, " {\n") 927 if gccResult == "void" { 928 fmt.Fprint(fgo2, "\t") 929 } else { 930 // Verify that any results don't contain any 931 // Go pointers. 932 addedDefer := false 933 forFieldList(fntype.Results, 934 func(i int, aname string, atype ast.Expr) { 935 if !p.hasPointer(nil, atype, false) { 936 return 937 } 938 if !addedDefer { 939 fmt.Fprint(fgo2, "\tdefer func() {\n") 940 addedDefer = true 941 } 942 fmt.Fprintf(fgo2, "\t\t_cgoCheckResult(r%d)\n", i) 943 }) 944 if addedDefer { 945 fmt.Fprint(fgo2, "\t}()\n") 946 } 947 fmt.Fprint(fgo2, "\treturn ") 948 } 949 if fn.Recv != nil { 950 fmt.Fprintf(fgo2, "recv.") 951 } 952 fmt.Fprintf(fgo2, "%s(", exp.Func.Name) 953 forFieldList(fntype.Params, 954 func(i int, aname string, atype ast.Expr) { 955 if i > 0 { 956 fmt.Fprint(fgo2, ", ") 957 } 958 fmt.Fprintf(fgo2, "p%d", i) 959 }) 960 fmt.Fprint(fgo2, ")\n") 961 fmt.Fprint(fgo2, "}\n") 962 } 963 964 fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog) 965 } 966 967 // Write out the C header allowing C code to call exported gccgo functions. 968 func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) { 969 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 970 971 p.writeExportHeader(fgcch) 972 973 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 974 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") 975 976 fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog) 977 fmt.Fprintf(fgcc, "%s\n", tsanProlog) 978 979 for _, exp := range p.ExpFunc { 980 fn := exp.Func 981 fntype := fn.Type 982 983 cdeclBuf := new(bytes.Buffer) 984 resultCount := 0 985 forFieldList(fntype.Results, 986 func(i int, aname string, atype ast.Expr) { resultCount++ }) 987 switch resultCount { 988 case 0: 989 fmt.Fprintf(cdeclBuf, "void") 990 case 1: 991 forFieldList(fntype.Results, 992 func(i int, aname string, atype ast.Expr) { 993 t := p.cgoType(atype) 994 fmt.Fprintf(cdeclBuf, "%s", t.C) 995 }) 996 default: 997 // Declare a result struct. 998 fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) 999 fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName) 1000 forFieldList(fntype.Results, 1001 func(i int, aname string, atype ast.Expr) { 1002 t := p.cgoType(atype) 1003 fmt.Fprintf(fgcch, "\t%s r%d;", t.C, i) 1004 if len(aname) > 0 { 1005 fmt.Fprintf(fgcch, " /* %s */", aname) 1006 } 1007 fmt.Fprint(fgcch, "\n") 1008 }) 1009 fmt.Fprintf(fgcch, "};\n") 1010 fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName) 1011 } 1012 1013 cRet := cdeclBuf.String() 1014 1015 cdeclBuf = new(bytes.Buffer) 1016 fmt.Fprintf(cdeclBuf, "(") 1017 if fn.Recv != nil { 1018 fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String()) 1019 } 1020 // Function parameters. 1021 forFieldList(fntype.Params, 1022 func(i int, aname string, atype ast.Expr) { 1023 if i > 0 || fn.Recv != nil { 1024 fmt.Fprintf(cdeclBuf, ", ") 1025 } 1026 t := p.cgoType(atype) 1027 fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i) 1028 }) 1029 fmt.Fprintf(cdeclBuf, ")") 1030 cParams := cdeclBuf.String() 1031 1032 if len(exp.Doc) > 0 { 1033 fmt.Fprintf(fgcch, "\n%s", exp.Doc) 1034 } 1035 1036 fmt.Fprintf(fgcch, "extern %s %s %s;\n", cRet, exp.ExpName, cParams) 1037 1038 // We need to use a name that will be exported by the 1039 // Go code; otherwise gccgo will make it static and we 1040 // will not be able to link against it from the C 1041 // code. 1042 goName := "Cgoexp_" + exp.ExpName 1043 fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName) 1044 fmt.Fprint(fgcc, "\n") 1045 1046 fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n") 1047 fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams) 1048 if resultCount > 0 { 1049 fmt.Fprintf(fgcc, "\t%s r;\n", cRet) 1050 } 1051 fmt.Fprintf(fgcc, "\tif(_cgo_wait_runtime_init_done)\n") 1052 fmt.Fprintf(fgcc, "\t\t_cgo_wait_runtime_init_done();\n") 1053 fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n") 1054 fmt.Fprint(fgcc, "\t") 1055 if resultCount > 0 { 1056 fmt.Fprint(fgcc, "r = ") 1057 } 1058 fmt.Fprintf(fgcc, "%s(", goName) 1059 if fn.Recv != nil { 1060 fmt.Fprint(fgcc, "recv") 1061 } 1062 forFieldList(fntype.Params, 1063 func(i int, aname string, atype ast.Expr) { 1064 if i > 0 || fn.Recv != nil { 1065 fmt.Fprintf(fgcc, ", ") 1066 } 1067 fmt.Fprintf(fgcc, "p%d", i) 1068 }) 1069 fmt.Fprint(fgcc, ");\n") 1070 fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") 1071 if resultCount > 0 { 1072 fmt.Fprint(fgcc, "\treturn r;\n") 1073 } 1074 fmt.Fprint(fgcc, "}\n") 1075 1076 // Dummy declaration for _cgo_main.c 1077 fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName) 1078 fmt.Fprint(fm, "\n") 1079 1080 // For gccgo we use a wrapper function in Go, in order 1081 // to call CgocallBack and CgocallBackDone. 1082 1083 // This code uses printer.Fprint, not conf.Fprint, 1084 // because we don't want //line comments in the middle 1085 // of the function types. 1086 fmt.Fprint(fgo2, "\n") 1087 fmt.Fprintf(fgo2, "func %s(", goName) 1088 if fn.Recv != nil { 1089 fmt.Fprint(fgo2, "recv ") 1090 printer.Fprint(fgo2, fset, fn.Recv.List[0].Type) 1091 } 1092 forFieldList(fntype.Params, 1093 func(i int, aname string, atype ast.Expr) { 1094 if i > 0 || fn.Recv != nil { 1095 fmt.Fprintf(fgo2, ", ") 1096 } 1097 fmt.Fprintf(fgo2, "p%d ", i) 1098 printer.Fprint(fgo2, fset, atype) 1099 }) 1100 fmt.Fprintf(fgo2, ")") 1101 if resultCount > 0 { 1102 fmt.Fprintf(fgo2, " (") 1103 forFieldList(fntype.Results, 1104 func(i int, aname string, atype ast.Expr) { 1105 if i > 0 { 1106 fmt.Fprint(fgo2, ", ") 1107 } 1108 printer.Fprint(fgo2, fset, atype) 1109 }) 1110 fmt.Fprint(fgo2, ")") 1111 } 1112 fmt.Fprint(fgo2, " {\n") 1113 fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n") 1114 fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n") 1115 fmt.Fprint(fgo2, "\t") 1116 if resultCount > 0 { 1117 fmt.Fprint(fgo2, "return ") 1118 } 1119 if fn.Recv != nil { 1120 fmt.Fprint(fgo2, "recv.") 1121 } 1122 fmt.Fprintf(fgo2, "%s(", exp.Func.Name) 1123 forFieldList(fntype.Params, 1124 func(i int, aname string, atype ast.Expr) { 1125 if i > 0 { 1126 fmt.Fprint(fgo2, ", ") 1127 } 1128 fmt.Fprintf(fgo2, "p%d", i) 1129 }) 1130 fmt.Fprint(fgo2, ")\n") 1131 fmt.Fprint(fgo2, "}\n") 1132 } 1133 1134 fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog) 1135 } 1136 1137 // writeExportHeader writes out the start of the _cgo_export.h file. 1138 func (p *Package) writeExportHeader(fgcch io.Writer) { 1139 fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n") 1140 pkg := *importPath 1141 if pkg == "" { 1142 pkg = p.PackagePath 1143 } 1144 fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg) 1145 1146 fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments. */\n\n") 1147 fmt.Fprintf(fgcch, "%s\n", p.Preamble) 1148 fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments. */\n\n") 1149 1150 fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) 1151 } 1152 1153 // Return the package prefix when using gccgo. 1154 func (p *Package) gccgoSymbolPrefix() string { 1155 if !*gccgo { 1156 return "" 1157 } 1158 1159 clean := func(r rune) rune { 1160 switch { 1161 case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', 1162 '0' <= r && r <= '9': 1163 return r 1164 } 1165 return '_' 1166 } 1167 1168 if *gccgopkgpath != "" { 1169 return strings.Map(clean, *gccgopkgpath) 1170 } 1171 if *gccgoprefix == "" && p.PackageName == "main" { 1172 return "main" 1173 } 1174 prefix := strings.Map(clean, *gccgoprefix) 1175 if prefix == "" { 1176 prefix = "go" 1177 } 1178 return prefix + "." + p.PackageName 1179 } 1180 1181 // Call a function for each entry in an ast.FieldList, passing the 1182 // index into the list, the name if any, and the type. 1183 func forFieldList(fl *ast.FieldList, fn func(int, string, ast.Expr)) { 1184 if fl == nil { 1185 return 1186 } 1187 i := 0 1188 for _, r := range fl.List { 1189 if r.Names == nil { 1190 fn(i, "", r.Type) 1191 i++ 1192 } else { 1193 for _, n := range r.Names { 1194 fn(i, n.Name, r.Type) 1195 i++ 1196 } 1197 } 1198 } 1199 } 1200 1201 func c(repr string, args ...interface{}) *TypeRepr { 1202 return &TypeRepr{repr, args} 1203 } 1204 1205 // Map predeclared Go types to Type. 1206 var goTypes = map[string]*Type{ 1207 "bool": {Size: 1, Align: 1, C: c("GoUint8")}, 1208 "byte": {Size: 1, Align: 1, C: c("GoUint8")}, 1209 "int": {Size: 0, Align: 0, C: c("GoInt")}, 1210 "uint": {Size: 0, Align: 0, C: c("GoUint")}, 1211 "rune": {Size: 4, Align: 4, C: c("GoInt32")}, 1212 "int8": {Size: 1, Align: 1, C: c("GoInt8")}, 1213 "uint8": {Size: 1, Align: 1, C: c("GoUint8")}, 1214 "int16": {Size: 2, Align: 2, C: c("GoInt16")}, 1215 "uint16": {Size: 2, Align: 2, C: c("GoUint16")}, 1216 "int32": {Size: 4, Align: 4, C: c("GoInt32")}, 1217 "uint32": {Size: 4, Align: 4, C: c("GoUint32")}, 1218 "int64": {Size: 8, Align: 8, C: c("GoInt64")}, 1219 "uint64": {Size: 8, Align: 8, C: c("GoUint64")}, 1220 "float32": {Size: 4, Align: 4, C: c("GoFloat32")}, 1221 "float64": {Size: 8, Align: 8, C: c("GoFloat64")}, 1222 "complex64": {Size: 8, Align: 4, C: c("GoComplex64")}, 1223 "complex128": {Size: 16, Align: 8, C: c("GoComplex128")}, 1224 } 1225 1226 // Map an ast type to a Type. 1227 func (p *Package) cgoType(e ast.Expr) *Type { 1228 switch t := e.(type) { 1229 case *ast.StarExpr: 1230 x := p.cgoType(t.X) 1231 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)} 1232 case *ast.ArrayType: 1233 if t.Len == nil { 1234 // Slice: pointer, len, cap. 1235 return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")} 1236 } 1237 case *ast.StructType: 1238 // TODO 1239 case *ast.FuncType: 1240 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} 1241 case *ast.InterfaceType: 1242 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} 1243 case *ast.MapType: 1244 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")} 1245 case *ast.ChanType: 1246 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")} 1247 case *ast.Ident: 1248 // Look up the type in the top level declarations. 1249 // TODO: Handle types defined within a function. 1250 for _, d := range p.Decl { 1251 gd, ok := d.(*ast.GenDecl) 1252 if !ok || gd.Tok != token.TYPE { 1253 continue 1254 } 1255 for _, spec := range gd.Specs { 1256 ts, ok := spec.(*ast.TypeSpec) 1257 if !ok { 1258 continue 1259 } 1260 if ts.Name.Name == t.Name { 1261 return p.cgoType(ts.Type) 1262 } 1263 } 1264 } 1265 if def := typedef[t.Name]; def != nil { 1266 return def 1267 } 1268 if t.Name == "uintptr" { 1269 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")} 1270 } 1271 if t.Name == "string" { 1272 // The string data is 1 pointer + 1 (pointer-sized) int. 1273 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")} 1274 } 1275 if t.Name == "error" { 1276 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} 1277 } 1278 if r, ok := goTypes[t.Name]; ok { 1279 if r.Size == 0 { // int or uint 1280 rr := new(Type) 1281 *rr = *r 1282 rr.Size = p.IntSize 1283 rr.Align = p.IntSize 1284 r = rr 1285 } 1286 if r.Align > p.PtrSize { 1287 r.Align = p.PtrSize 1288 } 1289 return r 1290 } 1291 error_(e.Pos(), "unrecognized Go type %s", t.Name) 1292 return &Type{Size: 4, Align: 4, C: c("int")} 1293 case *ast.SelectorExpr: 1294 id, ok := t.X.(*ast.Ident) 1295 if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" { 1296 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} 1297 } 1298 } 1299 error_(e.Pos(), "Go type not supported in export: %s", gofmt(e)) 1300 return &Type{Size: 4, Align: 4, C: c("int")} 1301 } 1302 1303 const gccProlog = ` 1304 /* 1305 If x and y are not equal, the type will be invalid 1306 (have a negative array count) and an inscrutable error will come 1307 out of the compiler and hopefully mention "name". 1308 */ 1309 #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 1310 1311 // Check at compile time that the sizes we use match our expectations. 1312 #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 1313 1314 __cgo_size_assert(char, 1) 1315 __cgo_size_assert(short, 2) 1316 __cgo_size_assert(int, 4) 1317 typedef long long __cgo_long_long; 1318 __cgo_size_assert(__cgo_long_long, 8) 1319 __cgo_size_assert(float, 4) 1320 __cgo_size_assert(double, 8) 1321 1322 extern char* _cgo_topofstack(void); 1323 1324 #include <errno.h> 1325 #include <string.h> 1326 ` 1327 1328 // Prologue defining TSAN functions in C. 1329 const noTsanProlog = ` 1330 #define CGO_NO_SANITIZE_THREAD 1331 #define _cgo_tsan_acquire() 1332 #define _cgo_tsan_release() 1333 ` 1334 1335 // This must match the TSAN code in runtime/cgo/libcgo.h. 1336 const yesTsanProlog = ` 1337 #define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread)) 1338 1339 long long _cgo_sync __attribute__ ((common)); 1340 1341 extern void __tsan_acquire(void*); 1342 extern void __tsan_release(void*); 1343 1344 __attribute__ ((unused)) 1345 static void _cgo_tsan_acquire() { 1346 __tsan_acquire(&_cgo_sync); 1347 } 1348 1349 __attribute__ ((unused)) 1350 static void _cgo_tsan_release() { 1351 __tsan_release(&_cgo_sync); 1352 } 1353 ` 1354 1355 // Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc. 1356 var tsanProlog = noTsanProlog 1357 1358 const builtinProlog = ` 1359 #include <stddef.h> /* for ptrdiff_t and size_t below */ 1360 1361 /* Define intgo when compiling with GCC. */ 1362 typedef ptrdiff_t intgo; 1363 1364 typedef struct { char *p; intgo n; } _GoString_; 1365 typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 1366 _GoString_ GoString(char *p); 1367 _GoString_ GoStringN(char *p, int l); 1368 _GoBytes_ GoBytes(void *p, int n); 1369 char *CString(_GoString_); 1370 void *CBytes(_GoBytes_); 1371 void *_CMalloc(size_t); 1372 ` 1373 1374 const goProlog = ` 1375 //go:linkname _cgo_runtime_cgocall runtime.cgocall 1376 func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32 1377 1378 //go:linkname _cgo_runtime_cgocallback runtime.cgocallback 1379 func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr) 1380 1381 //go:linkname _cgoCheckPointer runtime.cgoCheckPointer 1382 func _cgoCheckPointer(interface{}, ...interface{}) 1383 1384 //go:linkname _cgoCheckResult runtime.cgoCheckResult 1385 func _cgoCheckResult(interface{}) 1386 ` 1387 1388 const gccgoGoProlog = ` 1389 func _cgoCheckPointer(interface{}, ...interface{}) 1390 1391 func _cgoCheckResult(interface{}) 1392 ` 1393 1394 const goStringDef = ` 1395 //go:linkname _cgo_runtime_gostring runtime.gostring 1396 func _cgo_runtime_gostring(*_Ctype_char) string 1397 1398 func _Cfunc_GoString(p *_Ctype_char) string { 1399 return _cgo_runtime_gostring(p) 1400 } 1401 ` 1402 1403 const goStringNDef = ` 1404 //go:linkname _cgo_runtime_gostringn runtime.gostringn 1405 func _cgo_runtime_gostringn(*_Ctype_char, int) string 1406 1407 func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string { 1408 return _cgo_runtime_gostringn(p, int(l)) 1409 } 1410 ` 1411 1412 const goBytesDef = ` 1413 //go:linkname _cgo_runtime_gobytes runtime.gobytes 1414 func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte 1415 1416 func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { 1417 return _cgo_runtime_gobytes(p, int(l)) 1418 } 1419 ` 1420 1421 const cStringDef = ` 1422 func _Cfunc_CString(s string) *_Ctype_char { 1423 p := _cgo_cmalloc(uint64(len(s)+1)) 1424 pp := (*[1<<30]byte)(p) 1425 copy(pp[:], s) 1426 pp[len(s)] = 0 1427 return (*_Ctype_char)(p) 1428 } 1429 ` 1430 1431 const cBytesDef = ` 1432 func _Cfunc_CBytes(b []byte) unsafe.Pointer { 1433 p := _cgo_cmalloc(uint64(len(b))) 1434 pp := (*[1<<30]byte)(p) 1435 copy(pp[:], b) 1436 return p 1437 } 1438 ` 1439 1440 const cMallocDef = ` 1441 func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer { 1442 return _cgo_cmalloc(uint64(n)) 1443 } 1444 ` 1445 1446 var builtinDefs = map[string]string{ 1447 "GoString": goStringDef, 1448 "GoStringN": goStringNDef, 1449 "GoBytes": goBytesDef, 1450 "CString": cStringDef, 1451 "CBytes": cBytesDef, 1452 "_CMalloc": cMallocDef, 1453 } 1454 1455 // Definitions for C.malloc in Go and in C. We define it ourselves 1456 // since we call it from functions we define, such as C.CString. 1457 // Also, we have historically ensured that C.malloc does not return 1458 // nil even for an allocation of 0. 1459 1460 const cMallocDefGo = ` 1461 //go:cgo_import_static _cgoPREFIX_Cfunc__Cmalloc 1462 //go:linkname __cgofn__cgoPREFIX_Cfunc__Cmalloc _cgoPREFIX_Cfunc__Cmalloc 1463 var __cgofn__cgoPREFIX_Cfunc__Cmalloc byte 1464 var _cgoPREFIX_Cfunc__Cmalloc = unsafe.Pointer(&__cgofn__cgoPREFIX_Cfunc__Cmalloc) 1465 1466 //go:linkname runtime_throw runtime.throw 1467 func runtime_throw(string) 1468 1469 //go:cgo_unsafe_args 1470 func _cgo_cmalloc(p0 uint64) (r1 unsafe.Pointer) { 1471 _cgo_runtime_cgocall(_cgoPREFIX_Cfunc__Cmalloc, uintptr(unsafe.Pointer(&p0))) 1472 if r1 == nil { 1473 runtime_throw("runtime: C malloc failed") 1474 } 1475 return 1476 } 1477 ` 1478 1479 // cMallocDefC defines the C version of C.malloc for the gc compiler. 1480 // It is defined here because C.CString and friends need a definition. 1481 // We define it by hand, rather than simply inventing a reference to 1482 // C.malloc, because <stdlib.h> may not have been included. 1483 // This is approximately what writeOutputFunc would generate, but 1484 // skips the cgo_topofstack code (which is only needed if the C code 1485 // calls back into Go). This also avoids returning nil for an 1486 // allocation of 0 bytes. 1487 const cMallocDefC = ` 1488 CGO_NO_SANITIZE_THREAD 1489 void _cgoPREFIX_Cfunc__Cmalloc(void *v) { 1490 struct { 1491 unsigned long long p0; 1492 void *r1; 1493 } PACKED *a = v; 1494 void *ret; 1495 _cgo_tsan_acquire(); 1496 ret = malloc(a->p0); 1497 if (ret == 0 && a->p0 == 0) { 1498 ret = malloc(1); 1499 } 1500 a->r1 = ret; 1501 _cgo_tsan_release(); 1502 } 1503 ` 1504 1505 func (p *Package) cPrologGccgo() string { 1506 return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1), 1507 "GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1) 1508 } 1509 1510 const cPrologGccgo = ` 1511 #include <stdint.h> 1512 #include <stdlib.h> 1513 #include <string.h> 1514 1515 typedef unsigned char byte; 1516 typedef intptr_t intgo; 1517 1518 struct __go_string { 1519 const unsigned char *__data; 1520 intgo __length; 1521 }; 1522 1523 typedef struct __go_open_array { 1524 void* __values; 1525 intgo __count; 1526 intgo __capacity; 1527 } Slice; 1528 1529 struct __go_string __go_byte_array_to_string(const void* p, intgo len); 1530 struct __go_open_array __go_string_to_byte_array (struct __go_string str); 1531 1532 const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) { 1533 char *p = malloc(s.__length+1); 1534 memmove(p, s.__data, s.__length); 1535 p[s.__length] = 0; 1536 return p; 1537 } 1538 1539 void *_cgoPREFIX_Cfunc_CBytes(struct __go_open_array b) { 1540 char *p = malloc(b.__count); 1541 memmove(p, b.__values, b.__count); 1542 return p; 1543 } 1544 1545 struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) { 1546 intgo len = (p != NULL) ? strlen(p) : 0; 1547 return __go_byte_array_to_string(p, len); 1548 } 1549 1550 struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) { 1551 return __go_byte_array_to_string(p, n); 1552 } 1553 1554 Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) { 1555 struct __go_string s = { (const unsigned char *)p, n }; 1556 return __go_string_to_byte_array(s); 1557 } 1558 1559 extern void runtime_throw(const char *); 1560 void *_cgoPREFIX_Cfunc__CMalloc(size_t n) { 1561 void *p = malloc(n); 1562 if(p == NULL && n == 0) 1563 p = malloc(1); 1564 if(p == NULL) 1565 runtime_throw("runtime: C malloc failed"); 1566 return p; 1567 } 1568 1569 struct __go_type_descriptor; 1570 typedef struct __go_empty_interface { 1571 const struct __go_type_descriptor *__type_descriptor; 1572 void *__object; 1573 } Eface; 1574 1575 extern void runtimeCgoCheckPointer(Eface, Slice) 1576 __asm__("runtime.cgoCheckPointer") 1577 __attribute__((weak)); 1578 1579 extern void localCgoCheckPointer(Eface, Slice) 1580 __asm__("GCCGOSYMBOLPREF._cgoCheckPointer"); 1581 1582 void localCgoCheckPointer(Eface ptr, Slice args) { 1583 if(runtimeCgoCheckPointer) { 1584 runtimeCgoCheckPointer(ptr, args); 1585 } 1586 } 1587 1588 extern void runtimeCgoCheckResult(Eface) 1589 __asm__("runtime.cgoCheckResult") 1590 __attribute__((weak)); 1591 1592 extern void localCgoCheckResult(Eface) 1593 __asm__("GCCGOSYMBOLPREF._cgoCheckResult"); 1594 1595 void localCgoCheckResult(Eface val) { 1596 if(runtimeCgoCheckResult) { 1597 runtimeCgoCheckResult(val); 1598 } 1599 } 1600 ` 1601 1602 func (p *Package) gccExportHeaderProlog() string { 1603 return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1) 1604 } 1605 1606 const gccExportHeaderProlog = ` 1607 /* Start of boilerplate cgo prologue. */ 1608 1609 #ifndef GO_CGO_PROLOGUE_H 1610 #define GO_CGO_PROLOGUE_H 1611 1612 typedef signed char GoInt8; 1613 typedef unsigned char GoUint8; 1614 typedef short GoInt16; 1615 typedef unsigned short GoUint16; 1616 typedef int GoInt32; 1617 typedef unsigned int GoUint32; 1618 typedef long long GoInt64; 1619 typedef unsigned long long GoUint64; 1620 typedef GoIntGOINTBITS GoInt; 1621 typedef GoUintGOINTBITS GoUint; 1622 typedef __SIZE_TYPE__ GoUintptr; 1623 typedef float GoFloat32; 1624 typedef double GoFloat64; 1625 typedef float _Complex GoComplex64; 1626 typedef double _Complex GoComplex128; 1627 1628 /* 1629 static assertion to make sure the file is being used on architecture 1630 at least with matching size of GoInt. 1631 */ 1632 typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1]; 1633 1634 typedef struct { const char *p; GoInt n; } GoString; 1635 typedef void *GoMap; 1636 typedef void *GoChan; 1637 typedef struct { void *t; void *v; } GoInterface; 1638 typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 1639 1640 #endif 1641 1642 /* End of boilerplate cgo prologue. */ 1643 1644 #ifdef __cplusplus 1645 extern "C" { 1646 #endif 1647 ` 1648 1649 // gccExportHeaderEpilog goes at the end of the generated header file. 1650 const gccExportHeaderEpilog = ` 1651 #ifdef __cplusplus 1652 } 1653 #endif 1654 ` 1655 1656 // gccgoExportFileProlog is written to the _cgo_export.c file when 1657 // using gccgo. 1658 // We use weak declarations, and test the addresses, so that this code 1659 // works with older versions of gccgo. 1660 const gccgoExportFileProlog = ` 1661 extern _Bool runtime_iscgo __attribute__ ((weak)); 1662 1663 static void GoInit(void) __attribute__ ((constructor)); 1664 static void GoInit(void) { 1665 if(&runtime_iscgo) 1666 runtime_iscgo = 1; 1667 } 1668 1669 extern __SIZE_TYPE__ _cgo_wait_runtime_init_done() __attribute__ ((weak)); 1670 `