Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(883)

Delta Between Two Patch Sets: src/cmd/cgo/out.go

Issue 9835047: code review 9835047: cmd/cgo: Add support for C function pointers (Closed)
Left Patch Set: diff -r 1faca3687fe6 https://code.google.com/p/go Created 10 years, 10 months ago
Right Patch Set: diff -r d881cb1ffc14 https://code.google.com/p/go Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/cgo/main.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package main 5 package main
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "debug/elf" 9 "debug/elf"
10 "debug/macho" 10 "debug/macho"
(...skipping 14 matching lines...) Expand all
25 func (p *Package) writeDefs() { 25 func (p *Package) writeDefs() {
26 fgo2 := creat(*objDir + "_cgo_gotypes.go") 26 fgo2 := creat(*objDir + "_cgo_gotypes.go")
27 fc := creat(*objDir + "_cgo_defun.c") 27 fc := creat(*objDir + "_cgo_defun.c")
28 fm := creat(*objDir + "_cgo_main.c") 28 fm := creat(*objDir + "_cgo_main.c")
29 29
30 var gccgoInit bytes.Buffer 30 var gccgoInit bytes.Buffer
31 31
32 fflg := creat(*objDir + "_cgo_flags") 32 fflg := creat(*objDir + "_cgo_flags")
33 for k, v := range p.CgoFlags { 33 for k, v := range p.CgoFlags {
34 fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " ")) 34 fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
35 » » if k == "LDFLAGS" { 35 » » if k == "LDFLAGS" && !*gccgo {
36 for _, arg := range v { 36 for _, arg := range v {
37 fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg) 37 fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
38 } 38 }
39 } 39 }
40 } 40 }
41 fflg.Close() 41 fflg.Close()
42 42
43 // Write C main file for using gcc to resolve imports. 43 // Write C main file for using gcc to resolve imports.
44 fmt.Fprintf(fm, "int main() { return 0; }\n") 44 fmt.Fprintf(fm, "int main() { return 0; }\n")
45 if *importRuntimeCgo { 45 if *importRuntimeCgo {
46 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n") 46 fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
47 } else { 47 } else {
48 // If we're not importing runtime/cgo, we *are* runtime/cgo, 48 // If we're not importing runtime/cgo, we *are* runtime/cgo,
49 // which provides crosscall2. We just need a prototype. 49 // which provides crosscall2. We just need a prototype.
50 » » fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);") 50 » » fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n")
51 } 51 }
52 fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") 52 fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
53 fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") 53 fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n")
54 54
55 // Write second Go output: definitions of _C_xxx. 55 // Write second Go output: definitions of _C_xxx.
56 // In a separate file so that the import of "unsafe" does not 56 // In a separate file so that the import of "unsafe" does not
57 // pollute the original file. 57 // pollute the original file.
58 fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") 58 fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n")
59 fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) 59 fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
60 fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") 60 fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 for _, key := range nameKeys(p.Name) { 98 for _, key := range nameKeys(p.Name) {
99 n := p.Name[key] 99 n := p.Name[key]
100 if !n.IsVar() { 100 if !n.IsVar() {
101 continue 101 continue
102 } 102 }
103 103
104 if !cVars[n.C] { 104 if !cVars[n.C] {
105 fmt.Fprintf(fm, "extern char %s[];\n", n.C) 105 fmt.Fprintf(fm, "extern char %s[];\n", n.C)
106 fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) 106 fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
107 107
108 » » » fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C) 108 » » » if !*gccgo {
109 » » » » fmt.Fprintf(fc, "#pragma cgo_import_static %s\n" , n.C)
110 » » » }
111
109 fmt.Fprintf(fc, "extern byte *%s;\n", n.C) 112 fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
110 113
111 cVars[n.C] = true 114 cVars[n.C] = true
112 } 115 }
113 var amp string 116 var amp string
114 var node ast.Node 117 var node ast.Node
115 if n.Kind == "var" { 118 if n.Kind == "var" {
116 amp = "&" 119 amp = "&"
117 node = &ast.StarExpr{X: n.Type.Go} 120 node = &ast.StarExpr{X: n.Type.Go}
118 } else if n.Kind == "fpvar" { 121 } else if n.Kind == "fpvar" {
119 node = n.Type.Go 122 node = n.Type.Go
120 } else { 123 } else {
121 » » » panic(fmt.Errorf("Invalid var kind %q", n.Kind)) 124 » » » panic(fmt.Errorf("invalid var kind %q", n.Kind))
122 } 125 }
123 if *gccgo { 126 if *gccgo {
124 fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.M angle, gccgoSymbolPrefix, n.Mangle) 127 fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.M angle, gccgoSymbolPrefix, n.Mangle)
125 fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C) 128 fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
126 } else { 129 } else {
127 fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n. C) 130 fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n. C)
128 } 131 }
129 fmt.Fprintf(fc, "\n") 132 fmt.Fprintf(fc, "\n")
130 133
131 fmt.Fprintf(fgo2, "var %s ", n.Mangle) 134 fmt.Fprintf(fgo2, "var %s ", n.Mangle)
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 } 287 }
285 fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) 288 fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
286 off += t.Size 289 off += t.Size
287 } 290 }
288 if off%p.PtrSize != 0 { 291 if off%p.PtrSize != 0 {
289 pad := p.PtrSize - off%p.PtrSize 292 pad := p.PtrSize - off%p.PtrSize
290 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) 293 fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
291 off += pad 294 off += pad
292 } 295 }
293 if n.AddError { 296 if n.AddError {
294 » » fmt.Fprint(&buf, "\t\tvoid *e[2]; /* error */\n") 297 » » fmt.Fprint(&buf, "\t\tint e[2*sizeof(void *)/sizeof(int)]; /* er ror */\n")
295 off += 2 * p.PtrSize 298 off += 2 * p.PtrSize
296 } 299 }
297 if off == 0 { 300 if off == 0 {
298 fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct 301 fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct
299 } 302 }
300 fmt.Fprintf(&buf, "\t}") 303 fmt.Fprintf(&buf, "\t}")
301 return buf.String(), off 304 return buf.String(), off
302 } 305 }
303 306
304 func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { 307 func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
(...skipping 15 matching lines...) Expand all
320 t.Results = &ast.FieldList{List: l} 323 t.Results = &ast.FieldList{List: l}
321 gtype = t 324 gtype = t
322 } 325 }
323 326
324 // Go func declaration. 327 // Go func declaration.
325 d := &ast.FuncDecl{ 328 d := &ast.FuncDecl{
326 Name: ast.NewIdent(n.Mangle), 329 Name: ast.NewIdent(n.Mangle),
327 Type: gtype, 330 Type: gtype,
328 } 331 }
329 332
333 // Builtins defined in the C prolog.
334 inProlog := name == "CString" || name == "GoString" || name == "GoString N" || name == "GoBytes"
335
330 if *gccgo { 336 if *gccgo {
331 // Gccgo style hooks. 337 // Gccgo style hooks.
332 fmt.Fprint(fgo2, "\n") 338 fmt.Fprint(fgo2, "\n")
333 cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) 339 cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle)
334 paramnames := []string(nil) 340 paramnames := []string(nil)
335 for i, param := range d.Type.Params.List { 341 for i, param := range d.Type.Params.List {
336 paramName := fmt.Sprintf("p%d", i) 342 paramName := fmt.Sprintf("p%d", i)
337 param.Names = []*ast.Ident{ast.NewIdent(paramName)} 343 param.Names = []*ast.Ident{ast.NewIdent(paramName)}
338 paramnames = append(paramnames, paramName) 344 paramnames = append(paramnames, paramName)
339 } 345 }
340 346
341 conf.Fprint(fgo2, fset, d) 347 conf.Fprint(fgo2, fset, d)
342 fmt.Fprint(fgo2, " {\n") 348 fmt.Fprint(fgo2, " {\n")
343 » » fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n") 349 » » if !inProlog {
344 » » fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n") 350 » » » fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n")
351 » » » fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n")
352 » » }
345 if n.AddError { 353 if n.AddError {
346 fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n") 354 fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n")
347 } 355 }
348 fmt.Fprint(fgo2, "\t") 356 fmt.Fprint(fgo2, "\t")
349 if !void { 357 if !void {
350 fmt.Fprint(fgo2, "r := ") 358 fmt.Fprint(fgo2, "r := ")
351 } 359 }
352 fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", ")) 360 fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", "))
353 361
354 if n.AddError { 362 if n.AddError {
(...skipping 10 matching lines...) Expand all
365 fmt.Fprint(fgo2, "r, ") 373 fmt.Fprint(fgo2, "r, ")
366 } 374 }
367 fmt.Fprint(fgo2, "nil\n") 375 fmt.Fprint(fgo2, "nil\n")
368 } else if !void { 376 } else if !void {
369 fmt.Fprint(fgo2, "\treturn r\n") 377 fmt.Fprint(fgo2, "\treturn r\n")
370 } 378 }
371 379
372 fmt.Fprint(fgo2, "}\n") 380 fmt.Fprint(fgo2, "}\n")
373 381
374 // declare the C function. 382 // declare the C function.
375 » » fmt.Fprintf(fgo2, "//extern %s\n", n.C) 383 » » if inProlog {
384 » » » fmt.Fprintf(fgo2, "//extern %s\n", n.C)
385 » » } else {
386 » » » fmt.Fprintf(fgo2, "//extern _cgo%s%s\n", cPrefix, n.Mang le)
387 » » }
376 d.Name = ast.NewIdent(cname) 388 d.Name = ast.NewIdent(cname)
377 if n.AddError { 389 if n.AddError {
378 l := d.Type.Results.List 390 l := d.Type.Results.List
379 d.Type.Results.List = l[:len(l)-1] 391 d.Type.Results.List = l[:len(l)-1]
380 } 392 }
381 conf.Fprint(fgo2, fset, d) 393 conf.Fprint(fgo2, fset, d)
382 fmt.Fprint(fgo2, "\n") 394 fmt.Fprint(fgo2, "\n")
383 395
384 return 396 return
385 } 397 }
386 conf.Fprint(fgo2, fset, d) 398 conf.Fprint(fgo2, fset, d)
387 fmt.Fprint(fgo2, "\n") 399 fmt.Fprint(fgo2, "\n")
388 400
389 » if name == "CString" || name == "GoString" || name == "GoStringN" || nam e == "GoBytes" { 401 » if inProlog {
390 » » // The builtins are already defined in the C prolog.
391 return 402 return
392 } 403 }
393 404
394 var argSize int64 405 var argSize int64
395 _, argSize = p.structType(n) 406 _, argSize = p.structType(n)
396 407
397 // C wrapper calls into gcc, passing a pointer to the argument frame. 408 // C wrapper calls into gcc, passing a pointer to the argument frame.
398 fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangl e) 409 fmt.Fprintf(fc, "#pragma cgo_import_static _cgo%s%s\n", cPrefix, n.Mangl e)
399 fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle) 410 fmt.Fprintf(fc, "void _cgo%s%s(void*);\n", cPrefix, n.Mangle)
400 fmt.Fprintf(fc, "\n") 411 fmt.Fprintf(fc, "\n")
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { 479 func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
469 name := n.Mangle 480 name := n.Mangle
470 if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cf unc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] { 481 if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cf unc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] {
471 // The builtins are already defined in the C prolog, and we don' t 482 // The builtins are already defined in the C prolog, and we don' t
472 // want to duplicate function definitions we've already done. 483 // want to duplicate function definitions we've already done.
473 return 484 return
474 } 485 }
475 p.Written[name] = true 486 p.Written[name] = true
476 487
477 if *gccgo { 488 if *gccgo {
478 » » // we don't use wrappers with gccgo. 489 » » p.writeGccgoOutputFunc(fgcc, n)
479 return 490 return
480 } 491 }
481 492
482 ctype, _ := p.structType(n) 493 ctype, _ := p.structType(n)
483 494
484 // Gcc wrapper unpacks the C argument struct 495 // Gcc wrapper unpacks the C argument struct
485 // and calls the actual C function. 496 // and calls the actual C function.
486 fmt.Fprintf(fgcc, "void\n") 497 fmt.Fprintf(fgcc, "void\n")
487 fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) 498 fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle)
488 fmt.Fprintf(fgcc, "{\n") 499 fmt.Fprintf(fgcc, "{\n")
489 if n.AddError { 500 if n.AddError {
490 fmt.Fprintf(fgcc, "\tint e;\n") // assuming 32 bit (see comment above structType)
491 fmt.Fprintf(fgcc, "\terrno = 0;\n") 501 fmt.Fprintf(fgcc, "\terrno = 0;\n")
492 } 502 }
493 // We're trying to write a gcc struct that matches 6c/8c/5c's layout. 503 // We're trying to write a gcc struct that matches 6c/8c/5c's layout.
494 // Use packed attribute to force no padding in this struct in case 504 // Use packed attribute to force no padding in this struct in case
495 // gcc has different packing requirements. For example, 505 // gcc has different packing requirements. For example,
496 // on 386 Windows, gcc wants to 8-align int64s, but 8c does not. 506 // on 386 Windows, gcc wants to 8-align int64s, but 8c does not.
497 » fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__)) *a = v;\n", ctype) 507 » // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
508 » // and http://golang.org/issue/5603.
509 » extraAttr := ""
510 » if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" | | goarch == "386") {
511 » » extraAttr = ", __gcc_struct__"
512 » }
513 » fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__%v)) *a = v;\n", ctype, extraAttr)
498 fmt.Fprintf(fgcc, "\t") 514 fmt.Fprintf(fgcc, "\t")
499 if t := n.FuncType.Result; t != nil { 515 if t := n.FuncType.Result; t != nil {
500 fmt.Fprintf(fgcc, "a->r = ") 516 fmt.Fprintf(fgcc, "a->r = ")
501 if c := t.C.String(); c[len(c)-1] == '*' { 517 if c := t.C.String(); c[len(c)-1] == '*' {
502 » » » fmt.Fprintf(fgcc, "(const %s) ", t.C) 518 » » » fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
503 } 519 }
504 } 520 }
505 fmt.Fprintf(fgcc, "%s(", n.C) 521 fmt.Fprintf(fgcc, "%s(", n.C)
506 for i, t := range n.FuncType.Params { 522 for i, t := range n.FuncType.Params {
507 if i > 0 { 523 if i > 0 {
508 fmt.Fprintf(fgcc, ", ") 524 fmt.Fprintf(fgcc, ", ")
509 } 525 }
510 // We know the type params are correct, because 526 // We know the type params are correct, because
511 // the Go equivalents had good type params. 527 // the Go equivalents had good type params.
512 // However, our version of the type omits the magic 528 // However, our version of the type omits the magic
513 // words const and volatile, which can provoke 529 // words const and volatile, which can provoke
514 // C compiler warnings. Silence them by casting 530 // C compiler warnings. Silence them by casting
515 // all pointers to void*. (Eventually that will produce 531 // all pointers to void*. (Eventually that will produce
516 // other warnings.) 532 // other warnings.)
517 if c := t.C.String(); c[len(c)-1] == '*' { 533 if c := t.C.String(); c[len(c)-1] == '*' {
518 fmt.Fprintf(fgcc, "(void*)") 534 fmt.Fprintf(fgcc, "(void*)")
519 } 535 }
520 fmt.Fprintf(fgcc, "a->p%d", i) 536 fmt.Fprintf(fgcc, "a->p%d", i)
521 } 537 }
522 fmt.Fprintf(fgcc, ");\n") 538 fmt.Fprintf(fgcc, ");\n")
523 if n.AddError { 539 if n.AddError {
524 fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n") 540 fmt.Fprintf(fgcc, "\t*(int*)(a->e) = errno;\n")
525 } 541 }
542 fmt.Fprintf(fgcc, "}\n")
543 fmt.Fprintf(fgcc, "\n")
544 }
545
546 // Write out a wrapper for a function when using gccgo. This is a
547 // simple wrapper that just calls the real function. We only need a
548 // wrapper to support static functions in the prologue--without a
549 // wrapper, we can't refer to the function, since the reference is in
550 // a different file.
551 func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
552 if t := n.FuncType.Result; t != nil {
553 fmt.Fprintf(fgcc, "%s\n", t.C.String())
554 } else {
555 fmt.Fprintf(fgcc, "void\n")
556 }
557 fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle)
558 for i, t := range n.FuncType.Params {
559 if i > 0 {
560 fmt.Fprintf(fgcc, ", ")
561 }
562 c := t.Typedef
563 if c == "" {
564 c = t.C.String()
565 }
566 fmt.Fprintf(fgcc, "%s p%d", c, i)
567 }
568 fmt.Fprintf(fgcc, ")\n")
569 fmt.Fprintf(fgcc, "{\n")
570 fmt.Fprintf(fgcc, "\t")
571 if t := n.FuncType.Result; t != nil {
572 fmt.Fprintf(fgcc, "return ")
573 // Cast to void* to avoid warnings due to omitted qualifiers.
574 if c := t.C.String(); c[len(c)-1] == '*' {
575 fmt.Fprintf(fgcc, "(void*)")
576 }
577 }
578 fmt.Fprintf(fgcc, "%s(", n.C)
579 for i, t := range n.FuncType.Params {
580 if i > 0 {
581 fmt.Fprintf(fgcc, ", ")
582 }
583 // Cast to void* to avoid warnings due to omitted qualifiers.
584 if c := t.C.String(); c[len(c)-1] == '*' {
585 fmt.Fprintf(fgcc, "(void*)")
586 }
587 fmt.Fprintf(fgcc, "p%d", i)
588 }
589 fmt.Fprintf(fgcc, ");\n")
526 fmt.Fprintf(fgcc, "}\n") 590 fmt.Fprintf(fgcc, "}\n")
527 fmt.Fprintf(fgcc, "\n") 591 fmt.Fprintf(fgcc, "\n")
528 } 592 }
529 593
530 // Write out the various stubs we need to support functions exported 594 // Write out the various stubs we need to support functions exported
531 // from Go so that they are callable from C. 595 // from Go so that they are callable from C.
532 func (p *Package) writeExports(fgo2, fc, fm *os.File) { 596 func (p *Package) writeExports(fgo2, fc, fm *os.File) {
533 fgcc := creat(*objDir + "_cgo_export.c") 597 fgcc := creat(*objDir + "_cgo_export.c")
534 fgcch := creat(*objDir + "_cgo_export.h") 598 fgcch := creat(*objDir + "_cgo_export.h")
535 599
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 typedef double GoFloat64; 1215 typedef double GoFloat64;
1152 typedef __complex float GoComplex64; 1216 typedef __complex float GoComplex64;
1153 typedef __complex double GoComplex128; 1217 typedef __complex double GoComplex128;
1154 1218
1155 typedef struct { char *p; GoInt n; } GoString; 1219 typedef struct { char *p; GoInt n; } GoString;
1156 typedef void *GoMap; 1220 typedef void *GoMap;
1157 typedef void *GoChan; 1221 typedef void *GoChan;
1158 typedef struct { void *t; void *v; } GoInterface; 1222 typedef struct { void *t; void *v; } GoInterface;
1159 typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; 1223 typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
1160 ` 1224 `
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b