github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/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 and gcc. 25 // (The comments here say 6g 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 fmt.Fprintf(fm, "void _cgo_reginit(void) { }\n") 64 65 // Write second Go output: definitions of _C_xxx. 66 // In a separate file so that the import of "unsafe" does not 67 // pollute the original file. 68 fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") 69 fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) 70 fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") 71 if !*gccgo && *importRuntimeCgo { 72 fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") 73 } 74 if *importSyscall { 75 fmt.Fprintf(fgo2, "import \"syscall\"\n\n") 76 fmt.Fprintf(fgo2, "var _ syscall.Errno\n") 77 } 78 fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") 79 80 typedefNames := make([]string, 0, len(typedef)) 81 for name := range typedef { 82 typedefNames = append(typedefNames, name) 83 } 84 sort.Strings(typedefNames) 85 for _, name := range typedefNames { 86 def := typedef[name] 87 fmt.Fprintf(fgo2, "type %s ", name) 88 conf.Fprint(fgo2, fset, def.Go) 89 fmt.Fprintf(fgo2, "\n\n") 90 } 91 if *gccgo { 92 fmt.Fprintf(fgo2, "type _Ctype_void byte\n") 93 } else { 94 fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n") 95 } 96 97 if *gccgo { 98 fmt.Fprint(fc, p.cPrologGccgo()) 99 } else { 100 fmt.Fprint(fgo2, goProlog) 101 } 102 103 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 104 105 cVars := make(map[string]bool) 106 for _, key := range nameKeys(p.Name) { 107 n := p.Name[key] 108 if !n.IsVar() { 109 continue 110 } 111 112 if !cVars[n.C] { 113 fmt.Fprintf(fm, "extern char %s[];\n", n.C) 114 fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) 115 if *gccgo { 116 fmt.Fprintf(fc, "extern byte *%s;\n", n.C) 117 } else { 118 fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C) 119 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C) 120 fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C) 121 } 122 cVars[n.C] = true 123 } 124 125 var node ast.Node 126 if n.Kind == "var" { 127 node = &ast.StarExpr{X: n.Type.Go} 128 } else if n.Kind == "fpvar" { 129 node = n.Type.Go 130 } else { 131 panic(fmt.Errorf("invalid var kind %q", n.Kind)) 132 } 133 if *gccgo { 134 fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) 135 fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C) 136 fmt.Fprintf(fc, "\n") 137 } 138 139 fmt.Fprintf(fgo2, "var %s ", n.Mangle) 140 conf.Fprint(fgo2, fset, node) 141 if !*gccgo { 142 fmt.Fprintf(fgo2, " = (") 143 conf.Fprint(fgo2, fset, node) 144 fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C) 145 } 146 fmt.Fprintf(fgo2, "\n") 147 } 148 if *gccgo { 149 fmt.Fprintf(fc, "\n") 150 } 151 152 for _, key := range nameKeys(p.Name) { 153 n := p.Name[key] 154 if n.Const != "" { 155 fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const) 156 } 157 } 158 fmt.Fprintf(fgo2, "\n") 159 160 for _, key := range nameKeys(p.Name) { 161 n := p.Name[key] 162 if n.FuncType != nil { 163 p.writeDefsFunc(fgo2, n) 164 } 165 } 166 167 if *gccgo { 168 p.writeGccgoExports(fgo2, fm) 169 } else { 170 p.writeExports(fgo2, fm) 171 } 172 173 init := gccgoInit.String() 174 if init != "" { 175 fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));") 176 fmt.Fprintln(fc, "static void init(void) {") 177 fmt.Fprint(fc, init) 178 fmt.Fprintln(fc, "}") 179 } 180 } 181 182 func dynimport(obj string) { 183 stdout := os.Stdout 184 if *dynout != "" { 185 f, err := os.Create(*dynout) 186 if err != nil { 187 fatalf("%s", err) 188 } 189 stdout = f 190 } 191 192 fmt.Fprintf(stdout, "package %s\n", *dynpackage) 193 194 if f, err := elf.Open(obj); err == nil { 195 if *dynlinker { 196 // Emit the cgo_dynamic_linker line. 197 if sec := f.Section(".interp"); sec != nil { 198 if data, err := sec.Data(); err == nil && len(data) > 1 { 199 // skip trailing \0 in data 200 fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1])) 201 } 202 } 203 } 204 sym, err := f.ImportedSymbols() 205 if err != nil { 206 fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) 207 } 208 for _, s := range sym { 209 targ := s.Name 210 if s.Version != "" { 211 targ += "#" + s.Version 212 } 213 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) 214 } 215 lib, err := f.ImportedLibraries() 216 if err != nil { 217 fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) 218 } 219 for _, l := range lib { 220 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 221 } 222 return 223 } 224 225 if f, err := macho.Open(obj); err == nil { 226 sym, err := f.ImportedSymbols() 227 if err != nil { 228 fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) 229 } 230 for _, s := range sym { 231 if len(s) > 0 && s[0] == '_' { 232 s = s[1:] 233 } 234 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "") 235 } 236 lib, err := f.ImportedLibraries() 237 if err != nil { 238 fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) 239 } 240 for _, l := range lib { 241 fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) 242 } 243 return 244 } 245 246 if f, err := pe.Open(obj); err == nil { 247 sym, err := f.ImportedSymbols() 248 if err != nil { 249 fatalf("cannot load imported symbols from PE file %s: %v", obj, err) 250 } 251 for _, s := range sym { 252 ss := strings.Split(s, ":") 253 name := strings.Split(ss[0], "@")[0] 254 fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) 255 } 256 return 257 } 258 259 fatalf("cannot parse %s as ELF, Mach-O or PE", obj) 260 } 261 262 // Construct a gcc struct matching the 6g argument frame. 263 // Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. 264 // These assumptions are checked by the gccProlog. 265 // Also assumes that 6g convention is to word-align the 266 // input and output parameters. 267 func (p *Package) structType(n *Name) (string, int64) { 268 var buf bytes.Buffer 269 fmt.Fprint(&buf, "struct {\n") 270 off := int64(0) 271 for i, t := range n.FuncType.Params { 272 if off%t.Align != 0 { 273 pad := t.Align - off%t.Align 274 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 275 off += pad 276 } 277 c := t.Typedef 278 if c == "" { 279 c = t.C.String() 280 } 281 fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i) 282 off += t.Size 283 } 284 if off%p.PtrSize != 0 { 285 pad := p.PtrSize - off%p.PtrSize 286 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 287 off += pad 288 } 289 if t := n.FuncType.Result; t != nil { 290 if off%t.Align != 0 { 291 pad := t.Align - off%t.Align 292 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 293 off += pad 294 } 295 qual := "" 296 if c := t.C.String(); c[len(c)-1] == '*' { 297 qual = "const " 298 } 299 fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) 300 off += t.Size 301 } 302 if off%p.PtrSize != 0 { 303 pad := p.PtrSize - off%p.PtrSize 304 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 305 off += pad 306 } 307 if off == 0 { 308 fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct 309 } 310 fmt.Fprintf(&buf, "\t}") 311 return buf.String(), off 312 } 313 314 func (p *Package) writeDefsFunc(fgo2 io.Writer, n *Name) { 315 name := n.Go 316 gtype := n.FuncType.Go 317 void := gtype.Results == nil || len(gtype.Results.List) == 0 318 if n.AddError { 319 // Add "error" to return type list. 320 // Type list is known to be 0 or 1 element - it's a C function. 321 err := &ast.Field{Type: ast.NewIdent("error")} 322 l := gtype.Results.List 323 if len(l) == 0 { 324 l = []*ast.Field{err} 325 } else { 326 l = []*ast.Field{l[0], err} 327 } 328 t := new(ast.FuncType) 329 *t = *gtype 330 t.Results = &ast.FieldList{List: l} 331 gtype = t 332 } 333 334 // Go func declaration. 335 d := &ast.FuncDecl{ 336 Name: ast.NewIdent(n.Mangle), 337 Type: gtype, 338 } 339 340 // Builtins defined in the C prolog. 341 inProlog := builtinDefs[name] != "" 342 cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) 343 paramnames := []string(nil) 344 for i, param := range d.Type.Params.List { 345 paramName := fmt.Sprintf("p%d", i) 346 param.Names = []*ast.Ident{ast.NewIdent(paramName)} 347 paramnames = append(paramnames, paramName) 348 } 349 350 if *gccgo { 351 // Gccgo style hooks. 352 fmt.Fprint(fgo2, "\n") 353 conf.Fprint(fgo2, fset, d) 354 fmt.Fprint(fgo2, " {\n") 355 if !inProlog { 356 fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n") 357 fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n") 358 } 359 if n.AddError { 360 fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n") 361 } 362 fmt.Fprint(fgo2, "\t") 363 if !void { 364 fmt.Fprint(fgo2, "r := ") 365 } 366 fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", ")) 367 368 if n.AddError { 369 fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n") 370 fmt.Fprint(fgo2, "\tif e != 0 {\n") 371 fmt.Fprint(fgo2, "\t\treturn ") 372 if !void { 373 fmt.Fprint(fgo2, "r, ") 374 } 375 fmt.Fprint(fgo2, "e\n") 376 fmt.Fprint(fgo2, "\t}\n") 377 fmt.Fprint(fgo2, "\treturn ") 378 if !void { 379 fmt.Fprint(fgo2, "r, ") 380 } 381 fmt.Fprint(fgo2, "nil\n") 382 } else if !void { 383 fmt.Fprint(fgo2, "\treturn r\n") 384 } 385 386 fmt.Fprint(fgo2, "}\n") 387 388 // declare the C function. 389 fmt.Fprintf(fgo2, "//extern %s\n", cname) 390 d.Name = ast.NewIdent(cname) 391 if n.AddError { 392 l := d.Type.Results.List 393 d.Type.Results.List = l[:len(l)-1] 394 } 395 conf.Fprint(fgo2, fset, d) 396 fmt.Fprint(fgo2, "\n") 397 398 return 399 } 400 401 if inProlog { 402 fmt.Fprint(fgo2, builtinDefs[name]) 403 return 404 } 405 406 // C wrapper calls into gcc, passing a pointer to the argument frame. 407 fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname) 408 fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname) 409 fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname) 410 fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname) 411 412 nret := 0 413 if !void { 414 d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")} 415 nret = 1 416 } 417 if n.AddError { 418 d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")} 419 } 420 421 fmt.Fprint(fgo2, "\n") 422 conf.Fprint(fgo2, fset, d) 423 fmt.Fprint(fgo2, " {\n") 424 425 // NOTE: Using uintptr to hide from escape analysis. 426 arg := "0" 427 if len(paramnames) > 0 { 428 arg = "uintptr(unsafe.Pointer(&p0))" 429 } else if !void { 430 arg = "uintptr(unsafe.Pointer(&r1))" 431 } 432 433 prefix := "" 434 if n.AddError { 435 prefix = "errno := " 436 } 437 fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg) 438 if n.AddError { 439 fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") 440 } 441 fmt.Fprintf(fgo2, "\treturn\n") 442 fmt.Fprintf(fgo2, "}\n") 443 } 444 445 // writeOutput creates stubs for a specific source file to be compiled by 6g 446 // (The comments here say 6g but the code applies to the 8 and 5 tools too.) 447 func (p *Package) writeOutput(f *File, srcfile string) { 448 base := srcfile 449 if strings.HasSuffix(base, ".go") { 450 base = base[0 : len(base)-3] 451 } 452 base = strings.Map(slashToUnderscore, base) 453 fgo1 := creat(*objDir + base + ".cgo1.go") 454 fgcc := creat(*objDir + base + ".cgo2.c") 455 456 p.GoFiles = append(p.GoFiles, base+".cgo1.go") 457 p.GccFiles = append(p.GccFiles, base+".cgo2.c") 458 459 // Write Go output: Go input with rewrites of C.xxx to _C_xxx. 460 fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") 461 conf.Fprint(fgo1, fset, f.AST) 462 463 // While we process the vars and funcs, also write gcc output. 464 // Gcc output starts with the preamble. 465 fmt.Fprintf(fgcc, "%s\n", f.Preamble) 466 fmt.Fprintf(fgcc, "%s\n", gccProlog) 467 468 for _, key := range nameKeys(f.Name) { 469 n := f.Name[key] 470 if n.FuncType != nil { 471 p.writeOutputFunc(fgcc, n) 472 } 473 } 474 475 fgo1.Close() 476 fgcc.Close() 477 } 478 479 // fixGo converts the internal Name.Go field into the name we should show 480 // to users in error messages. There's only one for now: on input we rewrite 481 // C.malloc into C._CMalloc, so change it back here. 482 func fixGo(name string) string { 483 if name == "_CMalloc" { 484 return "malloc" 485 } 486 return name 487 } 488 489 var isBuiltin = map[string]bool{ 490 "_Cfunc_CString": true, 491 "_Cfunc_GoString": true, 492 "_Cfunc_GoStringN": true, 493 "_Cfunc_GoBytes": true, 494 "_Cfunc__CMalloc": true, 495 } 496 497 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { 498 name := n.Mangle 499 if isBuiltin[name] || p.Written[name] { 500 // The builtins are already defined in the C prolog, and we don't 501 // want to duplicate function definitions we've already done. 502 return 503 } 504 p.Written[name] = true 505 506 if *gccgo { 507 p.writeGccgoOutputFunc(fgcc, n) 508 return 509 } 510 511 ctype, _ := p.structType(n) 512 513 // Gcc wrapper unpacks the C argument struct 514 // and calls the actual C function. 515 if n.AddError { 516 fmt.Fprintf(fgcc, "int\n") 517 } else { 518 fmt.Fprintf(fgcc, "void\n") 519 } 520 fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) 521 fmt.Fprintf(fgcc, "{\n") 522 if n.AddError { 523 fmt.Fprintf(fgcc, "\terrno = 0;\n") 524 } 525 // We're trying to write a gcc struct that matches 6g's layout. 526 // Use packed attribute to force no padding in this struct in case 527 // gcc has different packing requirements. 528 fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) 529 if n.FuncType.Result != nil { 530 // Save the stack top for use below. 531 fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") 532 } 533 fmt.Fprintf(fgcc, "\t") 534 if t := n.FuncType.Result; t != nil { 535 fmt.Fprintf(fgcc, "__typeof__(a->r) r = ") 536 if c := t.C.String(); c[len(c)-1] == '*' { 537 fmt.Fprint(fgcc, "(__typeof__(a->r)) ") 538 } 539 } 540 fmt.Fprintf(fgcc, "%s(", n.C) 541 for i, t := range n.FuncType.Params { 542 if i > 0 { 543 fmt.Fprintf(fgcc, ", ") 544 } 545 // We know the type params are correct, because 546 // the Go equivalents had good type params. 547 // However, our version of the type omits the magic 548 // words const and volatile, which can provoke 549 // C compiler warnings. Silence them by casting 550 // all pointers to void*. (Eventually that will produce 551 // other warnings.) 552 if c := t.C.String(); c[len(c)-1] == '*' { 553 fmt.Fprintf(fgcc, "(void*)") 554 } 555 fmt.Fprintf(fgcc, "a->p%d", i) 556 } 557 fmt.Fprintf(fgcc, ");\n") 558 if n.FuncType.Result != nil { 559 // The cgo call may have caused a stack copy (via a callback). 560 // Adjust the return value pointer appropriately. 561 fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") 562 // Save the return value. 563 fmt.Fprintf(fgcc, "\ta->r = r;\n") 564 } 565 if n.AddError { 566 fmt.Fprintf(fgcc, "\treturn errno;\n") 567 } 568 fmt.Fprintf(fgcc, "}\n") 569 fmt.Fprintf(fgcc, "\n") 570 } 571 572 // Write out a wrapper for a function when using gccgo. This is a 573 // simple wrapper that just calls the real function. We only need a 574 // wrapper to support static functions in the prologue--without a 575 // wrapper, we can't refer to the function, since the reference is in 576 // a different file. 577 func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { 578 if t := n.FuncType.Result; t != nil { 579 fmt.Fprintf(fgcc, "%s\n", t.C.String()) 580 } else { 581 fmt.Fprintf(fgcc, "void\n") 582 } 583 fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle) 584 for i, t := range n.FuncType.Params { 585 if i > 0 { 586 fmt.Fprintf(fgcc, ", ") 587 } 588 c := t.Typedef 589 if c == "" { 590 c = t.C.String() 591 } 592 fmt.Fprintf(fgcc, "%s p%d", c, i) 593 } 594 fmt.Fprintf(fgcc, ")\n") 595 fmt.Fprintf(fgcc, "{\n") 596 fmt.Fprintf(fgcc, "\t") 597 if t := n.FuncType.Result; t != nil { 598 fmt.Fprintf(fgcc, "return ") 599 // Cast to void* to avoid warnings due to omitted qualifiers. 600 if c := t.C.String(); c[len(c)-1] == '*' { 601 fmt.Fprintf(fgcc, "(void*)") 602 } 603 } 604 fmt.Fprintf(fgcc, "%s(", n.C) 605 for i, t := range n.FuncType.Params { 606 if i > 0 { 607 fmt.Fprintf(fgcc, ", ") 608 } 609 // Cast to void* to avoid warnings due to omitted qualifiers. 610 if c := t.C.String(); c[len(c)-1] == '*' { 611 fmt.Fprintf(fgcc, "(void*)") 612 } 613 fmt.Fprintf(fgcc, "p%d", i) 614 } 615 fmt.Fprintf(fgcc, ");\n") 616 fmt.Fprintf(fgcc, "}\n") 617 fmt.Fprintf(fgcc, "\n") 618 } 619 620 // packedAttribute returns host compiler struct attribute that will be 621 // used to match 6g's struct layout. For example, on 386 Windows, 622 // gcc wants to 8-align int64s, but 8g does not. 623 // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, 624 // and http://golang.org/issue/5603. 625 func (p *Package) packedAttribute() string { 626 s := "__attribute__((__packed__" 627 if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") { 628 s += ", __gcc_struct__" 629 } 630 return s + "))" 631 } 632 633 // Write out the various stubs we need to support functions exported 634 // from Go so that they are callable from C. 635 func (p *Package) writeExports(fgo2, fm io.Writer) { 636 fgcc := creat(*objDir + "_cgo_export.c") 637 fgcch := creat(*objDir + "_cgo_export.h") 638 639 fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") 640 fmt.Fprintf(fgcch, "%s\n", p.Preamble) 641 fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) 642 643 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 644 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") 645 646 fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n") 647 648 for _, exp := range p.ExpFunc { 649 fn := exp.Func 650 651 // Construct a gcc struct matching the 6g argument and 652 // result frame. The gcc struct will be compiled with 653 // __attribute__((packed)) so all padding must be accounted 654 // for explicitly. 655 ctype := "struct {\n" 656 off := int64(0) 657 npad := 0 658 if fn.Recv != nil { 659 t := p.cgoType(fn.Recv.List[0].Type) 660 ctype += fmt.Sprintf("\t\t%s recv;\n", t.C) 661 off += t.Size 662 } 663 fntype := fn.Type 664 forFieldList(fntype.Params, 665 func(i int, atype ast.Expr) { 666 t := p.cgoType(atype) 667 if off%t.Align != 0 { 668 pad := t.Align - off%t.Align 669 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 670 off += pad 671 npad++ 672 } 673 ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i) 674 off += t.Size 675 }) 676 if off%p.PtrSize != 0 { 677 pad := p.PtrSize - off%p.PtrSize 678 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 679 off += pad 680 npad++ 681 } 682 forFieldList(fntype.Results, 683 func(i int, atype ast.Expr) { 684 t := p.cgoType(atype) 685 if off%t.Align != 0 { 686 pad := t.Align - off%t.Align 687 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 688 off += pad 689 npad++ 690 } 691 ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i) 692 off += t.Size 693 }) 694 if off%p.PtrSize != 0 { 695 pad := p.PtrSize - off%p.PtrSize 696 ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) 697 off += pad 698 npad++ 699 } 700 if ctype == "struct {\n" { 701 ctype += "\t\tchar unused;\n" // avoid empty struct 702 } 703 ctype += "\t}" 704 705 // Get the return type of the wrapper function 706 // compiled by gcc. 707 gccResult := "" 708 if fntype.Results == nil || len(fntype.Results.List) == 0 { 709 gccResult = "void" 710 } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 711 gccResult = p.cgoType(fntype.Results.List[0].Type).C.String() 712 } else { 713 fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) 714 fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName) 715 forFieldList(fntype.Results, 716 func(i int, atype ast.Expr) { 717 fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i) 718 }) 719 fmt.Fprintf(fgcch, "};\n") 720 gccResult = "struct " + exp.ExpName + "_return" 721 } 722 723 // Build the wrapper function compiled by gcc. 724 s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) 725 if fn.Recv != nil { 726 s += p.cgoType(fn.Recv.List[0].Type).C.String() 727 s += " recv" 728 } 729 forFieldList(fntype.Params, 730 func(i int, atype ast.Expr) { 731 if i > 0 || fn.Recv != nil { 732 s += ", " 733 } 734 s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) 735 }) 736 s += ")" 737 fmt.Fprintf(fgcch, "\nextern %s;\n", s) 738 739 fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName) 740 fmt.Fprintf(fgcc, "\n%s\n", s) 741 fmt.Fprintf(fgcc, "{\n") 742 fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) 743 if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { 744 fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) 745 } 746 if fn.Recv != nil { 747 fmt.Fprintf(fgcc, "\ta.recv = recv;\n") 748 } 749 forFieldList(fntype.Params, 750 func(i int, atype ast.Expr) { 751 fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) 752 }) 753 fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off) 754 if gccResult != "void" { 755 if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { 756 fmt.Fprintf(fgcc, "\treturn a.r0;\n") 757 } else { 758 forFieldList(fntype.Results, 759 func(i int, atype ast.Expr) { 760 fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i) 761 }) 762 fmt.Fprintf(fgcc, "\treturn r;\n") 763 } 764 } 765 fmt.Fprintf(fgcc, "}\n") 766 767 // Build the wrapper function compiled by 6g. 768 goname := exp.Func.Name.Name 769 if fn.Recv != nil { 770 goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname 771 } 772 fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname) 773 fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName) 774 fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) 775 fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g 776 fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName) 777 fmt.Fprintf(fgo2, "\tfn := %s\n", goname) 778 // The indirect here is converting from a Go function pointer to a C function pointer. 779 fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n") 780 fmt.Fprintf(fgo2, "}\n") 781 782 fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) 783 784 // Calling a function with a receiver from C requires 785 // a Go wrapper function. 786 if fn.Recv != nil { 787 fmt.Fprintf(fgo2, "func %s(recv ", goname) 788 conf.Fprint(fgo2, fset, fn.Recv.List[0].Type) 789 forFieldList(fntype.Params, 790 func(i int, atype ast.Expr) { 791 fmt.Fprintf(fgo2, ", p%d ", i) 792 conf.Fprint(fgo2, fset, atype) 793 }) 794 fmt.Fprintf(fgo2, ")") 795 if gccResult != "void" { 796 fmt.Fprint(fgo2, " (") 797 forFieldList(fntype.Results, 798 func(i int, atype ast.Expr) { 799 if i > 0 { 800 fmt.Fprint(fgo2, ", ") 801 } 802 conf.Fprint(fgo2, fset, atype) 803 }) 804 fmt.Fprint(fgo2, ")") 805 } 806 fmt.Fprint(fgo2, " {\n") 807 fmt.Fprint(fgo2, "\t") 808 if gccResult != "void" { 809 fmt.Fprint(fgo2, "return ") 810 } 811 fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name) 812 forFieldList(fntype.Params, 813 func(i int, atype ast.Expr) { 814 if i > 0 { 815 fmt.Fprint(fgo2, ", ") 816 } 817 fmt.Fprintf(fgo2, "p%d", i) 818 }) 819 fmt.Fprint(fgo2, ")\n") 820 fmt.Fprint(fgo2, "}\n") 821 } 822 } 823 } 824 825 // Write out the C header allowing C code to call exported gccgo functions. 826 func (p *Package) writeGccgoExports(fgo2, fm io.Writer) { 827 fgcc := creat(*objDir + "_cgo_export.c") 828 fgcch := creat(*objDir + "_cgo_export.h") 829 830 gccgoSymbolPrefix := p.gccgoSymbolPrefix() 831 832 fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") 833 fmt.Fprintf(fgcch, "%s\n", p.Preamble) 834 fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) 835 836 fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") 837 fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") 838 839 for _, exp := range p.ExpFunc { 840 fn := exp.Func 841 fntype := fn.Type 842 843 cdeclBuf := new(bytes.Buffer) 844 resultCount := 0 845 forFieldList(fntype.Results, 846 func(i int, atype ast.Expr) { resultCount++ }) 847 switch resultCount { 848 case 0: 849 fmt.Fprintf(cdeclBuf, "void") 850 case 1: 851 forFieldList(fntype.Results, 852 func(i int, atype ast.Expr) { 853 t := p.cgoType(atype) 854 fmt.Fprintf(cdeclBuf, "%s", t.C) 855 }) 856 default: 857 // Declare a result struct. 858 fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName) 859 forFieldList(fntype.Results, 860 func(i int, atype ast.Expr) { 861 t := p.cgoType(atype) 862 fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i) 863 }) 864 fmt.Fprintf(fgcch, "};\n") 865 fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName) 866 } 867 868 cRet := cdeclBuf.String() 869 870 cdeclBuf = new(bytes.Buffer) 871 fmt.Fprintf(cdeclBuf, "(") 872 if fn.Recv != nil { 873 fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String()) 874 } 875 // Function parameters. 876 forFieldList(fntype.Params, 877 func(i int, atype ast.Expr) { 878 if i > 0 || fn.Recv != nil { 879 fmt.Fprintf(cdeclBuf, ", ") 880 } 881 t := p.cgoType(atype) 882 fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i) 883 }) 884 fmt.Fprintf(cdeclBuf, ")") 885 cParams := cdeclBuf.String() 886 887 // We need to use a name that will be exported by the 888 // Go code; otherwise gccgo will make it static and we 889 // will not be able to link against it from the C 890 // code. 891 goName := "Cgoexp_" + exp.ExpName 892 fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName) 893 fmt.Fprint(fgcch, "\n") 894 895 // Use a #define so that the C code that includes 896 // cgo_export.h will be able to refer to the Go 897 // function using the expected name. 898 fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName) 899 900 // Use a #undef in _cgo_export.c so that we ignore the 901 // #define from cgo_export.h, since here we are 902 // defining the real function. 903 fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName) 904 905 fmt.Fprint(fgcc, "\n") 906 fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams) 907 fmt.Fprint(fgcc, "\t") 908 if resultCount > 0 { 909 fmt.Fprint(fgcc, "return ") 910 } 911 fmt.Fprintf(fgcc, "%s(", goName) 912 if fn.Recv != nil { 913 fmt.Fprint(fgcc, "recv") 914 } 915 forFieldList(fntype.Params, 916 func(i int, atype ast.Expr) { 917 if i > 0 || fn.Recv != nil { 918 fmt.Fprintf(fgcc, ", ") 919 } 920 fmt.Fprintf(fgcc, "p%d", i) 921 }) 922 fmt.Fprint(fgcc, ");\n") 923 fmt.Fprint(fgcc, "}\n") 924 925 // Dummy declaration for _cgo_main.c 926 fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName) 927 fmt.Fprint(fm, "\n") 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 `