github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/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 conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8} 23 24 // writeDefs creates output files to be compiled by 6g, 6c, and gcc. 25 // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) 26 func (p *Package) writeDefs() { 27 var fgo2, fc io.Writer 28 f := creat(*objDir + "_cgo_gotypes.go") 29 defer f.Close() 30 fgo2 = f 31 if *gccgo { 32 f := creat(*objDir + "_cgo_defun.c") 33 defer f.Close() 34 fc = f 35 } 36 fm := creat(*objDir + "_cgo_main.c") 37 38 var gccgoInit bytes.Buffer 39 40 fflg := creat(*objDir + "_cgo_flags") 41 for k, v := range p.CgoFlags { 42 fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " ")) 43 if k == "LDFLAGS" && !*gccgo { 44 for _, arg := range v { 45 fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg) 46 } 47 } 48 } 49 fflg.Close() 50 51 // Write C main file for using gcc to resolve imports. 52 fmt.Fprintf(fm, "int main() { return 0; }\n") 53 if *importRuntimeCgo { 54 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n") 55 fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n") 56 } else { 57 // If we're not importing runtime/cgo, we *are* runtime/cgo, 58 // which provides crosscall2. We just need a prototype. 59 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n") 60 } 61 fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") 62 fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") 63 64 // Write second Go output: definitions of _C_xxx. 65 // In a separate file so that the import of "unsafe" does not 66 // pollute the original file. 67 fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") 68 fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) 69 fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") 70 if !*gccgo && *importRuntimeCgo { 71 fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") 72 } 73 if *importSyscall { 74 fmt.Fprintf(fgo2, "import \"syscall\"\n\n") 75 fmt.Fprintf(fgo2, "var _ syscall.Errno\n") 76 } 77 fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") 78 79 typedefNames := make([]string, 0, len(typedef)) 80 for name := range typedef { 81 typedefNames = append(typedefNames, name) 82 } 83 sort.Strings(typedefNames) 84 for _, name := range typedefNames { 85 def := typedef[name] 86 fmt.Fprintf(fgo2, "type %s ", name) 87 conf.Fprint(fgo2, fset, def.Go) 88 fmt.Fprintf(fgo2, "\n\n") 89 } 90 if *gccgo { 91 fmt.Fprintf(fgo2, "type _Ctype_void byte\n") 92 } else { 93 fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n") 94 } 95 96 if *gccgo { 97 fmt.Fprint(fc, p.cPrologGccgo()) 98 } else { 99 fmt.Fprint(fgo2, goProlog) 100 } 101 102 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 103 104 cVars := make(map[string]bool) 105 for _, key := range nameKeys(p.Name) { 106 n := p.Name[key] 107 if !n.IsVar() { 108 continue 109 } 110 111 if !cVars[n.C] { 112 fmt.Fprintf(fm, "extern char %s[];\n", n.C) 113 fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) 114 if *gccgo { 115 fmt.Fprintf(fc, "extern byte *%s;\n", n.C) 116 } else { 117 fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C) 118 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C) 119 fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C) 120 } 121 cVars[n.C] = true 122 } 123 124 var node ast.Node 125 if n.Kind == "var" { 126 node = &ast.StarExpr{X: n.Type.Go} 127 } else if n.Kind == "fpvar" { 128 node = n.Type.Go 129 } else { 130 panic(fmt.Errorf("invalid var kind %q", n.Kind)) 131 } 132 if *gccgo { 133 fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) 134 fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C) 135 fmt.Fprintf(fc, "\n") 136 } 137 138 fmt.Fprintf(fgo2, "var %s ", n.Mangle) 139 conf.Fprint(fgo2, fset, node) 140 if !*gccgo { 141 fmt.Fprintf(fgo2, " = (") 142 conf.Fprint(fgo2, fset, node) 143 fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C) 144 } 145 fmt.Fprintf(fgo2, "\n") 146 } 147 if *gccgo { 148 fmt.Fprintf(fc, "\n") 149 } 150 151 for _, key := range nameKeys(p.Name) { 152 n := p.Name[key] 153 if n.Const != "" { 154 fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const) 155 } 156 } 157 fmt.Fprintf(fgo2, "\n") 158 159 for _, key := range nameKeys(p.Name) { 160 n := p.Name[key] 161 if n.FuncType != nil { 162 p.writeDefsFunc(fc, fgo2, n) 163 } 164 } 165 166 if *gccgo { 167 p.writeGccgoExports(fgo2, fc, fm) 168 } else { 169 p.writeExports(fgo2, fc, fm) 170 } 171 172 init := gccgoInit.String() 173 if init != "" { 174 fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));") 175 fmt.Fprintln(fc, "static void init(void) {") 176 fmt.Fprint(fc, init) 177 fmt.Fprintln(fc, "}") 178 } 179 } 180 181 func dynimport(obj string) { 182 stdout := os.Stdout 183 if *dynout != "" { 184 f, err := os.Create(*dynout) 185 if err != nil { 186 fatalf("%s", err) 187 } 188 stdout = f 189 } 190 191 fmt.Fprintf(stdout, "package %s\n", *dynpackage) 192 193 if f, err := elf.Open(obj); err == nil { 194 if *dynlinker { 195 // Emit the cgo_dynamic_linker line. 196 if sec := f.Section(".interp"); sec != nil { 197 if data, err := sec.Data(); err == nil && len(data) > 1 { 198 // skip trailing \0 in data 199 fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1])) 200 } 201 } 202 } 203 sym, err := f.ImportedSymbols() 204 if err != nil { 205 fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) 206 } 207 for _, s := range sym { 208 targ := s.Name 209 if s.Version != "" { 210 targ += "#" + s.Version 211 } 212 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) 213 } 214 lib, err := f.ImportedLibraries() 215 if err != nil { 216 fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) 217 } 218 for _, l := range lib { 219 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 220 } 221 return 222 } 223 224 if f, err := macho.Open(obj); err == nil { 225 sym, err := f.ImportedSymbols() 226 if err != nil { 227 fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) 228 } 229 for _, s := range sym { 230 if len(s) > 0 && s[0] == '_' { 231 s = s[1:] 232 } 233 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "") 234 } 235 lib, err := f.ImportedLibraries() 236 if err != nil { 237 fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) 238 } 239 for _, l := range lib { 240 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 241 } 242 return 243 } 244 245 if f, err := pe.Open(obj); err == nil { 246 sym, err := f.ImportedSymbols() 247 if err != nil { 248 fatalf("cannot load imported symbols from PE file %s: %v", obj, err) 249 } 250 for _, s := range sym { 251 ss := strings.Split(s, ":") 252 name := strings.Split(ss[0], "@")[0] 253 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) 254 } 255 return 256 } 257 258 fatalf("cannot parse %s as ELF, Mach-O or PE", obj) 259 } 260 261 // Construct a gcc struct matching the 6c argument frame. 262 // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. 263 // These assumptions are checked by the gccProlog. 264 // Also assumes that 6c convention is to word-align the 265 // input and output parameters. 266 func (p *Package) structType(n *Name) (string, int64) { 267 var buf bytes.Buffer 268 fmt.Fprint(&buf, "struct {\n") 269 off := int64(0) 270 for i, t := range n.FuncType.Params { 271 if off%t.Align != 0 { 272 pad := t.Align - off%t.Align 273 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 274 off += pad 275 } 276 c := t.Typedef 277 if c == "" { 278 c = t.C.String() 279 } 280 fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i) 281 off += t.Size 282 } 283 if off%p.PtrSize != 0 { 284 pad := p.PtrSize - off%p.PtrSize 285 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 286 off += pad 287 } 288 if t := n.FuncType.Result; t != nil { 289 if off%t.Align != 0 { 290 pad := t.Align - off%t.Align 291 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 292 off += pad 293 } 294 qual := "" 295 if c := t.C.String(); c[len(c)-1] == '*' { 296 qual = "const " 297 } 298 fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) 299 off += t.Size 300 } 301 if off%p.PtrSize != 0 { 302 pad := p.PtrSize - off%p.PtrSize 303 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 304 off += pad 305 } 306 if off == 0 { 307 fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct 308 } 309 fmt.Fprintf(&buf, "\t}") 310 return buf.String(), off 311 } 312 313 func (p *Package) writeDefsFunc(fc, fgo2 io.Writer, n *Name) { 314 name := n.Go 315 gtype := n.FuncType.Go 316 void := gtype.Results == nil || len(gtype.Results.List) == 0 317 if n.AddError { 318 // Add "error" to return type list. 319 // Type list is known to be 0 or 1 element - it's a C function. 320 err := &ast.Field{Type: ast.NewIdent("error")} 321 l := gtype.Results.List 322 if len(l) == 0 { 323 l = []*ast.Field{err} 324 } else { 325 l = []*ast.Field{l[0], err} 326 } 327 t := new(ast.FuncType) 328 *t = *gtype 329 t.Results = &ast.FieldList{List: l} 330 gtype = t 331 } 332 333 // Go func declaration. 334 d := &ast.FuncDecl{ 335 Name: ast.NewIdent(n.Mangle), 336 Type: gtype, 337 } 338 339 // Builtins defined in the C prolog. 340 inProlog := builtinDefs[name] != "" 341 cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) 342 paramnames := []string(nil) 343 for i, param := range d.Type.Params.List { 344 paramName := fmt.Sprintf("p%d", i) 345 param.Names = []*ast.Ident{ast.NewIdent(paramName)} 346 paramnames = append(paramnames, paramName) 347 } 348 349 if *gccgo { 350 // Gccgo style hooks. 351 fmt.Fprint(fgo2, "\n") 352 conf.Fprint(fgo2, fset, d) 353 fmt.Fprint(fgo2, " {\n") 354 if !inProlog { 355 fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n") 356 fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n") 357 } 358 if n.AddError { 359 fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n") 360 } 361 fmt.Fprint(fgo2, "\t") 362 if !void { 363 fmt.Fprint(fgo2, "r := ") 364 } 365 fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", ")) 366 367 if n.AddError { 368 fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n") 369 fmt.Fprint(fgo2, "\tif e != 0 {\n") 370 fmt.Fprint(fgo2, "\t\treturn ") 371 if !void { 372 fmt.Fprint(fgo2, "r, ") 373 } 374 fmt.Fprint(fgo2, "e\n") 375 fmt.Fprint(fgo2, "\t}\n") 376 fmt.Fprint(fgo2, "\treturn ") 377 if !void { 378 fmt.Fprint(fgo2, "r, ") 379 } 380 fmt.Fprint(fgo2, "nil\n") 381 } else if !void { 382 fmt.Fprint(fgo2, "\treturn r\n") 383 } 384 385 fmt.Fprint(fgo2, "}\n") 386 387 // declare the C function. 388 fmt.Fprintf(fgo2, "//extern %s\n", cname) 389 d.Name = ast.NewIdent(cname) 390 if n.AddError { 391 l := d.Type.Results.List 392 d.Type.Results.List = l[:len(l)-1] 393 } 394 conf.Fprint(fgo2, fset, d) 395 fmt.Fprint(fgo2, "\n") 396 397 return 398 } 399 400 if inProlog { 401 fmt.Fprint(fgo2, builtinDefs[name]) 402 return 403 } 404 405 // C wrapper calls into gcc, passing a pointer to the argument frame. 406 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname) 407 fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname) 408 fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname) 409 fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname) 410 411 nret := 0 412 if !void { 413 d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")} 414 nret = 1 415 } 416 if n.AddError { 417 d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")} 418 } 419 420 fmt.Fprint(fgo2, "\n") 421 conf.Fprint(fgo2, fset, d) 422 fmt.Fprint(fgo2, " {\n") 423 424 // NOTE: Using uintptr to hide from escape analysis. 425 arg := "0" 426 if len(paramnames) > 0 { 427 arg = "uintptr(unsafe.Pointer(&p0))" 428 } else if !void { 429 arg = "uintptr(unsafe.Pointer(&r1))" 430 } 431 432 prefix := "" 433 if n.AddError { 434 prefix = "errno := " 435 } 436 fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg) 437 if n.AddError { 438 fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") 439 } 440 fmt.Fprintf(fgo2, "\treturn\n") 441 fmt.Fprintf(fgo2, "}\n") 442 } 443 444 // writeOutput creates stubs for a specific source file to be compiled by 6g 445 // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) 446 func (p *Package) writeOutput(f *File, srcfile string) { 447 base := srcfile 448 if strings.HasSuffix(base, ".go") { 449 base = base[0 : len(base)-3] 450 } 451 base = strings.Map(slashToUnderscore, base) 452 fgo1 := creat(*objDir + base + ".cgo1.go") 453 fgcc := creat(*objDir + base + ".cgo2.c") 454 455 p.GoFiles = append(p.GoFiles, base+".cgo1.go") 456 p.GccFiles = append(p.GccFiles, base+".cgo2.c") 457 458 // Write Go output: Go input with rewrites of C.xxx to _C_xxx. 459 fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") 460 conf.Fprint(fgo1, fset, f.AST) 461 462 // While we process the vars and funcs, also write 6c and gcc output. 463 // Gcc output starts with the preamble. 464 fmt.Fprintf(fgcc, "%s\n", f.Preamble) 465 fmt.Fprintf(fgcc, "%s\n", gccProlog) 466 467 for _, key := range nameKeys(f.Name) { 468 n := f.Name[key] 469 if n.FuncType != nil { 470 p.writeOutputFunc(fgcc, n) 471 } 472 } 473 474 fgo1.Close() 475 fgcc.Close() 476 } 477 478 // fixGo converts the internal Name.Go field into the name we should show 479 // to users in error messages. There's only one for now: on input we rewrite 480 // C.malloc into C._CMalloc, so change it back here. 481 func fixGo(name string) string { 482 if name == "_CMalloc" { 483 return "malloc" 484 } 485 return name 486 } 487 488 var isBuiltin = map[string]bool{ 489 "_Cfunc_CString": true, 490 "_Cfunc_GoString": true, 491 "_Cfunc_GoStringN": true, 492 "_Cfunc_GoBytes": true, 493 "_Cfunc__CMalloc": true, 494 } 495 496 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { 497 name := n.Mangle 498 if isBuiltin[name] || p.Written[name] { 499 // The builtins are already defined in the C prolog, and we don't 500 // want to duplicate function definitions we've already done. 501 return 502 } 503 p.Written[name] = true 504 505 if *gccgo { 506 p.writeGccgoOutputFunc(fgcc, n) 507 return 508 } 509 510 ctype, _ := p.structType(n) 511 512 // Gcc wrapper unpacks the C argument struct 513 // and calls the actual C function. 514 if n.AddError { 515 fmt.Fprintf(fgcc, "int\n") 516 } else { 517 fmt.Fprintf(fgcc, "void\n") 518 } 519 fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) 520 fmt.Fprintf(fgcc, "{\n") 521 if n.AddError { 522 fmt.Fprintf(fgcc, "\terrno = 0;\n") 523 } 524 // We're trying to write a gcc struct that matches 6c/8c/5c's layout. 525 // Use packed attribute to force no padding in this struct in case 526 // gcc has different packing requirements. 527 fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) 528 if n.FuncType.Result != nil { 529 // Save the stack top for use below. 530 fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") 531 } 532 fmt.Fprintf(fgcc, "\t") 533 if t := n.FuncType.Result; t != nil { 534 fmt.Fprintf(fgcc, "__typeof__(a->r) r = ") 535 if c := t.C.String(); c[len(c)-1] == '*' { 536 fmt.Fprint(fgcc, "(__typeof__(a->r)) ") 537 } 538 } 539 fmt.Fprintf(fgcc, "%s(", n.C) 540 for i, t := range n.FuncType.Params { 541 if i > 0 { 542 fmt.Fprintf(fgcc, ", ") 543 } 544 // We know the type params are correct, because 545 // the Go equivalents had good type params. 546 // However, our version of the type omits the magic 547 // words const and volatile, which can provoke 548 // C compiler warnings. Silence them by casting 549 // all pointers to void*. (Eventually that will produce 550 // other warnings.) 551 if c := t.C.String(); c[len(c)-1] == '*' { 552 fmt.Fprintf(fgcc, "(void*)") 553 } 554 fmt.Fprintf(fgcc, "a->p%d", i) 555 } 556 fmt.Fprintf(fgcc, ");\n") 557 if n.FuncType.Result != nil { 558 // The cgo call may have caused a stack copy (via a callback). 559 // Adjust the return value pointer appropriately. 560 fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") 561 // Save the return value. 562 fmt.Fprintf(fgcc, "\ta->r = r;\n") 563 } 564 if n.AddError { 565 fmt.Fprintf(fgcc, "\treturn errno;\n") 566 } 567 fmt.Fprintf(fgcc, "}\n") 568 fmt.Fprintf(fgcc, "\n") 569 } 570 571 // Write out a wrapper for a function when using gccgo. This is a 572 // simple wrapper that just calls the real function. We only need a 573 // wrapper to support static functions in the prologue--without a 574 // wrapper, we can't refer to the function, since the reference is in 575 // a different file. 576 func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { 577 if t := n.FuncType.Result; t != nil { 578 fmt.Fprintf(fgcc, "%s\n", t.C.String()) 579 } else { 580 fmt.Fprintf(fgcc, "void\n") 581 } 582 fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle) 583 for i, t := range n.FuncType.Params { 584 if i > 0 { 585 fmt.Fprintf(fgcc, ", ") 586 } 587 c := t.Typedef 588 if c == "" { 589 c = t.C.String() 590 } 591 fmt.Fprintf(fgcc, "%s p%d", c, i) 592 } 593 fmt.Fprintf(fgcc, ")\n") 594 fmt.Fprintf(fgcc, "{\n") 595 fmt.Fprintf(fgcc, "\t") 596 if t := n.FuncType.Result; t != nil { 597 fmt.Fprintf(fgcc, "return ") 598 // Cast to void* to avoid warnings due to omitted qualifiers. 599 if c := t.C.String(); c[len(c)-1] == '*' { 600 fmt.Fprintf(fgcc, "(void*)") 601 } 602 } 603 fmt.Fprintf(fgcc, "%s(", n.C) 604 for i, t := range n.FuncType.Params { 605 if i > 0 { 606 fmt.Fprintf(fgcc, ", ") 607 } 608 // Cast to void* to avoid warnings due to omitted qualifiers. 609 if c := t.C.String(); c[len(c)-1] == '*' { 610 fmt.Fprintf(fgcc, "(void*)") 611 } 612 fmt.Fprintf(fgcc, "p%d", i) 613 } 614 fmt.Fprintf(fgcc, ");\n") 615 fmt.Fprintf(fgcc, "}\n") 616 fmt.Fprintf(fgcc, "\n") 617 } 618 619 // packedAttribute returns host compiler struct attribute that will be 620 // used to match 6c/8c/5c's struct layout. For example, on 386 Windows, 621 // gcc wants to 8-align int64s, but 8c does not. 622 // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, 623 // and http://golang.org/issue/5603. 624 func (p *Package) packedAttribute() string { 625 s := "__attribute__((__packed__" 626 if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") { 627 s += ", __gcc_struct__" 628 } 629 return s + "))" 630 } 631 632 // Write out the various stubs we need to support functions exported 633 // from Go so that they are callable from C. 634 func (p *Package) writeExports(fgo2, fc, fm io.Writer) { 635 fgcc := creat(*objDir + "_cgo_export.c") 636 fgcch := creat(*objDir + "_cgo_export.h") 637 638 fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") 639 fmt.Fprintf(fgcch, "%s\n", p.Preamble) 640 fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) 641 642 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 643 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") 644 645 fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n") 646 647 for _, exp := range p.ExpFunc { 648 fn := exp.Func 649 650 // Construct a gcc struct matching the 6c argument and 651 // result frame. The gcc struct will be compiled with 652 // __attribute__((packed)) so all padding must be accounted 653 // for explicitly. 654 ctype := "struct {\n" 655 off := int64(0) 656 npad := 0 657 if fn.Recv != nil { 658 t := p.cgoType(fn.Recv.List[0].Type) 659 ctype += fmt.Sprintf("\t\t%s recv;\n", t.C) 660 off += t.Size 661 } 662 fntype := fn.Type 663 forFieldList(fntype.Params, 664 func(i int, atype ast.Expr) { 665 t := p.cgoType(atype) 666 if off%t.Align != 0 { 667 pad := t.Align - off%t.Align 668 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 669 off += pad 670 npad++ 671 } 672 ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i) 673 off += t.Size 674 }) 675 if off%p.PtrSize != 0 { 676 pad := p.PtrSize - off%p.PtrSize 677 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 678 off += pad 679 npad++ 680 } 681 forFieldList(fntype.Results, 682 func(i int, atype ast.Expr) { 683 t := p.cgoType(atype) 684 if off%t.Align != 0 { 685 pad := t.Align - off%t.Align 686 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 687 off += pad 688 npad++ 689 } 690 ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i) 691 off += t.Size 692 }) 693 if off%p.PtrSize != 0 { 694 pad := p.PtrSize - off%p.PtrSize 695 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 696 off += pad 697 npad++ 698 } 699 if ctype == "struct {\n" { 700 ctype += "\t\tchar unused;\n" // avoid empty struct 701 } 702 ctype += "\t}" 703 704 // Get the return type of the wrapper function 705 // compiled by gcc. 706 gccResult := "" 707 if fntype.Results == nil || len(fntype.Results.List) == 0 { 708 gccResult = "void" 709 } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 710 gccResult = p.cgoType(fntype.Results.List[0].Type).C.String() 711 } else { 712 fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) 713 fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName) 714 forFieldList(fntype.Results, 715 func(i int, atype ast.Expr) { 716 fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i) 717 }) 718 fmt.Fprintf(fgcch, "};\n") 719 gccResult = "struct " + exp.ExpName + "_return" 720 } 721 722 // Build the wrapper function compiled by gcc. 723 s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) 724 if fn.Recv != nil { 725 s += p.cgoType(fn.Recv.List[0].Type).C.String() 726 s += " recv" 727 } 728 forFieldList(fntype.Params, 729 func(i int, atype ast.Expr) { 730 if i > 0 || fn.Recv != nil { 731 s += ", " 732 } 733 s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) 734 }) 735 s += ")" 736 fmt.Fprintf(fgcch, "\nextern %s;\n", s) 737 738 fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName) 739 fmt.Fprintf(fgcc, "\n%s\n", s) 740 fmt.Fprintf(fgcc, "{\n") 741 fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) 742 if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { 743 fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) 744 } 745 if fn.Recv != nil { 746 fmt.Fprintf(fgcc, "\ta.recv = recv;\n") 747 } 748 forFieldList(fntype.Params, 749 func(i int, atype ast.Expr) { 750 fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) 751 }) 752 fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off) 753 if gccResult != "void" { 754 if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 755 fmt.Fprintf(fgcc, "\treturn a.r0;\n") 756 } else { 757 forFieldList(fntype.Results, 758 func(i int, atype ast.Expr) { 759 fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i) 760 }) 761 fmt.Fprintf(fgcc, "\treturn r;\n") 762 } 763 } 764 fmt.Fprintf(fgcc, "}\n") 765 766 // Build the wrapper function compiled by 6c/8c 767 goname := exp.Func.Name.Name 768 if fn.Recv != nil { 769 goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname 770 } 771 fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname) 772 fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName) 773 fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) 774 fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g 775 fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName) 776 fmt.Fprintf(fgo2, "\tfn := %s\n", goname) 777 // The indirect here is converting from a Go function pointer to a C function pointer. 778 fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n") 779 fmt.Fprintf(fgo2, "}\n") 780 781 fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) 782 783 // Calling a function with a receiver from C requires 784 // a Go wrapper function. 785 if fn.Recv != nil { 786 fmt.Fprintf(fgo2, "func %s(recv ", goname) 787 conf.Fprint(fgo2, fset, fn.Recv.List[0].Type) 788 forFieldList(fntype.Params, 789 func(i int, atype ast.Expr) { 790 fmt.Fprintf(fgo2, ", p%d ", i) 791 conf.Fprint(fgo2, fset, atype) 792 }) 793 fmt.Fprintf(fgo2, ")") 794 if gccResult != "void" { 795 fmt.Fprint(fgo2, " (") 796 forFieldList(fntype.Results, 797 func(i int, atype ast.Expr) { 798 if i > 0 { 799 fmt.Fprint(fgo2, ", ") 800 } 801 conf.Fprint(fgo2, fset, atype) 802 }) 803 fmt.Fprint(fgo2, ")") 804 } 805 fmt.Fprint(fgo2, " {\n") 806 fmt.Fprint(fgo2, "\t") 807 if gccResult != "void" { 808 fmt.Fprint(fgo2, "return ") 809 } 810 fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name) 811 forFieldList(fntype.Params, 812 func(i int, atype ast.Expr) { 813 if i > 0 { 814 fmt.Fprint(fgo2, ", ") 815 } 816 fmt.Fprintf(fgo2, "p%d", i) 817 }) 818 fmt.Fprint(fgo2, ")\n") 819 fmt.Fprint(fgo2, "}\n") 820 } 821 } 822 } 823 824 // Write out the C header allowing C code to call exported gccgo functions. 825 func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) { 826 fgcc := creat(*objDir + "_cgo_export.c") 827 fgcch := creat(*objDir + "_cgo_export.h") 828 829 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 830 831 fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") 832 fmt.Fprintf(fgcch, "%s\n", p.Preamble) 833 fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) 834 835 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 836 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") 837 838 fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n") 839 840 for _, exp := range p.ExpFunc { 841 fn := exp.Func 842 fntype := fn.Type 843 844 cdeclBuf := new(bytes.Buffer) 845 resultCount := 0 846 forFieldList(fntype.Results, 847 func(i int, atype ast.Expr) { resultCount++ }) 848 switch resultCount { 849 case 0: 850 fmt.Fprintf(cdeclBuf, "void") 851 case 1: 852 forFieldList(fntype.Results, 853 func(i int, atype ast.Expr) { 854 t := p.cgoType(atype) 855 fmt.Fprintf(cdeclBuf, "%s", t.C) 856 }) 857 default: 858 // Declare a result struct. 859 fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName) 860 forFieldList(fntype.Results, 861 func(i int, atype ast.Expr) { 862 t := p.cgoType(atype) 863 fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i) 864 }) 865 fmt.Fprintf(fgcch, "};\n") 866 fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName) 867 } 868 869 cRet := cdeclBuf.String() 870 871 cdeclBuf = new(bytes.Buffer) 872 fmt.Fprintf(cdeclBuf, "(") 873 if fn.Recv != nil { 874 fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String()) 875 } 876 // Function parameters. 877 forFieldList(fntype.Params, 878 func(i int, atype ast.Expr) { 879 if i > 0 || fn.Recv != nil { 880 fmt.Fprintf(cdeclBuf, ", ") 881 } 882 t := p.cgoType(atype) 883 fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i) 884 }) 885 fmt.Fprintf(cdeclBuf, ")") 886 cParams := cdeclBuf.String() 887 888 // We need to use a name that will be exported by the 889 // Go code; otherwise gccgo will make it static and we 890 // will not be able to link against it from the C 891 // code. 892 goName := "Cgoexp_" + exp.ExpName 893 fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName) 894 fmt.Fprint(fgcch, "\n") 895 896 // Use a #define so that the C code that includes 897 // cgo_export.h will be able to refer to the Go 898 // function using the expected name. 899 fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName) 900 901 // Use a #undef in _cgo_export.c so that we ignore the 902 // #define from cgo_export.h, since here we are 903 // defining the real function. 904 fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName) 905 906 fmt.Fprint(fgcc, "\n") 907 fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams) 908 fmt.Fprint(fgcc, "\t") 909 if resultCount > 0 { 910 fmt.Fprint(fgcc, "return ") 911 } 912 fmt.Fprintf(fgcc, "%s(", goName) 913 if fn.Recv != nil { 914 fmt.Fprint(fgcc, "recv") 915 } 916 forFieldList(fntype.Params, 917 func(i int, atype ast.Expr) { 918 if i > 0 || fn.Recv != nil { 919 fmt.Fprintf(fgcc, ", ") 920 } 921 fmt.Fprintf(fgcc, "p%d", i) 922 }) 923 fmt.Fprint(fgcc, ");\n") 924 fmt.Fprint(fgcc, "}\n") 925 926 // Dummy declaration for _cgo_main.c 927 fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams) 928 929 // For gccgo we use a wrapper function in Go, in order 930 // to call CgocallBack and CgocallBackDone. 931 932 // This code uses printer.Fprint, not conf.Fprint, 933 // because we don't want //line comments in the middle 934 // of the function types. 935 fmt.Fprint(fgo2, "\n") 936 fmt.Fprintf(fgo2, "func %s(", goName) 937 if fn.Recv != nil { 938 fmt.Fprint(fgo2, "recv ") 939 printer.Fprint(fgo2, fset, fn.Recv.List[0].Type) 940 } 941 forFieldList(fntype.Params, 942 func(i int, atype ast.Expr) { 943 if i > 0 || fn.Recv != nil { 944 fmt.Fprintf(fgo2, ", ") 945 } 946 fmt.Fprintf(fgo2, "p%d ", i) 947 printer.Fprint(fgo2, fset, atype) 948 }) 949 fmt.Fprintf(fgo2, ")") 950 if resultCount > 0 { 951 fmt.Fprintf(fgo2, " (") 952 forFieldList(fntype.Results, 953 func(i int, atype ast.Expr) { 954 if i > 0 { 955 fmt.Fprint(fgo2, ", ") 956 } 957 printer.Fprint(fgo2, fset, atype) 958 }) 959 fmt.Fprint(fgo2, ")") 960 } 961 fmt.Fprint(fgo2, " {\n") 962 fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n") 963 fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n") 964 fmt.Fprint(fgo2, "\t") 965 if resultCount > 0 { 966 fmt.Fprint(fgo2, "return ") 967 } 968 if fn.Recv != nil { 969 fmt.Fprint(fgo2, "recv.") 970 } 971 fmt.Fprintf(fgo2, "%s(", exp.Func.Name) 972 forFieldList(fntype.Params, 973 func(i int, atype ast.Expr) { 974 if i > 0 { 975 fmt.Fprint(fgo2, ", ") 976 } 977 fmt.Fprintf(fgo2, "p%d", i) 978 }) 979 fmt.Fprint(fgo2, ")\n") 980 fmt.Fprint(fgo2, "}\n") 981 } 982 } 983 984 // Return the package prefix when using gccgo. 985 func (p *Package) gccgoSymbolPrefix() string { 986 if !*gccgo { 987 return "" 988 } 989 990 clean := func(r rune) rune { 991 switch { 992 case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', 993 '0' <= r && r <= '9': 994 return r 995 } 996 return '_' 997 } 998 999 if *gccgopkgpath != "" { 1000 return strings.Map(clean, *gccgopkgpath) 1001 } 1002 if *gccgoprefix == "" && p.PackageName == "main" { 1003 return "main" 1004 } 1005 prefix := strings.Map(clean, *gccgoprefix) 1006 if prefix == "" { 1007 prefix = "go" 1008 } 1009 return prefix + "." + p.PackageName 1010 } 1011 1012 // Call a function for each entry in an ast.FieldList, passing the 1013 // index into the list and the type. 1014 func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) { 1015 if fl == nil { 1016 return 1017 } 1018 i := 0 1019 for _, r := range fl.List { 1020 if r.Names == nil { 1021 fn(i, r.Type) 1022 i++ 1023 } else { 1024 for range r.Names { 1025 fn(i, r.Type) 1026 i++ 1027 } 1028 } 1029 } 1030 } 1031 1032 func c(repr string, args ...interface{}) *TypeRepr { 1033 return &TypeRepr{repr, args} 1034 } 1035 1036 // Map predeclared Go types to Type. 1037 var goTypes = map[string]*Type{ 1038 "bool": {Size: 1, Align: 1, C: c("GoUint8")}, 1039 "byte": {Size: 1, Align: 1, C: c("GoUint8")}, 1040 "int": {Size: 0, Align: 0, C: c("GoInt")}, 1041 "uint": {Size: 0, Align: 0, C: c("GoUint")}, 1042 "rune": {Size: 4, Align: 4, C: c("GoInt32")}, 1043 "int8": {Size: 1, Align: 1, C: c("GoInt8")}, 1044 "uint8": {Size: 1, Align: 1, C: c("GoUint8")}, 1045 "int16": {Size: 2, Align: 2, C: c("GoInt16")}, 1046 "uint16": {Size: 2, Align: 2, C: c("GoUint16")}, 1047 "int32": {Size: 4, Align: 4, C: c("GoInt32")}, 1048 "uint32": {Size: 4, Align: 4, C: c("GoUint32")}, 1049 "int64": {Size: 8, Align: 8, C: c("GoInt64")}, 1050 "uint64": {Size: 8, Align: 8, C: c("GoUint64")}, 1051 "float32": {Size: 4, Align: 4, C: c("GoFloat32")}, 1052 "float64": {Size: 8, Align: 8, C: c("GoFloat64")}, 1053 "complex64": {Size: 8, Align: 8, C: c("GoComplex64")}, 1054 "complex128": {Size: 16, Align: 16, C: c("GoComplex128")}, 1055 } 1056 1057 // Map an ast type to a Type. 1058 func (p *Package) cgoType(e ast.Expr) *Type { 1059 switch t := e.(type) { 1060 case *ast.StarExpr: 1061 x := p.cgoType(t.X) 1062 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)} 1063 case *ast.ArrayType: 1064 if t.Len == nil { 1065 // Slice: pointer, len, cap. 1066 return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")} 1067 } 1068 case *ast.StructType: 1069 // TODO 1070 case *ast.FuncType: 1071 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} 1072 case *ast.InterfaceType: 1073 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} 1074 case *ast.MapType: 1075 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")} 1076 case *ast.ChanType: 1077 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")} 1078 case *ast.Ident: 1079 // Look up the type in the top level declarations. 1080 // TODO: Handle types defined within a function. 1081 for _, d := range p.Decl { 1082 gd, ok := d.(*ast.GenDecl) 1083 if !ok || gd.Tok != token.TYPE { 1084 continue 1085 } 1086 for _, spec := range gd.Specs { 1087 ts, ok := spec.(*ast.TypeSpec) 1088 if !ok { 1089 continue 1090 } 1091 if ts.Name.Name == t.Name { 1092 return p.cgoType(ts.Type) 1093 } 1094 } 1095 } 1096 if def := typedef[t.Name]; def != nil { 1097 return def 1098 } 1099 if t.Name == "uintptr" { 1100 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")} 1101 } 1102 if t.Name == "string" { 1103 // The string data is 1 pointer + 1 (pointer-sized) int. 1104 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")} 1105 } 1106 if t.Name == "error" { 1107 return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} 1108 } 1109 if r, ok := goTypes[t.Name]; ok { 1110 if r.Size == 0 { // int or uint 1111 rr := new(Type) 1112 *rr = *r 1113 rr.Size = p.IntSize 1114 rr.Align = p.IntSize 1115 r = rr 1116 } 1117 if r.Align > p.PtrSize { 1118 r.Align = p.PtrSize 1119 } 1120 return r 1121 } 1122 error_(e.Pos(), "unrecognized Go type %s", t.Name) 1123 return &Type{Size: 4, Align: 4, C: c("int")} 1124 case *ast.SelectorExpr: 1125 id, ok := t.X.(*ast.Ident) 1126 if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" { 1127 return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} 1128 } 1129 } 1130 error_(e.Pos(), "Go type not supported in export: %s", gofmt(e)) 1131 return &Type{Size: 4, Align: 4, C: c("int")} 1132 } 1133 1134 const gccProlog = ` 1135 // Usual nonsense: if x and y are not equal, the type will be invalid 1136 // (have a negative array count) and an inscrutable error will come 1137 // out of the compiler and hopefully mention "name". 1138 #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; 1139 1140 // Check at compile time that the sizes we use match our expectations. 1141 #define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) 1142 1143 __cgo_size_assert(char, 1) 1144 __cgo_size_assert(short, 2) 1145 __cgo_size_assert(int, 4) 1146 typedef long long __cgo_long_long; 1147 __cgo_size_assert(__cgo_long_long, 8) 1148 __cgo_size_assert(float, 4) 1149 __cgo_size_assert(double, 8) 1150 1151 extern char* _cgo_topofstack(void); 1152 1153 #include <errno.h> 1154 #include <string.h> 1155 ` 1156 1157 const builtinProlog = ` 1158 #include <stddef.h> /* for ptrdiff_t and size_t below */ 1159 1160 /* Define intgo when compiling with GCC. */ 1161 typedef ptrdiff_t intgo; 1162 1163 typedef struct { char *p; intgo n; } _GoString_; 1164 typedef struct { char *p; intgo n; intgo c; } _GoBytes_; 1165 _GoString_ GoString(char *p); 1166 _GoString_ GoStringN(char *p, int l); 1167 _GoBytes_ GoBytes(void *p, int n); 1168 char *CString(_GoString_); 1169 void *_CMalloc(size_t); 1170 ` 1171 1172 const goProlog = ` 1173 //go:linkname _cgo_runtime_cgocall_errno runtime.cgocall_errno 1174 func _cgo_runtime_cgocall_errno(unsafe.Pointer, uintptr) int32 1175 1176 //go:linkname _cgo_runtime_cmalloc runtime.cmalloc 1177 func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer 1178 1179 //go:linkname _cgo_runtime_cgocallback runtime.cgocallback 1180 func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr) 1181 ` 1182 1183 const goStringDef = ` 1184 //go:linkname _cgo_runtime_gostring runtime.gostring 1185 func _cgo_runtime_gostring(*_Ctype_char) string 1186 1187 func _Cfunc_GoString(p *_Ctype_char) string { 1188 return _cgo_runtime_gostring(p) 1189 } 1190 ` 1191 1192 const goStringNDef = ` 1193 //go:linkname _cgo_runtime_gostringn runtime.gostringn 1194 func _cgo_runtime_gostringn(*_Ctype_char, int) string 1195 1196 func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string { 1197 return _cgo_runtime_gostringn(p, int(l)) 1198 } 1199 ` 1200 1201 const goBytesDef = ` 1202 //go:linkname _cgo_runtime_gobytes runtime.gobytes 1203 func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte 1204 1205 func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { 1206 return _cgo_runtime_gobytes(p, int(l)) 1207 } 1208 ` 1209 1210 const cStringDef = ` 1211 func _Cfunc_CString(s string) *_Ctype_char { 1212 p := _cgo_runtime_cmalloc(uintptr(len(s)+1)) 1213 pp := (*[1<<30]byte)(p) 1214 copy(pp[:], s) 1215 pp[len(s)] = 0 1216 return (*_Ctype_char)(p) 1217 } 1218 ` 1219 1220 const cMallocDef = ` 1221 func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer { 1222 return _cgo_runtime_cmalloc(uintptr(n)) 1223 } 1224 ` 1225 1226 var builtinDefs = map[string]string{ 1227 "GoString": goStringDef, 1228 "GoStringN": goStringNDef, 1229 "GoBytes": goBytesDef, 1230 "CString": cStringDef, 1231 "_CMalloc": cMallocDef, 1232 } 1233 1234 func (p *Package) cPrologGccgo() string { 1235 return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1) 1236 } 1237 1238 const cPrologGccgo = ` 1239 #include <stdint.h> 1240 #include <stdlib.h> 1241 #include <string.h> 1242 1243 typedef unsigned char byte; 1244 typedef intptr_t intgo; 1245 1246 struct __go_string { 1247 const unsigned char *__data; 1248 intgo __length; 1249 }; 1250 1251 typedef struct __go_open_array { 1252 void* __values; 1253 intgo __count; 1254 intgo __capacity; 1255 } Slice; 1256 1257 struct __go_string __go_byte_array_to_string(const void* p, intgo len); 1258 struct __go_open_array __go_string_to_byte_array (struct __go_string str); 1259 1260 const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) { 1261 char *p = malloc(s.__length+1); 1262 memmove(p, s.__data, s.__length); 1263 p[s.__length] = 0; 1264 return p; 1265 } 1266 1267 struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) { 1268 intgo len = (p != NULL) ? strlen(p) : 0; 1269 return __go_byte_array_to_string(p, len); 1270 } 1271 1272 struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) { 1273 return __go_byte_array_to_string(p, n); 1274 } 1275 1276 Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) { 1277 struct __go_string s = { (const unsigned char *)p, n }; 1278 return __go_string_to_byte_array(s); 1279 } 1280 1281 extern void runtime_throw(const char *); 1282 void *_cgoPREFIX_Cfunc__CMalloc(size_t n) { 1283 void *p = malloc(n); 1284 if(p == NULL && n == 0) 1285 p = malloc(1); 1286 if(p == NULL) 1287 runtime_throw("runtime: C malloc failed"); 1288 return p; 1289 } 1290 ` 1291 1292 func (p *Package) gccExportHeaderProlog() string { 1293 return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1) 1294 } 1295 1296 const gccExportHeaderProlog = ` 1297 typedef signed char GoInt8; 1298 typedef unsigned char GoUint8; 1299 typedef short GoInt16; 1300 typedef unsigned short GoUint16; 1301 typedef int GoInt32; 1302 typedef unsigned int GoUint32; 1303 typedef long long GoInt64; 1304 typedef unsigned long long GoUint64; 1305 typedef GoIntGOINTBITS GoInt; 1306 typedef GoUintGOINTBITS GoUint; 1307 typedef __SIZE_TYPE__ GoUintptr; 1308 typedef float GoFloat32; 1309 typedef double GoFloat64; 1310 typedef __complex float GoComplex64; 1311 typedef __complex double GoComplex128; 1312 1313 typedef struct { char *p; GoInt n; } GoString; 1314 typedef void *GoMap; 1315 typedef void *GoChan; 1316 typedef struct { void *t; void *v; } GoInterface; 1317 typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 1318 `