2017-03-15 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libgo / go / cmd / cgo / gcc.go
blob5ea2d941ca2ea9f9609c2c3531f7373ebd31aeb4
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.
5 // Annotate Ref in Prog with C types by parsing gcc debug output.
6 // Conversion of debug output to Go types.
8 package main
10 import (
11 "bytes"
12 "debug/dwarf"
13 "debug/elf"
14 "debug/macho"
15 "debug/pe"
16 "encoding/binary"
17 "errors"
18 "flag"
19 "fmt"
20 "go/ast"
21 "go/parser"
22 "go/token"
23 "os"
24 "strconv"
25 "strings"
26 "unicode"
27 "unicode/utf8"
30 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
31 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
33 var nameToC = map[string]string{
34 "schar": "signed char",
35 "uchar": "unsigned char",
36 "ushort": "unsigned short",
37 "uint": "unsigned int",
38 "ulong": "unsigned long",
39 "longlong": "long long",
40 "ulonglong": "unsigned long long",
41 "complexfloat": "float _Complex",
42 "complexdouble": "double _Complex",
45 // cname returns the C name to use for C.s.
46 // The expansions are listed in nameToC and also
47 // struct_foo becomes "struct foo", and similarly for
48 // union and enum.
49 func cname(s string) string {
50 if t, ok := nameToC[s]; ok {
51 return t
54 if strings.HasPrefix(s, "struct_") {
55 return "struct " + s[len("struct_"):]
57 if strings.HasPrefix(s, "union_") {
58 return "union " + s[len("union_"):]
60 if strings.HasPrefix(s, "enum_") {
61 return "enum " + s[len("enum_"):]
63 if strings.HasPrefix(s, "sizeof_") {
64 return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
66 return s
69 // DiscardCgoDirectives processes the import C preamble, and discards
70 // all #cgo CFLAGS and LDFLAGS directives, so they don't make their
71 // way into _cgo_export.h.
72 func (f *File) DiscardCgoDirectives() {
73 linesIn := strings.Split(f.Preamble, "\n")
74 linesOut := make([]string, 0, len(linesIn))
75 for _, line := range linesIn {
76 l := strings.TrimSpace(line)
77 if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
78 linesOut = append(linesOut, line)
79 } else {
80 linesOut = append(linesOut, "")
83 f.Preamble = strings.Join(linesOut, "\n")
86 // addToFlag appends args to flag. All flags are later written out onto the
87 // _cgo_flags file for the build system to use.
88 func (p *Package) addToFlag(flag string, args []string) {
89 p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
90 if flag == "CFLAGS" {
91 // We'll also need these when preprocessing for dwarf information.
92 p.GccOptions = append(p.GccOptions, args...)
96 // splitQuoted splits the string s around each instance of one or more consecutive
97 // white space characters while taking into account quotes and escaping, and
98 // returns an array of substrings of s or an empty list if s contains only white space.
99 // Single quotes and double quotes are recognized to prevent splitting within the
100 // quoted region, and are removed from the resulting substrings. If a quote in s
101 // isn't closed err will be set and r will have the unclosed argument as the
102 // last element. The backslash is used for escaping.
104 // For example, the following string:
106 // `a b:"c d" 'e''f' "g\""`
108 // Would be parsed as:
110 // []string{"a", "b:c d", "ef", `g"`}
112 func splitQuoted(s string) (r []string, err error) {
113 var args []string
114 arg := make([]rune, len(s))
115 escaped := false
116 quoted := false
117 quote := '\x00'
118 i := 0
119 for _, r := range s {
120 switch {
121 case escaped:
122 escaped = false
123 case r == '\\':
124 escaped = true
125 continue
126 case quote != 0:
127 if r == quote {
128 quote = 0
129 continue
131 case r == '"' || r == '\'':
132 quoted = true
133 quote = r
134 continue
135 case unicode.IsSpace(r):
136 if quoted || i > 0 {
137 quoted = false
138 args = append(args, string(arg[:i]))
139 i = 0
141 continue
143 arg[i] = r
146 if quoted || i > 0 {
147 args = append(args, string(arg[:i]))
149 if quote != 0 {
150 err = errors.New("unclosed quote")
151 } else if escaped {
152 err = errors.New("unfinished escaping")
154 return args, err
157 // Translate rewrites f.AST, the original Go input, to remove
158 // references to the imported package C, replacing them with
159 // references to the equivalent Go types, functions, and variables.
160 func (p *Package) Translate(f *File) {
161 for _, cref := range f.Ref {
162 // Convert C.ulong to C.unsigned long, etc.
163 cref.Name.C = cname(cref.Name.Go)
165 p.loadDefines(f)
166 needType := p.guessKinds(f)
167 if len(needType) > 0 {
168 p.loadDWARF(f, needType)
170 if p.rewriteCalls(f) {
171 // Add `import _cgo_unsafe "unsafe"` as the first decl
172 // after the package statement.
173 imp := &ast.GenDecl{
174 Tok: token.IMPORT,
175 Specs: []ast.Spec{
176 &ast.ImportSpec{
177 Name: ast.NewIdent("_cgo_unsafe"),
178 Path: &ast.BasicLit{
179 Kind: token.STRING,
180 Value: `"unsafe"`,
185 f.AST.Decls = append([]ast.Decl{imp}, f.AST.Decls...)
187 p.rewriteRef(f)
190 // loadDefines coerces gcc into spitting out the #defines in use
191 // in the file f and saves relevant renamings in f.Name[name].Define.
192 func (p *Package) loadDefines(f *File) {
193 var b bytes.Buffer
194 b.WriteString(f.Preamble)
195 b.WriteString(builtinProlog)
196 stdout := p.gccDefines(b.Bytes())
198 for _, line := range strings.Split(stdout, "\n") {
199 if len(line) < 9 || line[0:7] != "#define" {
200 continue
203 line = strings.TrimSpace(line[8:])
205 var key, val string
206 spaceIndex := strings.Index(line, " ")
207 tabIndex := strings.Index(line, "\t")
209 if spaceIndex == -1 && tabIndex == -1 {
210 continue
211 } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
212 key = line[0:spaceIndex]
213 val = strings.TrimSpace(line[spaceIndex:])
214 } else {
215 key = line[0:tabIndex]
216 val = strings.TrimSpace(line[tabIndex:])
219 if key == "__clang__" {
220 p.GccIsClang = true
223 if n := f.Name[key]; n != nil {
224 if *debugDefine {
225 fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
227 n.Define = val
232 // guessKinds tricks gcc into revealing the kind of each
233 // name xxx for the references C.xxx in the Go input.
234 // The kind is either a constant, type, or variable.
235 func (p *Package) guessKinds(f *File) []*Name {
236 // Determine kinds for names we already know about,
237 // like #defines or 'struct foo', before bothering with gcc.
238 var names, needType []*Name
239 for _, key := range nameKeys(f.Name) {
240 n := f.Name[key]
241 // If we've already found this name as a #define
242 // and we can translate it as a constant value, do so.
243 if n.Define != "" {
244 isConst := false
245 if _, err := strconv.Atoi(n.Define); err == nil {
246 isConst = true
247 } else if n.Define[0] == '"' || n.Define[0] == '\'' {
248 if _, err := parser.ParseExpr(n.Define); err == nil {
249 isConst = true
252 if isConst {
253 n.Kind = "const"
254 // Turn decimal into hex, just for consistency
255 // with enum-derived constants. Otherwise
256 // in the cgo -godefs output half the constants
257 // are in hex and half are in whatever the #define used.
258 i, err := strconv.ParseInt(n.Define, 0, 64)
259 if err == nil {
260 n.Const = fmt.Sprintf("%#x", i)
261 } else {
262 n.Const = n.Define
264 continue
267 if isName(n.Define) {
268 n.C = n.Define
272 needType = append(needType, n)
274 // If this is a struct, union, or enum type name, no need to guess the kind.
275 if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
276 n.Kind = "type"
277 continue
280 // Otherwise, we'll need to find out from gcc.
281 names = append(names, n)
284 // Bypass gcc if there's nothing left to find out.
285 if len(names) == 0 {
286 return needType
289 // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
290 // For names, find out whether they are integer constants.
291 // We used to look at specific warning or error messages here, but that tied the
292 // behavior too closely to specific versions of the compilers.
293 // Instead, arrange that we can infer what we need from only the presence or absence
294 // of an error on a specific line.
296 // For each name, we generate these lines, where xxx is the index in toSniff plus one.
298 // #line xxx "not-declared"
299 // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
300 // #line xxx "not-type"
301 // void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
302 // #line xxx "not-const"
303 // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
305 // If we see an error at not-declared:xxx, the corresponding name is not declared.
306 // If we see an error at not-type:xxx, the corresponding name is a type.
307 // If we see an error at not-const:xxx, the corresponding name is not an integer constant.
308 // If we see no errors, we assume the name is an expression but not a constant
309 // (so a variable or a function).
311 // The specific input forms are chosen so that they are valid C syntax regardless of
312 // whether name denotes a type or an expression.
314 var b bytes.Buffer
315 b.WriteString(f.Preamble)
316 b.WriteString(builtinProlog)
318 for i, n := range names {
319 fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
320 "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
321 "#line %d \"not-type\"\n"+
322 "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
323 "#line %d \"not-const\"\n"+
324 "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
325 i+1, i+1, n.C,
326 i+1, i+1, n.C,
327 i+1, i+1, n.C)
329 fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
330 "int __cgo__1 = __cgo__2;\n")
332 stderr := p.gccErrors(b.Bytes())
333 if stderr == "" {
334 fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
337 completed := false
338 sniff := make([]int, len(names))
339 const (
340 notType = 1 << iota
341 notConst
342 notDeclared
344 for _, line := range strings.Split(stderr, "\n") {
345 if !strings.Contains(line, ": error:") {
346 // we only care about errors.
347 // we tried to turn off warnings on the command line, but one never knows.
348 continue
351 c1 := strings.Index(line, ":")
352 if c1 < 0 {
353 continue
355 c2 := strings.Index(line[c1+1:], ":")
356 if c2 < 0 {
357 continue
359 c2 += c1 + 1
361 filename := line[:c1]
362 i, _ := strconv.Atoi(line[c1+1 : c2])
364 if i < 0 || i >= len(names) {
365 continue
368 switch filename {
369 case "completed":
370 // Strictly speaking, there is no guarantee that seeing the error at completed:1
371 // (at the end of the file) means we've seen all the errors from earlier in the file,
372 // but usually it does. Certainly if we don't see the completed:1 error, we did
373 // not get all the errors we expected.
374 completed = true
376 case "not-declared":
377 sniff[i] |= notDeclared
378 case "not-type":
379 sniff[i] |= notType
380 case "not-const":
381 sniff[i] |= notConst
385 if !completed {
386 fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr)
389 for i, n := range names {
390 switch sniff[i] {
391 default:
392 error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
393 case notType:
394 n.Kind = "const"
395 case notConst:
396 n.Kind = "type"
397 case notConst | notType:
398 n.Kind = "not-type"
401 if nerrors > 0 {
402 // Check if compiling the preamble by itself causes any errors,
403 // because the messages we've printed out so far aren't helpful
404 // to users debugging preamble mistakes. See issue 8442.
405 preambleErrors := p.gccErrors([]byte(f.Preamble))
406 if len(preambleErrors) > 0 {
407 error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
410 fatalf("unresolved names")
413 needType = append(needType, names...)
414 return needType
417 // loadDWARF parses the DWARF debug information generated
418 // by gcc to learn the details of the constants, variables, and types
419 // being referred to as C.xxx.
420 func (p *Package) loadDWARF(f *File, names []*Name) {
421 // Extract the types from the DWARF section of an object
422 // from a well-formed C program. Gcc only generates DWARF info
423 // for symbols in the object file, so it is not enough to print the
424 // preamble and hope the symbols we care about will be there.
425 // Instead, emit
426 // __typeof__(names[i]) *__cgo__i;
427 // for each entry in names and then dereference the type we
428 // learn for __cgo__i.
429 var b bytes.Buffer
430 b.WriteString(f.Preamble)
431 b.WriteString(builtinProlog)
432 b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
433 for i, n := range names {
434 fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
435 if n.Kind == "const" {
436 fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
440 // Apple's LLVM-based gcc does not include the enumeration
441 // names and values in its DWARF debug output. In case we're
442 // using such a gcc, create a data block initialized with the values.
443 // We can read them out of the object file.
444 fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
445 for _, n := range names {
446 if n.Kind == "const" {
447 fmt.Fprintf(&b, "\t%s,\n", n.C)
448 } else {
449 fmt.Fprintf(&b, "\t0,\n")
452 // for the last entry, we cannot use 0, otherwise
453 // in case all __cgodebug_data is zero initialized,
454 // LLVM-based gcc will place the it in the __DATA.__common
455 // zero-filled section (our debug/macho doesn't support
456 // this)
457 fmt.Fprintf(&b, "\t1\n")
458 fmt.Fprintf(&b, "};\n")
460 d, bo, debugData := p.gccDebug(b.Bytes())
461 enumVal := make([]int64, len(debugData)/8)
462 for i := range enumVal {
463 enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
466 // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
467 types := make([]dwarf.Type, len(names))
468 enums := make([]dwarf.Offset, len(names))
469 nameToIndex := make(map[*Name]int)
470 for i, n := range names {
471 nameToIndex[n] = i
473 nameToRef := make(map[*Name]*Ref)
474 for _, ref := range f.Ref {
475 nameToRef[ref.Name] = ref
477 r := d.Reader()
478 for {
479 e, err := r.Next()
480 if err != nil {
481 fatalf("reading DWARF entry: %s", err)
483 if e == nil {
484 break
486 switch e.Tag {
487 case dwarf.TagEnumerationType:
488 offset := e.Offset
489 for {
490 e, err := r.Next()
491 if err != nil {
492 fatalf("reading DWARF entry: %s", err)
494 if e.Tag == 0 {
495 break
497 if e.Tag == dwarf.TagEnumerator {
498 entryName := e.Val(dwarf.AttrName).(string)
499 if strings.HasPrefix(entryName, "__cgo_enum__") {
500 n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
501 if 0 <= n && n < len(names) {
502 enums[n] = offset
507 case dwarf.TagVariable:
508 name, _ := e.Val(dwarf.AttrName).(string)
509 typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
510 if name == "" || typOff == 0 {
511 if e.Val(dwarf.AttrSpecification) != nil {
512 // Since we are reading all the DWARF,
513 // assume we will see the variable elsewhere.
514 break
516 fatalf("malformed DWARF TagVariable entry")
518 if !strings.HasPrefix(name, "__cgo__") {
519 break
521 typ, err := d.Type(typOff)
522 if err != nil {
523 fatalf("loading DWARF type: %s", err)
525 t, ok := typ.(*dwarf.PtrType)
526 if !ok || t == nil {
527 fatalf("internal error: %s has non-pointer type", name)
529 i, err := strconv.Atoi(name[7:])
530 if err != nil {
531 fatalf("malformed __cgo__ name: %s", name)
533 if enums[i] != 0 {
534 t, err := d.Type(enums[i])
535 if err != nil {
536 fatalf("loading DWARF type: %s", err)
538 types[i] = t
539 } else {
540 types[i] = t.Type
543 if e.Tag != dwarf.TagCompileUnit {
544 r.SkipChildren()
548 // Record types and typedef information.
549 var conv typeConv
550 conv.Init(p.PtrSize, p.IntSize)
551 for i, n := range names {
552 if types[i] == nil {
553 continue
555 pos := token.NoPos
556 if ref, ok := nameToRef[n]; ok {
557 pos = ref.Pos()
559 f, fok := types[i].(*dwarf.FuncType)
560 if n.Kind != "type" && fok {
561 n.Kind = "func"
562 n.FuncType = conv.FuncType(f, pos)
563 } else {
564 n.Type = conv.Type(types[i], pos)
565 if enums[i] != 0 && n.Type.EnumValues != nil {
566 k := fmt.Sprintf("__cgo_enum__%d", i)
567 n.Kind = "const"
568 n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
569 // Remove injected enum to ensure the value will deep-compare
570 // equally in future loads of the same constant.
571 delete(n.Type.EnumValues, k)
573 // Prefer debug data over DWARF debug output, if we have it.
574 if n.Kind == "const" && i < len(enumVal) {
575 n.Const = fmt.Sprintf("%#x", enumVal[i])
578 conv.FinishType(pos)
582 // mangleName does name mangling to translate names
583 // from the original Go source files to the names
584 // used in the final Go files generated by cgo.
585 func (p *Package) mangleName(n *Name) {
586 // When using gccgo variables have to be
587 // exported so that they become global symbols
588 // that the C code can refer to.
589 prefix := "_C"
590 if *gccgo && n.IsVar() {
591 prefix = "C"
593 n.Mangle = prefix + n.Kind + "_" + n.Go
596 // rewriteCalls rewrites all calls that pass pointers to check that
597 // they follow the rules for passing pointers between Go and C.
598 // This returns whether the package needs to import unsafe as _cgo_unsafe.
599 func (p *Package) rewriteCalls(f *File) bool {
600 needsUnsafe := false
601 for _, call := range f.Calls {
602 // This is a call to C.xxx; set goname to "xxx".
603 goname := call.Call.Fun.(*ast.SelectorExpr).Sel.Name
604 if goname == "malloc" {
605 continue
607 name := f.Name[goname]
608 if name.Kind != "func" {
609 // Probably a type conversion.
610 continue
612 if p.rewriteCall(f, call, name) {
613 needsUnsafe = true
616 return needsUnsafe
619 // rewriteCall rewrites one call to add pointer checks.
620 // If any pointer checks are required, we rewrite the call into a
621 // function literal that calls _cgoCheckPointer for each pointer
622 // argument and then calls the original function.
623 // This returns whether the package needs to import unsafe as _cgo_unsafe.
624 func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
625 // Avoid a crash if the number of arguments is
626 // less than the number of parameters.
627 // This will be caught when the generated file is compiled.
628 if len(call.Call.Args) < len(name.FuncType.Params) {
629 return false
632 any := false
633 for i, param := range name.FuncType.Params {
634 if p.needsPointerCheck(f, param.Go, call.Call.Args[i]) {
635 any = true
636 break
639 if !any {
640 return false
643 // We need to rewrite this call.
645 // We are going to rewrite C.f(p) to
646 // func (_cgo0 ptype) {
647 // _cgoCheckPointer(_cgo0)
648 // C.f(_cgo0)
649 // }(p)
650 // Using a function literal like this lets us do correct
651 // argument type checking, and works correctly if the call is
652 // deferred.
653 needsUnsafe := false
654 params := make([]*ast.Field, len(name.FuncType.Params))
655 nargs := make([]ast.Expr, len(name.FuncType.Params))
656 var stmts []ast.Stmt
657 for i, param := range name.FuncType.Params {
658 // params is going to become the parameters of the
659 // function literal.
660 // nargs is going to become the list of arguments made
661 // by the call within the function literal.
662 // nparam is the parameter of the function literal that
663 // corresponds to param.
665 origArg := call.Call.Args[i]
666 nparam := ast.NewIdent(fmt.Sprintf("_cgo%d", i))
667 nargs[i] = nparam
669 // The Go version of the C type might use unsafe.Pointer,
670 // but the file might not import unsafe.
671 // Rewrite the Go type if necessary to use _cgo_unsafe.
672 ptype := p.rewriteUnsafe(param.Go)
673 if ptype != param.Go {
674 needsUnsafe = true
677 params[i] = &ast.Field{
678 Names: []*ast.Ident{nparam},
679 Type: ptype,
682 if !p.needsPointerCheck(f, param.Go, origArg) {
683 continue
686 // Run the cgo pointer checks on nparam.
688 // Change the function literal to call the real function
689 // with the parameter passed through _cgoCheckPointer.
690 c := &ast.CallExpr{
691 Fun: ast.NewIdent("_cgoCheckPointer"),
692 Args: []ast.Expr{
693 nparam,
697 // Add optional additional arguments for an address
698 // expression.
699 c.Args = p.checkAddrArgs(f, c.Args, origArg)
701 stmt := &ast.ExprStmt{
702 X: c,
704 stmts = append(stmts, stmt)
707 fcall := &ast.CallExpr{
708 Fun: call.Call.Fun,
709 Args: nargs,
711 ftype := &ast.FuncType{
712 Params: &ast.FieldList{
713 List: params,
716 if name.FuncType.Result != nil {
717 rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
718 if rtype != name.FuncType.Result.Go {
719 needsUnsafe = true
721 ftype.Results = &ast.FieldList{
722 List: []*ast.Field{
723 &ast.Field{
724 Type: rtype,
730 // There is a Ref pointing to the old call.Call.Fun.
731 for _, ref := range f.Ref {
732 if ref.Expr == &call.Call.Fun {
733 ref.Expr = &fcall.Fun
735 // If this call expects two results, we have to
736 // adjust the results of the function we generated.
737 if ref.Context == "call2" {
738 if ftype.Results == nil {
739 // An explicit void argument
740 // looks odd but it seems to
741 // be how cgo has worked historically.
742 ftype.Results = &ast.FieldList{
743 List: []*ast.Field{
744 &ast.Field{
745 Type: ast.NewIdent("_Ctype_void"),
750 ftype.Results.List = append(ftype.Results.List,
751 &ast.Field{
752 Type: ast.NewIdent("error"),
758 var fbody ast.Stmt
759 if ftype.Results == nil {
760 fbody = &ast.ExprStmt{
761 X: fcall,
763 } else {
764 fbody = &ast.ReturnStmt{
765 Results: []ast.Expr{fcall},
768 call.Call.Fun = &ast.FuncLit{
769 Type: ftype,
770 Body: &ast.BlockStmt{
771 List: append(stmts, fbody),
774 call.Call.Lparen = token.NoPos
775 call.Call.Rparen = token.NoPos
777 return needsUnsafe
780 // needsPointerCheck returns whether the type t needs a pointer check.
781 // This is true if t is a pointer and if the value to which it points
782 // might contain a pointer.
783 func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
784 // An untyped nil does not need a pointer check, and when
785 // _cgoCheckPointer returns the untyped nil the type assertion we
786 // are going to insert will fail. Easier to just skip nil arguments.
787 // TODO: Note that this fails if nil is shadowed.
788 if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
789 return false
792 return p.hasPointer(f, t, true)
795 // hasPointer is used by needsPointerCheck. If top is true it returns
796 // whether t is or contains a pointer that might point to a pointer.
797 // If top is false it returns whether t is or contains a pointer.
798 // f may be nil.
799 func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
800 switch t := t.(type) {
801 case *ast.ArrayType:
802 if t.Len == nil {
803 if !top {
804 return true
806 return p.hasPointer(f, t.Elt, false)
808 return p.hasPointer(f, t.Elt, top)
809 case *ast.StructType:
810 for _, field := range t.Fields.List {
811 if p.hasPointer(f, field.Type, top) {
812 return true
815 return false
816 case *ast.StarExpr: // Pointer type.
817 if !top {
818 return true
820 // Check whether this is a pointer to a C union (or class)
821 // type that contains a pointer.
822 if unionWithPointer[t.X] {
823 return true
825 return p.hasPointer(f, t.X, false)
826 case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
827 return true
828 case *ast.Ident:
829 // TODO: Handle types defined within function.
830 for _, d := range p.Decl {
831 gd, ok := d.(*ast.GenDecl)
832 if !ok || gd.Tok != token.TYPE {
833 continue
835 for _, spec := range gd.Specs {
836 ts, ok := spec.(*ast.TypeSpec)
837 if !ok {
838 continue
840 if ts.Name.Name == t.Name {
841 return p.hasPointer(f, ts.Type, top)
845 if def := typedef[t.Name]; def != nil {
846 return p.hasPointer(f, def.Go, top)
848 if t.Name == "string" {
849 return !top
851 if t.Name == "error" {
852 return true
854 if goTypes[t.Name] != nil {
855 return false
857 // We can't figure out the type. Conservative
858 // approach is to assume it has a pointer.
859 return true
860 case *ast.SelectorExpr:
861 if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
862 // Type defined in a different package.
863 // Conservative approach is to assume it has a
864 // pointer.
865 return true
867 if f == nil {
868 // Conservative approach: assume pointer.
869 return true
871 name := f.Name[t.Sel.Name]
872 if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
873 return p.hasPointer(f, name.Type.Go, top)
875 // We can't figure out the type. Conservative
876 // approach is to assume it has a pointer.
877 return true
878 default:
879 error_(t.Pos(), "could not understand type %s", gofmt(t))
880 return true
884 // checkAddrArgs tries to add arguments to the call of
885 // _cgoCheckPointer when the argument is an address expression. We
886 // pass true to mean that the argument is an address operation of
887 // something other than a slice index, which means that it's only
888 // necessary to check the specific element pointed to, not the entire
889 // object. This is for &s.f, where f is a field in a struct. We can
890 // pass a slice or array, meaning that we should check the entire
891 // slice or array but need not check any other part of the object.
892 // This is for &s.a[i], where we need to check all of a. However, we
893 // only pass the slice or array if we can refer to it without side
894 // effects.
895 func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr {
896 // Strip type conversions.
897 for {
898 c, ok := x.(*ast.CallExpr)
899 if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
900 break
902 x = c.Args[0]
904 u, ok := x.(*ast.UnaryExpr)
905 if !ok || u.Op != token.AND {
906 return args
908 index, ok := u.X.(*ast.IndexExpr)
909 if !ok {
910 // This is the address of something that is not an
911 // index expression. We only need to examine the
912 // single value to which it points.
913 // TODO: what if true is shadowed?
914 return append(args, ast.NewIdent("true"))
916 if !p.hasSideEffects(f, index.X) {
917 // Examine the entire slice.
918 return append(args, index.X)
920 // Treat the pointer as unknown.
921 return args
924 // hasSideEffects returns whether the expression x has any side
925 // effects. x is an expression, not a statement, so the only side
926 // effect is a function call.
927 func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
928 found := false
929 f.walk(x, "expr",
930 func(f *File, x interface{}, context string) {
931 switch x.(type) {
932 case *ast.CallExpr:
933 found = true
936 return found
939 // isType returns whether the expression is definitely a type.
940 // This is conservative--it returns false for an unknown identifier.
941 func (p *Package) isType(t ast.Expr) bool {
942 switch t := t.(type) {
943 case *ast.SelectorExpr:
944 id, ok := t.X.(*ast.Ident)
945 if !ok {
946 return false
948 if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
949 return true
951 if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
952 return true
954 return false
955 case *ast.Ident:
956 // TODO: This ignores shadowing.
957 switch t.Name {
958 case "unsafe.Pointer", "bool", "byte",
959 "complex64", "complex128",
960 "error",
961 "float32", "float64",
962 "int", "int8", "int16", "int32", "int64",
963 "rune", "string",
964 "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
966 return true
968 case *ast.StarExpr:
969 return p.isType(t.X)
970 case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
971 *ast.MapType, *ast.ChanType:
973 return true
975 return false
978 // rewriteUnsafe returns a version of t with references to unsafe.Pointer
979 // rewritten to use _cgo_unsafe.Pointer instead.
980 func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr {
981 switch t := t.(type) {
982 case *ast.Ident:
983 // We don't see a SelectorExpr for unsafe.Pointer;
984 // this is created by code in this file.
985 if t.Name == "unsafe.Pointer" {
986 return ast.NewIdent("_cgo_unsafe.Pointer")
988 case *ast.ArrayType:
989 t1 := p.rewriteUnsafe(t.Elt)
990 if t1 != t.Elt {
991 r := *t
992 r.Elt = t1
993 return &r
995 case *ast.StructType:
996 changed := false
997 fields := *t.Fields
998 fields.List = nil
999 for _, f := range t.Fields.List {
1000 ft := p.rewriteUnsafe(f.Type)
1001 if ft == f.Type {
1002 fields.List = append(fields.List, f)
1003 } else {
1004 fn := *f
1005 fn.Type = ft
1006 fields.List = append(fields.List, &fn)
1007 changed = true
1010 if changed {
1011 r := *t
1012 r.Fields = &fields
1013 return &r
1015 case *ast.StarExpr: // Pointer type.
1016 x1 := p.rewriteUnsafe(t.X)
1017 if x1 != t.X {
1018 r := *t
1019 r.X = x1
1020 return &r
1023 return t
1026 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
1027 // Go equivalents, now that we have figured out the meaning of all
1028 // the xxx. In *godefs mode, rewriteRef replaces the names
1029 // with full definitions instead of mangled names.
1030 func (p *Package) rewriteRef(f *File) {
1031 // Keep a list of all the functions, to remove the ones
1032 // only used as expressions and avoid generating bridge
1033 // code for them.
1034 functions := make(map[string]bool)
1036 // Assign mangled names.
1037 for _, n := range f.Name {
1038 if n.Kind == "not-type" {
1039 n.Kind = "var"
1041 if n.Mangle == "" {
1042 p.mangleName(n)
1044 if n.Kind == "func" {
1045 functions[n.Go] = false
1049 // Now that we have all the name types filled in,
1050 // scan through the Refs to identify the ones that
1051 // are trying to do a ,err call. Also check that
1052 // functions are only used in calls.
1053 for _, r := range f.Ref {
1054 if r.Name.Kind == "const" && r.Name.Const == "" {
1055 error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
1057 var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
1058 switch r.Context {
1059 case "call", "call2":
1060 if r.Name.Kind != "func" {
1061 if r.Name.Kind == "type" {
1062 r.Context = "type"
1063 if r.Name.Type == nil {
1064 error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1065 break
1067 expr = r.Name.Type.Go
1068 break
1070 error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
1071 break
1073 functions[r.Name.Go] = true
1074 if r.Context == "call2" {
1075 if r.Name.Go == "_CMalloc" {
1076 error_(r.Pos(), "no two-result form for C.malloc")
1077 break
1079 // Invent new Name for the two-result function.
1080 n := f.Name["2"+r.Name.Go]
1081 if n == nil {
1082 n = new(Name)
1083 *n = *r.Name
1084 n.AddError = true
1085 n.Mangle = "_C2func_" + n.Go
1086 f.Name["2"+r.Name.Go] = n
1088 expr = ast.NewIdent(n.Mangle)
1089 r.Name = n
1090 break
1092 case "expr":
1093 if r.Name.Kind == "func" {
1094 // Function is being used in an expression, to e.g. pass around a C function pointer.
1095 // Create a new Name for this Ref which causes the variable to be declared in Go land.
1096 fpName := "fp_" + r.Name.Go
1097 name := f.Name[fpName]
1098 if name == nil {
1099 name = &Name{
1100 Go: fpName,
1101 C: r.Name.C,
1102 Kind: "fpvar",
1103 Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
1105 p.mangleName(name)
1106 f.Name[fpName] = name
1108 r.Name = name
1109 // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
1110 // function is defined in out.go and simply returns its argument. See
1111 // issue 7757.
1112 expr = &ast.CallExpr{
1113 Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
1114 Args: []ast.Expr{ast.NewIdent(name.Mangle)},
1116 } else if r.Name.Kind == "type" {
1117 // Okay - might be new(T)
1118 if r.Name.Type == nil {
1119 error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1120 break
1122 expr = r.Name.Type.Go
1123 } else if r.Name.Kind == "var" {
1124 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1127 case "selector":
1128 if r.Name.Kind == "var" {
1129 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1130 } else {
1131 error_(r.Pos(), "only C variables allowed in selector expression %s", fixGo(r.Name.Go))
1134 case "type":
1135 if r.Name.Kind != "type" {
1136 error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
1137 } else if r.Name.Type == nil {
1138 // Use of C.enum_x, C.struct_x or C.union_x without C definition.
1139 // GCC won't raise an error when using pointers to such unknown types.
1140 error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1141 } else {
1142 expr = r.Name.Type.Go
1144 default:
1145 if r.Name.Kind == "func" {
1146 error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
1149 if *godefs {
1150 // Substitute definition for mangled type name.
1151 if id, ok := expr.(*ast.Ident); ok {
1152 if t := typedef[id.Name]; t != nil {
1153 expr = t.Go
1155 if id.Name == r.Name.Mangle && r.Name.Const != "" {
1156 expr = ast.NewIdent(r.Name.Const)
1161 // Copy position information from old expr into new expr,
1162 // in case expression being replaced is first on line.
1163 // See golang.org/issue/6563.
1164 pos := (*r.Expr).Pos()
1165 switch x := expr.(type) {
1166 case *ast.Ident:
1167 expr = &ast.Ident{NamePos: pos, Name: x.Name}
1170 *r.Expr = expr
1173 // Remove functions only used as expressions, so their respective
1174 // bridge functions are not generated.
1175 for name, used := range functions {
1176 if !used {
1177 delete(f.Name, name)
1182 // gccBaseCmd returns the start of the compiler command line.
1183 // It uses $CC if set, or else $GCC, or else the compiler recorded
1184 // during the initial build as defaultCC.
1185 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
1186 func (p *Package) gccBaseCmd() []string {
1187 // Use $CC if set, since that's what the build uses.
1188 if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
1189 return ret
1191 // Try $GCC if set, since that's what we used to use.
1192 if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
1193 return ret
1195 return strings.Fields(defaultCC)
1198 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1199 func (p *Package) gccMachine() []string {
1200 switch goarch {
1201 case "amd64":
1202 return []string{"-m64"}
1203 case "386":
1204 return []string{"-m32"}
1205 case "arm":
1206 return []string{"-marm"} // not thumb
1207 case "s390":
1208 return []string{"-m31"}
1209 case "s390x":
1210 return []string{"-m64"}
1211 case "mips64", "mips64le":
1212 return []string{"-mabi=64"}
1213 case "mips", "mipsle":
1214 return []string{"-mabi=32"}
1216 return nil
1219 func gccTmp() string {
1220 return *objDir + "_cgo_.o"
1223 // gccCmd returns the gcc command line to use for compiling
1224 // the input.
1225 func (p *Package) gccCmd() []string {
1226 c := append(p.gccBaseCmd(),
1227 "-w", // no warnings
1228 "-Wno-error", // warnings are not errors
1229 "-o"+gccTmp(), // write object to tmp
1230 "-gdwarf-2", // generate DWARF v2 debugging symbols
1231 "-c", // do not link
1232 "-xc", // input language is C
1234 if p.GccIsClang {
1235 c = append(c,
1236 "-ferror-limit=0",
1237 // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
1238 // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
1239 // flag to disable the warning. Yes, really good diagnostics, clang.
1240 "-Wno-unknown-warning-option",
1241 "-Wno-unneeded-internal-declaration",
1242 "-Wno-unused-function",
1243 "-Qunused-arguments",
1244 // Clang embeds prototypes for some builtin functions,
1245 // like malloc and calloc, but all size_t parameters are
1246 // incorrectly typed unsigned long. We work around that
1247 // by disabling the builtin functions (this is safe as
1248 // it won't affect the actual compilation of the C code).
1249 // See: https://golang.org/issue/6506.
1250 "-fno-builtin",
1254 c = append(c, p.GccOptions...)
1255 c = append(c, p.gccMachine()...)
1256 c = append(c, "-") //read input from standard input
1257 return c
1260 // gccDebug runs gcc -gdwarf-2 over the C program stdin and
1261 // returns the corresponding DWARF data and, if present, debug data block.
1262 func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
1263 runGcc(stdin, p.gccCmd())
1265 isDebugData := func(s string) bool {
1266 // Some systems use leading _ to denote non-assembly symbols.
1267 return s == "__cgodebug_data" || s == "___cgodebug_data"
1270 if f, err := macho.Open(gccTmp()); err == nil {
1271 defer f.Close()
1272 d, err := f.DWARF()
1273 if err != nil {
1274 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1276 var data []byte
1277 if f.Symtab != nil {
1278 for i := range f.Symtab.Syms {
1279 s := &f.Symtab.Syms[i]
1280 if isDebugData(s.Name) {
1281 // Found it. Now find data section.
1282 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1283 sect := f.Sections[i]
1284 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1285 if sdat, err := sect.Data(); err == nil {
1286 data = sdat[s.Value-sect.Addr:]
1293 return d, f.ByteOrder, data
1296 if f, err := elf.Open(gccTmp()); err == nil {
1297 defer f.Close()
1298 d, err := f.DWARF()
1299 if err != nil {
1300 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1302 var data []byte
1303 symtab, err := f.Symbols()
1304 if err == nil {
1305 for i := range symtab {
1306 s := &symtab[i]
1307 if isDebugData(s.Name) {
1308 // Found it. Now find data section.
1309 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1310 sect := f.Sections[i]
1311 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1312 if sdat, err := sect.Data(); err == nil {
1313 data = sdat[s.Value-sect.Addr:]
1320 return d, f.ByteOrder, data
1323 if f, err := pe.Open(gccTmp()); err == nil {
1324 defer f.Close()
1325 d, err := f.DWARF()
1326 if err != nil {
1327 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1329 var data []byte
1330 for _, s := range f.Symbols {
1331 if isDebugData(s.Name) {
1332 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
1333 sect := f.Sections[i]
1334 if s.Value < sect.Size {
1335 if sdat, err := sect.Data(); err == nil {
1336 data = sdat[s.Value:]
1342 return d, binary.LittleEndian, data
1345 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
1346 panic("not reached")
1349 // gccDefines runs gcc -E -dM -xc - over the C program stdin
1350 // and returns the corresponding standard output, which is the
1351 // #defines that gcc encountered while processing the input
1352 // and its included files.
1353 func (p *Package) gccDefines(stdin []byte) string {
1354 base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
1355 base = append(base, p.gccMachine()...)
1356 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
1357 return stdout
1360 // gccErrors runs gcc over the C program stdin and returns
1361 // the errors that gcc prints. That is, this function expects
1362 // gcc to fail.
1363 func (p *Package) gccErrors(stdin []byte) string {
1364 // TODO(rsc): require failure
1365 args := p.gccCmd()
1367 // Optimization options can confuse the error messages; remove them.
1368 nargs := make([]string, 0, len(args))
1369 for _, arg := range args {
1370 if !strings.HasPrefix(arg, "-O") {
1371 nargs = append(nargs, arg)
1375 if *debugGcc {
1376 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
1377 os.Stderr.Write(stdin)
1378 fmt.Fprint(os.Stderr, "EOF\n")
1380 stdout, stderr, _ := run(stdin, nargs)
1381 if *debugGcc {
1382 os.Stderr.Write(stdout)
1383 os.Stderr.Write(stderr)
1385 return string(stderr)
1388 // runGcc runs the gcc command line args with stdin on standard input.
1389 // If the command exits with a non-zero exit status, runGcc prints
1390 // details about what was run and exits.
1391 // Otherwise runGcc returns the data written to standard output and standard error.
1392 // Note that for some of the uses we expect useful data back
1393 // on standard error, but for those uses gcc must still exit 0.
1394 func runGcc(stdin []byte, args []string) (string, string) {
1395 if *debugGcc {
1396 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
1397 os.Stderr.Write(stdin)
1398 fmt.Fprint(os.Stderr, "EOF\n")
1400 stdout, stderr, ok := run(stdin, args)
1401 if *debugGcc {
1402 os.Stderr.Write(stdout)
1403 os.Stderr.Write(stderr)
1405 if !ok {
1406 os.Stderr.Write(stderr)
1407 os.Exit(2)
1409 return string(stdout), string(stderr)
1412 // A typeConv is a translator from dwarf types to Go types
1413 // with equivalent memory layout.
1414 type typeConv struct {
1415 // Cache of already-translated or in-progress types.
1416 m map[dwarf.Type]*Type
1418 // Map from types to incomplete pointers to those types.
1419 ptrs map[dwarf.Type][]*Type
1420 // Keys of ptrs in insertion order (deterministic worklist)
1421 ptrKeys []dwarf.Type
1423 // Predeclared types.
1424 bool ast.Expr
1425 byte ast.Expr // denotes padding
1426 int8, int16, int32, int64 ast.Expr
1427 uint8, uint16, uint32, uint64, uintptr ast.Expr
1428 float32, float64 ast.Expr
1429 complex64, complex128 ast.Expr
1430 void ast.Expr
1431 string ast.Expr
1432 goVoid ast.Expr // _Ctype_void, denotes C's void
1433 goVoidPtr ast.Expr // unsafe.Pointer or *byte
1435 ptrSize int64
1436 intSize int64
1439 var tagGen int
1440 var typedef = make(map[string]*Type)
1441 var goIdent = make(map[string]*ast.Ident)
1443 // unionWithPointer is true for a Go type that represents a C union (or class)
1444 // that may contain a pointer. This is used for cgo pointer checking.
1445 var unionWithPointer = make(map[ast.Expr]bool)
1447 func (c *typeConv) Init(ptrSize, intSize int64) {
1448 c.ptrSize = ptrSize
1449 c.intSize = intSize
1450 c.m = make(map[dwarf.Type]*Type)
1451 c.ptrs = make(map[dwarf.Type][]*Type)
1452 c.bool = c.Ident("bool")
1453 c.byte = c.Ident("byte")
1454 c.int8 = c.Ident("int8")
1455 c.int16 = c.Ident("int16")
1456 c.int32 = c.Ident("int32")
1457 c.int64 = c.Ident("int64")
1458 c.uint8 = c.Ident("uint8")
1459 c.uint16 = c.Ident("uint16")
1460 c.uint32 = c.Ident("uint32")
1461 c.uint64 = c.Ident("uint64")
1462 c.uintptr = c.Ident("uintptr")
1463 c.float32 = c.Ident("float32")
1464 c.float64 = c.Ident("float64")
1465 c.complex64 = c.Ident("complex64")
1466 c.complex128 = c.Ident("complex128")
1467 c.void = c.Ident("void")
1468 c.string = c.Ident("string")
1469 c.goVoid = c.Ident("_Ctype_void")
1471 // Normally cgo translates void* to unsafe.Pointer,
1472 // but for historical reasons -godefs uses *byte instead.
1473 if *godefs {
1474 c.goVoidPtr = &ast.StarExpr{X: c.byte}
1475 } else {
1476 c.goVoidPtr = c.Ident("unsafe.Pointer")
1480 // base strips away qualifiers and typedefs to get the underlying type
1481 func base(dt dwarf.Type) dwarf.Type {
1482 for {
1483 if d, ok := dt.(*dwarf.QualType); ok {
1484 dt = d.Type
1485 continue
1487 if d, ok := dt.(*dwarf.TypedefType); ok {
1488 dt = d.Type
1489 continue
1491 break
1493 return dt
1496 // unqual strips away qualifiers from a DWARF type.
1497 // In general we don't care about top-level qualifiers.
1498 func unqual(dt dwarf.Type) dwarf.Type {
1499 for {
1500 if d, ok := dt.(*dwarf.QualType); ok {
1501 dt = d.Type
1502 } else {
1503 break
1506 return dt
1509 // Map from dwarf text names to aliases we use in package "C".
1510 var dwarfToName = map[string]string{
1511 "long int": "long",
1512 "long unsigned int": "ulong",
1513 "unsigned int": "uint",
1514 "short unsigned int": "ushort",
1515 "unsigned short": "ushort", // Used by Clang; issue 13129.
1516 "short int": "short",
1517 "long long int": "longlong",
1518 "long long unsigned int": "ulonglong",
1519 "signed char": "schar",
1520 "unsigned char": "uchar",
1523 const signedDelta = 64
1525 // String returns the current type representation. Format arguments
1526 // are assembled within this method so that any changes in mutable
1527 // values are taken into account.
1528 func (tr *TypeRepr) String() string {
1529 if len(tr.Repr) == 0 {
1530 return ""
1532 if len(tr.FormatArgs) == 0 {
1533 return tr.Repr
1535 return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
1538 // Empty reports whether the result of String would be "".
1539 func (tr *TypeRepr) Empty() bool {
1540 return len(tr.Repr) == 0
1543 // Set modifies the type representation.
1544 // If fargs are provided, repr is used as a format for fmt.Sprintf.
1545 // Otherwise, repr is used unprocessed as the type representation.
1546 func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
1547 tr.Repr = repr
1548 tr.FormatArgs = fargs
1551 // FinishType completes any outstanding type mapping work.
1552 // In particular, it resolves incomplete pointer types.
1553 func (c *typeConv) FinishType(pos token.Pos) {
1554 // Completing one pointer type might produce more to complete.
1555 // Keep looping until they're all done.
1556 for len(c.ptrKeys) > 0 {
1557 dtype := c.ptrKeys[0]
1558 c.ptrKeys = c.ptrKeys[1:]
1560 // Note Type might invalidate c.ptrs[dtype].
1561 t := c.Type(dtype, pos)
1562 for _, ptr := range c.ptrs[dtype] {
1563 ptr.Go.(*ast.StarExpr).X = t.Go
1564 ptr.C.Set("%s*", t.C)
1566 c.ptrs[dtype] = nil // retain the map key
1570 // Type returns a *Type with the same memory layout as
1571 // dtype when used as the type of a variable or a struct field.
1572 func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
1573 if t, ok := c.m[dtype]; ok {
1574 if t.Go == nil {
1575 fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
1577 return t
1580 t := new(Type)
1581 t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
1582 t.Align = -1
1583 t.C = &TypeRepr{Repr: dtype.Common().Name}
1584 c.m[dtype] = t
1586 switch dt := dtype.(type) {
1587 default:
1588 fatalf("%s: unexpected type: %s", lineno(pos), dtype)
1590 case *dwarf.AddrType:
1591 if t.Size != c.ptrSize {
1592 fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
1594 t.Go = c.uintptr
1595 t.Align = t.Size
1597 case *dwarf.ArrayType:
1598 if dt.StrideBitSize > 0 {
1599 // Cannot represent bit-sized elements in Go.
1600 t.Go = c.Opaque(t.Size)
1601 break
1603 count := dt.Count
1604 if count == -1 {
1605 // Indicates flexible array member, which Go doesn't support.
1606 // Translate to zero-length array instead.
1607 count = 0
1609 sub := c.Type(dt.Type, pos)
1610 t.Align = sub.Align
1611 t.Go = &ast.ArrayType{
1612 Len: c.intExpr(count),
1613 Elt: sub.Go,
1615 // Recalculate t.Size now that we know sub.Size.
1616 t.Size = count * sub.Size
1617 t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
1619 case *dwarf.BoolType:
1620 t.Go = c.bool
1621 t.Align = 1
1623 case *dwarf.CharType:
1624 if t.Size != 1 {
1625 fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
1627 t.Go = c.int8
1628 t.Align = 1
1630 case *dwarf.EnumType:
1631 if t.Align = t.Size; t.Align >= c.ptrSize {
1632 t.Align = c.ptrSize
1634 t.C.Set("enum " + dt.EnumName)
1635 signed := 0
1636 t.EnumValues = make(map[string]int64)
1637 for _, ev := range dt.Val {
1638 t.EnumValues[ev.Name] = ev.Val
1639 if ev.Val < 0 {
1640 signed = signedDelta
1643 switch t.Size + int64(signed) {
1644 default:
1645 fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
1646 case 1:
1647 t.Go = c.uint8
1648 case 2:
1649 t.Go = c.uint16
1650 case 4:
1651 t.Go = c.uint32
1652 case 8:
1653 t.Go = c.uint64
1654 case 1 + signedDelta:
1655 t.Go = c.int8
1656 case 2 + signedDelta:
1657 t.Go = c.int16
1658 case 4 + signedDelta:
1659 t.Go = c.int32
1660 case 8 + signedDelta:
1661 t.Go = c.int64
1664 case *dwarf.FloatType:
1665 switch t.Size {
1666 default:
1667 fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
1668 case 4:
1669 t.Go = c.float32
1670 case 8:
1671 t.Go = c.float64
1673 if t.Align = t.Size; t.Align >= c.ptrSize {
1674 t.Align = c.ptrSize
1677 case *dwarf.ComplexType:
1678 switch t.Size {
1679 default:
1680 fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
1681 case 8:
1682 t.Go = c.complex64
1683 case 16:
1684 t.Go = c.complex128
1686 if t.Align = t.Size / 2; t.Align >= c.ptrSize {
1687 t.Align = c.ptrSize
1690 case *dwarf.FuncType:
1691 // No attempt at translation: would enable calls
1692 // directly between worlds, but we need to moderate those.
1693 t.Go = c.uintptr
1694 t.Align = c.ptrSize
1696 case *dwarf.IntType:
1697 if dt.BitSize > 0 {
1698 fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
1700 switch t.Size {
1701 default:
1702 fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
1703 case 1:
1704 t.Go = c.int8
1705 case 2:
1706 t.Go = c.int16
1707 case 4:
1708 t.Go = c.int32
1709 case 8:
1710 t.Go = c.int64
1711 case 16:
1712 t.Go = &ast.ArrayType{
1713 Len: c.intExpr(t.Size),
1714 Elt: c.uint8,
1717 if t.Align = t.Size; t.Align >= c.ptrSize {
1718 t.Align = c.ptrSize
1721 case *dwarf.PtrType:
1722 // Clang doesn't emit DW_AT_byte_size for pointer types.
1723 if t.Size != c.ptrSize && t.Size != -1 {
1724 fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
1726 t.Size = c.ptrSize
1727 t.Align = c.ptrSize
1729 if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
1730 t.Go = c.goVoidPtr
1731 t.C.Set("void*")
1732 dq := dt.Type
1733 for {
1734 if d, ok := dq.(*dwarf.QualType); ok {
1735 t.C.Set(d.Qual + " " + t.C.String())
1736 dq = d.Type
1737 } else {
1738 break
1741 break
1744 // Placeholder initialization; completed in FinishType.
1745 t.Go = &ast.StarExpr{}
1746 t.C.Set("<incomplete>*")
1747 if _, ok := c.ptrs[dt.Type]; !ok {
1748 c.ptrKeys = append(c.ptrKeys, dt.Type)
1750 c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
1752 case *dwarf.QualType:
1753 t1 := c.Type(dt.Type, pos)
1754 t.Size = t1.Size
1755 t.Align = t1.Align
1756 t.Go = t1.Go
1757 if unionWithPointer[t1.Go] {
1758 unionWithPointer[t.Go] = true
1760 t.EnumValues = nil
1761 t.Typedef = ""
1762 t.C.Set("%s "+dt.Qual, t1.C)
1763 return t
1765 case *dwarf.StructType:
1766 // Convert to Go struct, being careful about alignment.
1767 // Have to give it a name to simulate C "struct foo" references.
1768 tag := dt.StructName
1769 if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
1770 break
1772 if tag == "" {
1773 tag = "__" + strconv.Itoa(tagGen)
1774 tagGen++
1775 } else if t.C.Empty() {
1776 t.C.Set(dt.Kind + " " + tag)
1778 name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
1779 t.Go = name // publish before recursive calls
1780 goIdent[name.Name] = name
1781 if dt.ByteSize < 0 {
1782 // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
1783 // so execute the basic things that the struct case would do
1784 // other than try to determine a Go representation.
1785 tt := *t
1786 tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
1787 tt.Go = c.Ident("struct{}")
1788 typedef[name.Name] = &tt
1789 break
1791 switch dt.Kind {
1792 case "class", "union":
1793 t.Go = c.Opaque(t.Size)
1794 if c.dwarfHasPointer(dt, pos) {
1795 unionWithPointer[t.Go] = true
1797 if t.C.Empty() {
1798 t.C.Set("__typeof__(unsigned char[%d])", t.Size)
1800 t.Align = 1 // TODO: should probably base this on field alignment.
1801 typedef[name.Name] = t
1802 case "struct":
1803 g, csyntax, align := c.Struct(dt, pos)
1804 if t.C.Empty() {
1805 t.C.Set(csyntax)
1807 t.Align = align
1808 tt := *t
1809 if tag != "" {
1810 tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
1812 tt.Go = g
1813 typedef[name.Name] = &tt
1816 case *dwarf.TypedefType:
1817 // Record typedef for printing.
1818 if dt.Name == "_GoString_" {
1819 // Special C name for Go string type.
1820 // Knows string layout used by compilers: pointer plus length,
1821 // which rounds up to 2 pointers after alignment.
1822 t.Go = c.string
1823 t.Size = c.ptrSize * 2
1824 t.Align = c.ptrSize
1825 break
1827 if dt.Name == "_GoBytes_" {
1828 // Special C name for Go []byte type.
1829 // Knows slice layout used by compilers: pointer, length, cap.
1830 t.Go = c.Ident("[]byte")
1831 t.Size = c.ptrSize + 4 + 4
1832 t.Align = c.ptrSize
1833 break
1835 name := c.Ident("_Ctype_" + dt.Name)
1836 goIdent[name.Name] = name
1837 sub := c.Type(dt.Type, pos)
1838 t.Go = name
1839 if unionWithPointer[sub.Go] {
1840 unionWithPointer[t.Go] = true
1842 t.Size = sub.Size
1843 t.Align = sub.Align
1844 oldType := typedef[name.Name]
1845 if oldType == nil {
1846 tt := *t
1847 tt.Go = sub.Go
1848 typedef[name.Name] = &tt
1851 // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
1852 // use that as the Go form for this typedef too, so that the typedef will be interchangeable
1853 // with the base type.
1854 // In -godefs mode, do this for all typedefs.
1855 if isStructUnionClass(sub.Go) || *godefs {
1856 t.Go = sub.Go
1858 if isStructUnionClass(sub.Go) {
1859 // Use the typedef name for C code.
1860 typedef[sub.Go.(*ast.Ident).Name].C = t.C
1863 // If we've seen this typedef before, and it
1864 // was an anonymous struct/union/class before
1865 // too, use the old definition.
1866 // TODO: it would be safer to only do this if
1867 // we verify that the types are the same.
1868 if oldType != nil && isStructUnionClass(oldType.Go) {
1869 t.Go = oldType.Go
1873 case *dwarf.UcharType:
1874 if t.Size != 1 {
1875 fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
1877 t.Go = c.uint8
1878 t.Align = 1
1880 case *dwarf.UintType:
1881 if dt.BitSize > 0 {
1882 fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
1884 switch t.Size {
1885 default:
1886 fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
1887 case 1:
1888 t.Go = c.uint8
1889 case 2:
1890 t.Go = c.uint16
1891 case 4:
1892 t.Go = c.uint32
1893 case 8:
1894 t.Go = c.uint64
1895 case 16:
1896 t.Go = &ast.ArrayType{
1897 Len: c.intExpr(t.Size),
1898 Elt: c.uint8,
1901 if t.Align = t.Size; t.Align >= c.ptrSize {
1902 t.Align = c.ptrSize
1905 case *dwarf.VoidType:
1906 t.Go = c.goVoid
1907 t.C.Set("void")
1908 t.Align = 1
1911 switch dtype.(type) {
1912 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
1913 s := dtype.Common().Name
1914 if s != "" {
1915 if ss, ok := dwarfToName[s]; ok {
1916 s = ss
1918 s = strings.Join(strings.Split(s, " "), "") // strip spaces
1919 name := c.Ident("_Ctype_" + s)
1920 tt := *t
1921 typedef[name.Name] = &tt
1922 if !*godefs {
1923 t.Go = name
1928 if t.Size < 0 {
1929 // Unsized types are [0]byte, unless they're typedefs of other types
1930 // or structs with tags.
1931 // if so, use the name we've already defined.
1932 t.Size = 0
1933 switch dt := dtype.(type) {
1934 case *dwarf.TypedefType:
1935 // ok
1936 case *dwarf.StructType:
1937 if dt.StructName != "" {
1938 break
1940 t.Go = c.Opaque(0)
1941 default:
1942 t.Go = c.Opaque(0)
1944 if t.C.Empty() {
1945 t.C.Set("void")
1949 if t.C.Empty() {
1950 fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
1953 return t
1956 // isStructUnionClass reports whether the type described by the Go syntax x
1957 // is a struct, union, or class with a tag.
1958 func isStructUnionClass(x ast.Expr) bool {
1959 id, ok := x.(*ast.Ident)
1960 if !ok {
1961 return false
1963 name := id.Name
1964 return strings.HasPrefix(name, "_Ctype_struct_") ||
1965 strings.HasPrefix(name, "_Ctype_union_") ||
1966 strings.HasPrefix(name, "_Ctype_class_")
1969 // FuncArg returns a Go type with the same memory layout as
1970 // dtype when used as the type of a C function argument.
1971 func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
1972 t := c.Type(unqual(dtype), pos)
1973 switch dt := dtype.(type) {
1974 case *dwarf.ArrayType:
1975 // Arrays are passed implicitly as pointers in C.
1976 // In Go, we must be explicit.
1977 tr := &TypeRepr{}
1978 tr.Set("%s*", t.C)
1979 return &Type{
1980 Size: c.ptrSize,
1981 Align: c.ptrSize,
1982 Go: &ast.StarExpr{X: t.Go},
1983 C: tr,
1985 case *dwarf.TypedefType:
1986 // C has much more relaxed rules than Go for
1987 // implicit type conversions. When the parameter
1988 // is type T defined as *X, simulate a little of the
1989 // laxness of C by making the argument *X instead of T.
1990 if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
1991 // Unless the typedef happens to point to void* since
1992 // Go has special rules around using unsafe.Pointer.
1993 if _, void := base(ptr.Type).(*dwarf.VoidType); void {
1994 break
1997 t = c.Type(ptr, pos)
1998 if t == nil {
1999 return nil
2002 // For a struct/union/class, remember the C spelling,
2003 // in case it has __attribute__((unavailable)).
2004 // See issue 2888.
2005 if isStructUnionClass(t.Go) {
2006 t.Typedef = dt.Name
2010 return t
2013 // FuncType returns the Go type analogous to dtype.
2014 // There is no guarantee about matching memory layout.
2015 func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
2016 p := make([]*Type, len(dtype.ParamType))
2017 gp := make([]*ast.Field, len(dtype.ParamType))
2018 for i, f := range dtype.ParamType {
2019 // gcc's DWARF generator outputs a single DotDotDotType parameter for
2020 // function pointers that specify no parameters (e.g. void
2021 // (*__cgo_0)()). Treat this special case as void. This case is
2022 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
2023 // legal).
2024 if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
2025 p, gp = nil, nil
2026 break
2028 p[i] = c.FuncArg(f, pos)
2029 gp[i] = &ast.Field{Type: p[i].Go}
2031 var r *Type
2032 var gr []*ast.Field
2033 if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
2034 gr = []*ast.Field{{Type: c.goVoid}}
2035 } else if dtype.ReturnType != nil {
2036 r = c.Type(unqual(dtype.ReturnType), pos)
2037 gr = []*ast.Field{{Type: r.Go}}
2039 return &FuncType{
2040 Params: p,
2041 Result: r,
2042 Go: &ast.FuncType{
2043 Params: &ast.FieldList{List: gp},
2044 Results: &ast.FieldList{List: gr},
2049 // Identifier
2050 func (c *typeConv) Ident(s string) *ast.Ident {
2051 return ast.NewIdent(s)
2054 // Opaque type of n bytes.
2055 func (c *typeConv) Opaque(n int64) ast.Expr {
2056 return &ast.ArrayType{
2057 Len: c.intExpr(n),
2058 Elt: c.byte,
2062 // Expr for integer n.
2063 func (c *typeConv) intExpr(n int64) ast.Expr {
2064 return &ast.BasicLit{
2065 Kind: token.INT,
2066 Value: strconv.FormatInt(n, 10),
2070 // Add padding of given size to fld.
2071 func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
2072 n := len(fld)
2073 fld = fld[0 : n+1]
2074 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
2075 sizes = sizes[0 : n+1]
2076 sizes[n] = size
2077 return fld, sizes
2080 // Struct conversion: return Go and (gc) C syntax for type.
2081 func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
2082 // Minimum alignment for a struct is 1 byte.
2083 align = 1
2085 var buf bytes.Buffer
2086 buf.WriteString("struct {")
2087 fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
2088 sizes := make([]int64, 0, 2*len(dt.Field)+1)
2089 off := int64(0)
2091 // Rename struct fields that happen to be named Go keywords into
2092 // _{keyword}. Create a map from C ident -> Go ident. The Go ident will
2093 // be mangled. Any existing identifier that already has the same name on
2094 // the C-side will cause the Go-mangled version to be prefixed with _.
2095 // (e.g. in a struct with fields '_type' and 'type', the latter would be
2096 // rendered as '__type' in Go).
2097 ident := make(map[string]string)
2098 used := make(map[string]bool)
2099 for _, f := range dt.Field {
2100 ident[f.Name] = f.Name
2101 used[f.Name] = true
2104 if !*godefs {
2105 for cid, goid := range ident {
2106 if token.Lookup(goid).IsKeyword() {
2107 // Avoid keyword
2108 goid = "_" + goid
2110 // Also avoid existing fields
2111 for _, exist := used[goid]; exist; _, exist = used[goid] {
2112 goid = "_" + goid
2115 used[goid] = true
2116 ident[cid] = goid
2121 anon := 0
2122 for _, f := range dt.Field {
2123 if f.ByteOffset > off {
2124 fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
2125 off = f.ByteOffset
2128 name := f.Name
2129 ft := f.Type
2131 // In godefs mode, if this field is a C11
2132 // anonymous union then treat the first field in the
2133 // union as the field in the struct. This handles
2134 // cases like the glibc <sys/resource.h> file; see
2135 // issue 6677.
2136 if *godefs {
2137 if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
2138 name = st.Field[0].Name
2139 ident[name] = name
2140 ft = st.Field[0].Type
2144 // TODO: Handle fields that are anonymous structs by
2145 // promoting the fields of the inner struct.
2147 t := c.Type(ft, pos)
2148 tgo := t.Go
2149 size := t.Size
2150 talign := t.Align
2151 if f.BitSize > 0 {
2152 if f.BitSize%8 != 0 {
2153 continue
2155 size = f.BitSize / 8
2156 name := tgo.(*ast.Ident).String()
2157 if strings.HasPrefix(name, "int") {
2158 name = "int"
2159 } else {
2160 name = "uint"
2162 tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
2163 talign = size
2166 if talign > 0 && f.ByteOffset%talign != 0 {
2167 // Drop misaligned fields, the same way we drop integer bit fields.
2168 // The goal is to make available what can be made available.
2169 // Otherwise one bad and unneeded field in an otherwise okay struct
2170 // makes the whole program not compile. Much of the time these
2171 // structs are in system headers that cannot be corrected.
2172 continue
2174 n := len(fld)
2175 fld = fld[0 : n+1]
2176 if name == "" {
2177 name = fmt.Sprintf("anon%d", anon)
2178 anon++
2179 ident[name] = name
2181 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
2182 sizes = sizes[0 : n+1]
2183 sizes[n] = size
2184 off += size
2185 buf.WriteString(t.C.String())
2186 buf.WriteString(" ")
2187 buf.WriteString(name)
2188 buf.WriteString("; ")
2189 if talign > align {
2190 align = talign
2193 if off < dt.ByteSize {
2194 fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
2195 off = dt.ByteSize
2198 // If the last field in a non-zero-sized struct is zero-sized
2199 // the compiler is going to pad it by one (see issue 9401).
2200 // We can't permit that, because then the size of the Go
2201 // struct will not be the same as the size of the C struct.
2202 // Our only option in such a case is to remove the field,
2203 // which means that it cannot be referenced from Go.
2204 for off > 0 && sizes[len(sizes)-1] == 0 {
2205 n := len(sizes)
2206 fld = fld[0 : n-1]
2207 sizes = sizes[0 : n-1]
2210 if off != dt.ByteSize {
2211 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
2213 buf.WriteString("}")
2214 csyntax = buf.String()
2216 if *godefs {
2217 godefsFields(fld)
2219 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
2220 return
2223 // dwarfHasPointer returns whether the DWARF type dt contains a pointer.
2224 func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
2225 switch dt := dt.(type) {
2226 default:
2227 fatalf("%s: unexpected type: %s", lineno(pos), dt)
2228 return false
2230 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
2231 *dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
2232 *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:
2234 return false
2236 case *dwarf.ArrayType:
2237 return c.dwarfHasPointer(dt.Type, pos)
2239 case *dwarf.PtrType:
2240 return true
2242 case *dwarf.QualType:
2243 return c.dwarfHasPointer(dt.Type, pos)
2245 case *dwarf.StructType:
2246 for _, f := range dt.Field {
2247 if c.dwarfHasPointer(f.Type, pos) {
2248 return true
2251 return false
2253 case *dwarf.TypedefType:
2254 if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
2255 return true
2257 return c.dwarfHasPointer(dt.Type, pos)
2261 func upper(s string) string {
2262 if s == "" {
2263 return ""
2265 r, size := utf8.DecodeRuneInString(s)
2266 if r == '_' {
2267 return "X" + s
2269 return string(unicode.ToUpper(r)) + s[size:]
2272 // godefsFields rewrites field names for use in Go or C definitions.
2273 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
2274 // converts names to upper case, and rewrites _ into Pad_godefs_n,
2275 // so that all fields are exported.
2276 func godefsFields(fld []*ast.Field) {
2277 prefix := fieldPrefix(fld)
2278 npad := 0
2279 for _, f := range fld {
2280 for _, n := range f.Names {
2281 if n.Name != prefix {
2282 n.Name = strings.TrimPrefix(n.Name, prefix)
2284 if n.Name == "_" {
2285 // Use exported name instead.
2286 n.Name = "Pad_cgo_" + strconv.Itoa(npad)
2287 npad++
2289 n.Name = upper(n.Name)
2294 // fieldPrefix returns the prefix that should be removed from all the
2295 // field names when generating the C or Go code. For generated
2296 // C, we leave the names as is (tv_sec, tv_usec), since that's what
2297 // people are used to seeing in C. For generated Go code, such as
2298 // package syscall's data structures, we drop a common prefix
2299 // (so sec, usec, which will get turned into Sec, Usec for exporting).
2300 func fieldPrefix(fld []*ast.Field) string {
2301 prefix := ""
2302 for _, f := range fld {
2303 for _, n := range f.Names {
2304 // Ignore field names that don't have the prefix we're
2305 // looking for. It is common in C headers to have fields
2306 // named, say, _pad in an otherwise prefixed header.
2307 // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
2308 // still want to remove the tv_ prefix.
2309 // The check for "orig_" here handles orig_eax in the
2310 // x86 ptrace register sets, which otherwise have all fields
2311 // with reg_ prefixes.
2312 if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
2313 continue
2315 i := strings.Index(n.Name, "_")
2316 if i < 0 {
2317 continue
2319 if prefix == "" {
2320 prefix = n.Name[:i+1]
2321 } else if prefix != n.Name[:i+1] {
2322 return ""
2326 return prefix