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.
32 var debugDefine
= flag
.Bool("debug-define", false, "print relevant #defines")
33 var debugGcc
= flag
.Bool("debug-gcc", false, "print gcc invocations")
35 var nameToC
= map[string]string{
36 "schar": "signed char",
37 "uchar": "unsigned char",
38 "ushort": "unsigned short",
39 "uint": "unsigned int",
40 "ulong": "unsigned long",
41 "longlong": "long long",
42 "ulonglong": "unsigned long long",
43 "complexfloat": "float _Complex",
44 "complexdouble": "double _Complex",
47 // cname returns the C name to use for C.s.
48 // The expansions are listed in nameToC and also
49 // struct_foo becomes "struct foo", and similarly for
51 func cname(s
string) string {
52 if t
, ok
:= nameToC
[s
]; ok
{
56 if strings
.HasPrefix(s
, "struct_") {
57 return "struct " + s
[len("struct_"):]
59 if strings
.HasPrefix(s
, "union_") {
60 return "union " + s
[len("union_"):]
62 if strings
.HasPrefix(s
, "enum_") {
63 return "enum " + s
[len("enum_"):]
65 if strings
.HasPrefix(s
, "sizeof_") {
66 return "sizeof(" + cname(s
[len("sizeof_"):]) + ")"
71 // DiscardCgoDirectives processes the import C preamble, and discards
72 // all #cgo CFLAGS and LDFLAGS directives, so they don't make their
73 // way into _cgo_export.h.
74 func (f
*File
) DiscardCgoDirectives() {
75 linesIn
:= strings
.Split(f
.Preamble
, "\n")
76 linesOut
:= make([]string, 0, len(linesIn
))
77 for _
, line
:= range linesIn
{
78 l
:= strings
.TrimSpace(line
)
79 if len(l
) < 5 || l
[:4] != "#cgo" ||
!unicode
.IsSpace(rune(l
[4])) {
80 linesOut
= append(linesOut
, line
)
82 linesOut
= append(linesOut
, "")
85 f
.Preamble
= strings
.Join(linesOut
, "\n")
88 // addToFlag appends args to flag. All flags are later written out onto the
89 // _cgo_flags file for the build system to use.
90 func (p
*Package
) addToFlag(flag
string, args
[]string) {
92 // We'll also need these when preprocessing for dwarf information.
93 // However, discard any -g options: we need to be able
94 // to parse the debug info, so stick to what we expect.
95 for _
, arg
:= range args
{
96 if !strings
.HasPrefix(arg
, "-g") {
97 p
.GccOptions
= append(p
.GccOptions
, arg
)
103 for i
, arg
:= range args
{
104 // The go tool will pass us a -I option pointing to objdir;
105 // we don't need to record that for later, as the objdir
106 // will disappear anyhow.
108 // Discard argument in "-I objdir" case.
110 } else if strings
.HasPrefix(arg
, "-I") && strings
.HasPrefix(arg
[2:], *objDir
) {
111 // This is -Iobjdir. Don't save this argument.
112 } else if arg
== "-I" && i
+1 < len(args
) && strings
.HasPrefix(args
[i
+1], *objDir
) {
113 // This is -I objdir. Don't save this argument
117 p
.CgoFlags
[flag
] = append(p
.CgoFlags
[flag
], arg
)
122 // splitQuoted splits the string s around each instance of one or more consecutive
123 // white space characters while taking into account quotes and escaping, and
124 // returns an array of substrings of s or an empty list if s contains only white space.
125 // Single quotes and double quotes are recognized to prevent splitting within the
126 // quoted region, and are removed from the resulting substrings. If a quote in s
127 // isn't closed err will be set and r will have the unclosed argument as the
128 // last element. The backslash is used for escaping.
130 // For example, the following string:
132 // `a b:"c d" 'e''f' "g\""`
134 // Would be parsed as:
136 // []string{"a", "b:c d", "ef", `g"`}
138 func splitQuoted(s
string) (r
[]string, err error
) {
140 arg
:= make([]rune
, len(s
))
145 for _
, r
:= range s
{
157 case r
== '"' || r
== '\'':
161 case unicode
.IsSpace(r
):
164 args
= append(args
, string(arg
[:i
]))
173 args
= append(args
, string(arg
[:i
]))
176 err
= errors
.New("unclosed quote")
178 err
= errors
.New("unfinished escaping")
183 // Translate rewrites f.AST, the original Go input, to remove
184 // references to the imported package C, replacing them with
185 // references to the equivalent Go types, functions, and variables.
186 func (p
*Package
) Translate(f
*File
) {
187 for _
, cref
:= range f
.Ref
{
188 // Convert C.ulong to C.unsigned long, etc.
189 cref
.Name
.C
= cname(cref
.Name
.Go
)
193 conv
.Init(p
.PtrSize
, p
.IntSize
)
196 p
.typedefs
= map[string]bool{}
199 for len(p
.typedefs
) > numTypedefs
{
200 numTypedefs
= len(p
.typedefs
)
201 // Also ask about any typedefs we've seen so far.
202 for _
, info
:= range p
.typedefList
{
207 f
.Name
[info
.typedef
] = n
208 f
.NamePos
[n
] = info
.pos
210 needType
:= p
.guessKinds(f
)
211 if len(needType
) > 0 {
212 p
.loadDWARF(f
, &conv
, needType
)
215 // In godefs mode we're OK with the typedefs, which
216 // will presumably also be defined in the file, we
217 // don't want to resolve them to their base types.
223 if p
.rewriteCalls(f
) {
224 // Add `import _cgo_unsafe "unsafe"` after the package statement.
225 f
.Edit
.Insert(f
.offset(f
.AST
.Name
.End()), "; import _cgo_unsafe \"unsafe\"")
230 // loadDefines coerces gcc into spitting out the #defines in use
231 // in the file f and saves relevant renamings in f.Name[name].Define.
232 func (p
*Package
) loadDefines(f
*File
) {
234 b
.WriteString(builtinProlog
)
235 b
.WriteString(f
.Preamble
)
236 stdout
:= p
.gccDefines(b
.Bytes())
238 for _
, line
:= range strings
.Split(stdout
, "\n") {
239 if len(line
) < 9 || line
[0:7] != "#define" {
243 line
= strings
.TrimSpace(line
[8:])
246 spaceIndex
:= strings
.Index(line
, " ")
247 tabIndex
:= strings
.Index(line
, "\t")
249 if spaceIndex
== -1 && tabIndex
== -1 {
251 } else if tabIndex
== -1 ||
(spaceIndex
!= -1 && spaceIndex
< tabIndex
) {
252 key
= line
[0:spaceIndex
]
253 val
= strings
.TrimSpace(line
[spaceIndex
:])
255 key
= line
[0:tabIndex
]
256 val
= strings
.TrimSpace(line
[tabIndex
:])
259 if key
== "__clang__" {
263 if n
:= f
.Name
[key
]; n
!= nil {
265 fmt
.Fprintf(os
.Stderr
, "#define %s %s\n", key
, val
)
272 // guessKinds tricks gcc into revealing the kind of each
273 // name xxx for the references C.xxx in the Go input.
274 // The kind is either a constant, type, or variable.
275 func (p
*Package
) guessKinds(f
*File
) []*Name
{
276 // Determine kinds for names we already know about,
277 // like #defines or 'struct foo', before bothering with gcc.
278 var names
, needType
[]*Name
279 optional
:= map[*Name
]bool{}
280 for _
, key
:= range nameKeys(f
.Name
) {
282 // If we've already found this name as a #define
283 // and we can translate it as a constant value, do so.
285 if i
, err
:= strconv
.ParseInt(n
.Define
, 0, 64); err
== nil {
287 // Turn decimal into hex, just for consistency
288 // with enum-derived constants. Otherwise
289 // in the cgo -godefs output half the constants
290 // are in hex and half are in whatever the #define used.
291 n
.Const
= fmt
.Sprintf("%#x", i
)
292 } else if n
.Define
[0] == '\'' {
293 if _
, err
:= parser
.ParseExpr(n
.Define
); err
== nil {
297 } else if n
.Define
[0] == '"' {
298 if _
, err
:= parser
.ParseExpr(n
.Define
); err
== nil {
309 // If this is a struct, union, or enum type name, no need to guess the kind.
310 if strings
.HasPrefix(n
.C
, "struct ") || strings
.HasPrefix(n
.C
, "union ") || strings
.HasPrefix(n
.C
, "enum ") {
312 needType
= append(needType
, n
)
316 if goos
== "darwin" && strings
.HasSuffix(n
.C
, "Ref") {
317 // For FooRef, find out if FooGetTypeID exists.
318 s
:= n
.C
[:len(n
.C
)-3] + "GetTypeID"
319 n
:= &Name
{Go
: s
, C
: s
}
320 names
= append(names
, n
)
324 // Otherwise, we'll need to find out from gcc.
325 names
= append(names
, n
)
328 // Bypass gcc if there's nothing left to find out.
333 // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
334 // For names, find out whether they are integer constants.
335 // We used to look at specific warning or error messages here, but that tied the
336 // behavior too closely to specific versions of the compilers.
337 // Instead, arrange that we can infer what we need from only the presence or absence
338 // of an error on a specific line.
340 // For each name, we generate these lines, where xxx is the index in toSniff plus one.
342 // #line xxx "not-declared"
343 // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__1; }
344 // #line xxx "not-type"
345 // void __cgo_f_xxx_2(void) { name *__cgo_undefined__2; }
346 // #line xxx "not-int-const"
347 // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__3 = (name)*1 }; }
348 // #line xxx "not-num-const"
349 // void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
350 // #line xxx "not-str-lit"
351 // void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
353 // If we see an error at not-declared:xxx, the corresponding name is not declared.
354 // If we see an error at not-type:xxx, the corresponding name is a type.
355 // If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
356 // If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
357 // If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
359 // The specific input forms are chosen so that they are valid C syntax regardless of
360 // whether name denotes a type or an expression.
363 b
.WriteString(builtinProlog
)
364 b
.WriteString(f
.Preamble
)
366 for i
, n
:= range names
{
367 fmt
.Fprintf(&b
, "#line %d \"not-declared\"\n"+
368 "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__1; }\n"+
369 "#line %d \"not-type\"\n"+
370 "void __cgo_f_%d_2(void) { %s *__cgo_undefined__2; }\n"+
371 "#line %d \"not-int-const\"\n"+
372 "void __cgo_f_%d_3(void) { enum { __cgo_undefined__3 = (%s)*1 }; }\n"+
373 "#line %d \"not-num-const\"\n"+
374 "void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
375 "#line %d \"not-str-lit\"\n"+
376 "void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
384 fmt
.Fprintf(&b
, "#line 1 \"completed\"\n"+
385 "int __cgo__1 = __cgo__2;\n")
387 stderr
:= p
.gccErrors(b
.Bytes())
389 fatalf("%s produced no output\non input:\n%s", p
.gccBaseCmd()[0], b
.Bytes())
393 sniff
:= make([]int, len(names
))
401 sawUnmatchedErrors
:= false
402 for _
, line
:= range strings
.Split(stderr
, "\n") {
403 // Ignore warnings and random comments, with one
404 // exception: newer GCC versions will sometimes emit
405 // an error on a macro #define with a note referring
406 // to where the expansion occurs. We care about where
407 // the expansion occurs, so in that case treat the note
409 isError
:= strings
.Contains(line
, ": error:")
410 isErrorNote
:= strings
.Contains(line
, ": note:") && sawUnmatchedErrors
411 if !isError
&& !isErrorNote
{
415 c1
:= strings
.Index(line
, ":")
419 c2
:= strings
.Index(line
[c1
+1:], ":")
425 filename
:= line
[:c1
]
426 i
, _
:= strconv
.Atoi(line
[c1
+1 : c2
])
428 if i
< 0 || i
>= len(names
) {
430 sawUnmatchedErrors
= true
437 // Strictly speaking, there is no guarantee that seeing the error at completed:1
438 // (at the end of the file) means we've seen all the errors from earlier in the file,
439 // but usually it does. Certainly if we don't see the completed:1 error, we did
440 // not get all the errors we expected.
444 sniff
[i
] |
= notDeclared
447 case "not-int-const":
448 sniff
[i
] |
= notIntConst
449 case "not-num-const":
450 sniff
[i
] |
= notNumConst
452 sniff
[i
] |
= notStrLiteral
455 sawUnmatchedErrors
= true
460 sawUnmatchedErrors
= false
464 fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p
.gccBaseCmd()[0], b
.Bytes(), stderr
)
467 for i
, n
:= range names
{
470 if sniff
[i
]¬Declared
!= 0 && optional
[n
] {
471 // Ignore optional undeclared identifiers.
472 // Don't report an error, and skip adding n to the needType array.
475 error_(f
.NamePos
[n
], "could not determine kind of name for C.%s", fixGo(n
.Go
))
476 case notStrLiteral | notType
:
478 case notIntConst | notStrLiteral | notType
:
480 case notIntConst | notNumConst | notType
:
482 case notIntConst | notNumConst | notStrLiteral
:
484 case notIntConst | notNumConst | notStrLiteral | notType
:
487 needType
= append(needType
, n
)
490 // Check if compiling the preamble by itself causes any errors,
491 // because the messages we've printed out so far aren't helpful
492 // to users debugging preamble mistakes. See issue 8442.
493 preambleErrors
:= p
.gccErrors([]byte(f
.Preamble
))
494 if len(preambleErrors
) > 0 {
495 error_(token
.NoPos
, "\n%s errors for preamble:\n%s", p
.gccBaseCmd()[0], preambleErrors
)
498 fatalf("unresolved names")
504 // loadDWARF parses the DWARF debug information generated
505 // by gcc to learn the details of the constants, variables, and types
506 // being referred to as C.xxx.
507 func (p
*Package
) loadDWARF(f
*File
, conv
*typeConv
, names
[]*Name
) {
508 // Extract the types from the DWARF section of an object
509 // from a well-formed C program. Gcc only generates DWARF info
510 // for symbols in the object file, so it is not enough to print the
511 // preamble and hope the symbols we care about will be there.
513 // __typeof__(names[i]) *__cgo__i;
514 // for each entry in names and then dereference the type we
515 // learn for __cgo__i.
517 b
.WriteString(builtinProlog
)
518 b
.WriteString(f
.Preamble
)
519 b
.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
520 for i
, n
:= range names
{
521 fmt
.Fprintf(&b
, "__typeof__(%s) *__cgo__%d;\n", n
.C
, i
)
522 if n
.Kind
== "iconst" {
523 fmt
.Fprintf(&b
, "enum { __cgo_enum__%d = %s };\n", i
, n
.C
)
527 // We create a data block initialized with the values,
528 // so we can read them out of the object file.
529 fmt
.Fprintf(&b
, "long long __cgodebug_ints[] = {\n")
530 for _
, n
:= range names
{
531 if n
.Kind
== "iconst" {
532 fmt
.Fprintf(&b
, "\t%s,\n", n
.C
)
534 fmt
.Fprintf(&b
, "\t0,\n")
537 // for the last entry, we cannot use 0, otherwise
538 // in case all __cgodebug_data is zero initialized,
539 // LLVM-based gcc will place the it in the __DATA.__common
540 // zero-filled section (our debug/macho doesn't support
542 fmt
.Fprintf(&b
, "\t1\n")
543 fmt
.Fprintf(&b
, "};\n")
545 // do the same work for floats.
546 fmt
.Fprintf(&b
, "double __cgodebug_floats[] = {\n")
547 for _
, n
:= range names
{
548 if n
.Kind
== "fconst" {
549 fmt
.Fprintf(&b
, "\t%s,\n", n
.C
)
551 fmt
.Fprintf(&b
, "\t0,\n")
554 fmt
.Fprintf(&b
, "\t1\n")
555 fmt
.Fprintf(&b
, "};\n")
557 // do the same work for strings.
558 for i
, n
:= range names
{
559 if n
.Kind
== "sconst" {
560 fmt
.Fprintf(&b
, "const char __cgodebug_str__%d[] = %s;\n", i
, n
.C
)
561 fmt
.Fprintf(&b
, "const unsigned long long __cgodebug_strlen__%d = sizeof(%s)-1;\n", i
, n
.C
)
565 d
, ints
, floats
, strs
:= p
.gccDebug(b
.Bytes(), len(names
))
567 // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
568 types
:= make([]dwarf
.Type
, len(names
))
573 fatalf("reading DWARF entry: %s", err
)
579 case dwarf
.TagVariable
:
580 name
, _
:= e
.Val(dwarf
.AttrName
).(string)
581 typOff
, _
:= e
.Val(dwarf
.AttrType
).(dwarf
.Offset
)
582 if name
== "" || typOff
== 0 {
583 if e
.Val(dwarf
.AttrSpecification
) != nil {
584 // Since we are reading all the DWARF,
585 // assume we will see the variable elsewhere.
588 fatalf("malformed DWARF TagVariable entry")
590 if !strings
.HasPrefix(name
, "__cgo__") {
593 typ
, err
:= d
.Type(typOff
)
595 fatalf("loading DWARF type: %s", err
)
597 t
, ok
:= typ
.(*dwarf
.PtrType
)
599 fatalf("internal error: %s has non-pointer type", name
)
601 i
, err
:= strconv
.Atoi(name
[7:])
603 fatalf("malformed __cgo__ name: %s", name
)
606 p
.recordTypedefs(t
.Type
, f
.NamePos
[names
[i
]])
608 if e
.Tag
!= dwarf
.TagCompileUnit
{
613 // Record types and typedef information.
614 for i
, n
:= range names
{
615 if strings
.HasSuffix(n
.Go
, "GetTypeID") && types
[i
].String() == "func() CFTypeID" {
616 conv
.getTypeIDs
[n
.Go
[:len(n
.Go
)-9]] = true
619 for i
, n
:= range names
{
624 f
, fok
:= types
[i
].(*dwarf
.FuncType
)
625 if n
.Kind
!= "type" && fok
{
627 n
.FuncType
= conv
.FuncType(f
, pos
)
629 n
.Type
= conv
.Type(types
[i
], pos
)
633 if _
, ok
:= types
[i
].(*dwarf
.UintType
); ok
{
634 n
.Const
= fmt
.Sprintf("%#x", uint64(ints
[i
]))
636 n
.Const
= fmt
.Sprintf("%#x", ints
[i
])
640 if i
>= len(floats
) {
643 switch base(types
[i
]).(type) {
644 case *dwarf
.IntType
, *dwarf
.UintType
:
645 // This has an integer type so it's
646 // not really a floating point
647 // constant. This can happen when the
648 // C compiler complains about using
649 // the value as an integer constant,
650 // but not as a general constant.
651 // Treat this as a variable of the
652 // appropriate type, not a constant,
653 // to get C-style type handling,
654 // avoiding the problem that C permits
655 // uint64(-1) but Go does not.
659 n
.Const
= fmt
.Sprintf("%f", floats
[i
])
663 n
.Const
= fmt
.Sprintf("%q", strs
[i
])
671 // recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
672 func (p
*Package
) recordTypedefs(dtype dwarf
.Type
, pos token
.Pos
) {
673 p
.recordTypedefs1(dtype
, pos
, map[dwarf
.Type
]bool{})
676 func (p
*Package
) recordTypedefs1(dtype dwarf
.Type
, pos token
.Pos
, visited
map[dwarf
.Type
]bool) {
683 visited
[dtype
] = true
684 switch dt
:= dtype
.(type) {
685 case *dwarf
.TypedefType
:
686 if strings
.HasPrefix(dt
.Name
, "__builtin") {
687 // Don't look inside builtin types. There be dragons.
690 if !p
.typedefs
[dt
.Name
] {
691 p
.typedefs
[dt
.Name
] = true
692 p
.typedefList
= append(p
.typedefList
, typedefInfo
{dt
.Name
, pos
})
693 p
.recordTypedefs1(dt
.Type
, pos
, visited
)
696 p
.recordTypedefs1(dt
.Type
, pos
, visited
)
697 case *dwarf
.ArrayType
:
698 p
.recordTypedefs1(dt
.Type
, pos
, visited
)
699 case *dwarf
.QualType
:
700 p
.recordTypedefs1(dt
.Type
, pos
, visited
)
701 case *dwarf
.FuncType
:
702 p
.recordTypedefs1(dt
.ReturnType
, pos
, visited
)
703 for _
, a
:= range dt
.ParamType
{
704 p
.recordTypedefs1(a
, pos
, visited
)
706 case *dwarf
.StructType
:
707 for _
, f
:= range dt
.Field
{
708 p
.recordTypedefs1(f
.Type
, pos
, visited
)
713 // prepareNames finalizes the Kind field of not-type names and sets
714 // the mangled name of all names.
715 func (p
*Package
) prepareNames(f
*File
) {
716 for _
, n
:= range f
.Name
{
717 if n
.Kind
== "not-type" {
722 n
.FuncType
= &FuncType
{
725 Results
: &ast
.FieldList
{List
: []*ast
.Field
{{Type
: n
.Type
.Go
}}},
734 // mangleName does name mangling to translate names
735 // from the original Go source files to the names
736 // used in the final Go files generated by cgo.
737 func (p
*Package
) mangleName(n
*Name
) {
738 // When using gccgo variables have to be
739 // exported so that they become global symbols
740 // that the C code can refer to.
742 if *gccgo
&& n
.IsVar() {
745 n
.Mangle
= prefix
+ n
.Kind
+ "_" + n
.Go
748 func (f
*File
) isMangledName(s
string) bool {
750 if strings
.HasPrefix(s
, prefix
) {
752 for _
, k
:= range nameKinds
{
753 if strings
.HasPrefix(t
, k
+"_") {
761 // rewriteCalls rewrites all calls that pass pointers to check that
762 // they follow the rules for passing pointers between Go and C.
763 // This reports whether the package needs to import unsafe as _cgo_unsafe.
764 func (p
*Package
) rewriteCalls(f
*File
) bool {
766 // Walk backward so that in C.f1(C.f2()) we rewrite C.f2 first.
767 for _
, call
:= range f
.Calls
{
771 start
:= f
.offset(call
.Call
.Pos())
772 end
:= f
.offset(call
.Call
.End())
773 str
, nu
:= p
.rewriteCall(f
, call
)
775 f
.Edit
.Replace(start
, end
, str
)
784 // rewriteCall rewrites one call to add pointer checks.
785 // If any pointer checks are required, we rewrite the call into a
786 // function literal that calls _cgoCheckPointer for each pointer
787 // argument and then calls the original function.
788 // This returns the rewritten call and whether the package needs to
789 // import unsafe as _cgo_unsafe.
790 // If it returns the empty string, the call did not need to be rewritten.
791 func (p
*Package
) rewriteCall(f
*File
, call
*Call
) (string, bool) {
792 // This is a call to C.xxx; set goname to "xxx".
793 // It may have already been mangled by rewriteName.
795 switch fun
:= call
.Call
.Fun
.(type) {
796 case *ast
.SelectorExpr
:
797 goname
= fun
.Sel
.Name
799 goname
= strings
.TrimPrefix(fun
.Name
, "_C2func_")
800 goname
= strings
.TrimPrefix(goname
, "_Cfunc_")
802 if goname
== "" || goname
== "malloc" {
805 name
:= f
.Name
[goname
]
806 if name
== nil || name
.Kind
!= "func" {
807 // Probably a type conversion.
811 params
:= name
.FuncType
.Params
812 args
:= call
.Call
.Args
814 // Avoid a crash if the number of arguments doesn't match
815 // the number of parameters.
816 // This will be caught when the generated file is compiled.
817 if len(args
) != len(params
) {
822 for i
, param
:= range params
{
823 if p
.needsPointerCheck(f
, param
.Go
, args
[i
]) {
832 // We need to rewrite this call.
837 // _cgoCheckPointer(_cgo0, nil)
840 // Using a function literal like this lets us evaluate the
841 // function arguments only once while doing pointer checks.
842 // This is particularly useful when passing additional arguments
843 // to _cgoCheckPointer, as done in checkIndex and checkAddr.
845 // When the function argument is a conversion to unsafe.Pointer,
846 // we unwrap the conversion before checking the pointer,
847 // and then wrap again when calling C.f. This lets us check
848 // the real type of the pointer in some cases. See issue #25941.
850 // When the call to C.f is deferred, we use an additional function
851 // literal to evaluate the arguments at the right time.
852 // defer func() func() {
855 // _cgoCheckPointer(_cgo0, nil)
859 // This works because the defer statement evaluates the first
860 // function literal in order to get the function to call.
863 sb
.WriteString("func() ")
865 sb
.WriteString("func() ")
872 // Check whether this call expects two results.
873 for _
, ref
:= range f
.Ref
{
874 if ref
.Expr
!= &call
.Call
.Fun
{
877 if ref
.Context
== ctxCall2
{
885 // Add the result type, if any.
886 if name
.FuncType
.Result
!= nil {
887 rtype
:= p
.rewriteUnsafe(name
.FuncType
.Result
.Go
)
888 if rtype
!= name
.FuncType
.Result
.Go
{
891 sb
.WriteString(gofmtLine(rtype
))
895 // Add the second result type, if any.
897 if name
.FuncType
.Result
== nil {
898 // An explicit void result looks odd but it
899 // seems to be how cgo has worked historically.
900 sb
.WriteString("_Ctype_void")
902 sb
.WriteString(", error)")
908 // Define _cgoN for each argument value.
909 // Write _cgoCheckPointer calls to sbCheck.
910 var sbCheck bytes
.Buffer
911 for i
, param
:= range params
{
913 arg
, nu
:= p
.mangle(f
, &args
[i
])
918 // Use "var x T = ..." syntax to explicitly convert untyped
919 // constants to the parameter type, to avoid a type mismatch.
920 ptype
:= p
.rewriteUnsafe(param
.Go
)
922 if !p
.needsPointerCheck(f
, param
.Go
, args
[i
]) || param
.BadPointer
{
923 if ptype
!= param
.Go
{
926 fmt
.Fprintf(&sb
, "var _cgo%d %s = %s; ", i
,
927 gofmtLine(ptype
), gofmtPos(arg
, origArg
.Pos()))
932 if p
.checkIndex(&sb
, &sbCheck
, arg
, i
) {
937 if p
.checkAddr(&sb
, &sbCheck
, arg
, i
) {
941 fmt
.Fprintf(&sb
, "_cgo%d := %s; ", i
, gofmtPos(arg
, origArg
.Pos()))
942 fmt
.Fprintf(&sbCheck
, "_cgoCheckPointer(_cgo%d, nil); ", i
)
946 sb
.WriteString("return func() { ")
949 // Write out the calls to _cgoCheckPointer.
950 sb
.WriteString(sbCheck
.String())
953 sb
.WriteString("return ")
956 m
, nu
:= p
.mangle(f
, &call
.Call
.Fun
)
960 sb
.WriteString(gofmtLine(m
))
963 for i
:= range params
{
967 fmt
.Fprintf(&sb
, "_cgo%d", i
)
969 sb
.WriteString("); ")
979 return sb
.String(), needsUnsafe
982 // needsPointerCheck reports whether the type t needs a pointer check.
983 // This is true if t is a pointer and if the value to which it points
984 // might contain a pointer.
985 func (p
*Package
) needsPointerCheck(f
*File
, t ast
.Expr
, arg ast
.Expr
) bool {
986 // An untyped nil does not need a pointer check, and when
987 // _cgoCheckPointer returns the untyped nil the type assertion we
988 // are going to insert will fail. Easier to just skip nil arguments.
989 // TODO: Note that this fails if nil is shadowed.
990 if id
, ok
:= arg
.(*ast
.Ident
); ok
&& id
.Name
== "nil" {
994 return p
.hasPointer(f
, t
, true)
997 // hasPointer is used by needsPointerCheck. If top is true it returns
998 // whether t is or contains a pointer that might point to a pointer.
999 // If top is false it reports whether t is or contains a pointer.
1001 func (p
*Package
) hasPointer(f
*File
, t ast
.Expr
, top
bool) bool {
1002 switch t
:= t
.(type) {
1003 case *ast
.ArrayType
:
1008 return p
.hasPointer(f
, t
.Elt
, false)
1010 return p
.hasPointer(f
, t
.Elt
, top
)
1011 case *ast
.StructType
:
1012 for _
, field
:= range t
.Fields
.List
{
1013 if p
.hasPointer(f
, field
.Type
, top
) {
1018 case *ast
.StarExpr
: // Pointer type.
1022 // Check whether this is a pointer to a C union (or class)
1023 // type that contains a pointer.
1024 if unionWithPointer
[t
.X
] {
1027 return p
.hasPointer(f
, t
.X
, false)
1028 case *ast
.FuncType
, *ast
.InterfaceType
, *ast
.MapType
, *ast
.ChanType
:
1031 // TODO: Handle types defined within function.
1032 for _
, d
:= range p
.Decl
{
1033 gd
, ok
:= d
.(*ast
.GenDecl
)
1034 if !ok || gd
.Tok
!= token
.TYPE
{
1037 for _
, spec
:= range gd
.Specs
{
1038 ts
, ok
:= spec
.(*ast
.TypeSpec
)
1042 if ts
.Name
.Name
== t
.Name
{
1043 return p
.hasPointer(f
, ts
.Type
, top
)
1047 if def
:= typedef
[t
.Name
]; def
!= nil {
1048 return p
.hasPointer(f
, def
.Go
, top
)
1050 if t
.Name
== "string" {
1053 if t
.Name
== "error" {
1056 if goTypes
[t
.Name
] != nil {
1059 // We can't figure out the type. Conservative
1060 // approach is to assume it has a pointer.
1062 case *ast
.SelectorExpr
:
1063 if l
, ok
:= t
.X
.(*ast
.Ident
); !ok || l
.Name
!= "C" {
1064 // Type defined in a different package.
1065 // Conservative approach is to assume it has a
1070 // Conservative approach: assume pointer.
1073 name
:= f
.Name
[t
.Sel
.Name
]
1074 if name
!= nil && name
.Kind
== "type" && name
.Type
!= nil && name
.Type
.Go
!= nil {
1075 return p
.hasPointer(f
, name
.Type
.Go
, top
)
1077 // We can't figure out the type. Conservative
1078 // approach is to assume it has a pointer.
1081 error_(t
.Pos(), "could not understand type %s", gofmt(t
))
1086 // mangle replaces references to C names in arg with the mangled names,
1087 // rewriting calls when it finds them.
1088 // It removes the corresponding references in f.Ref and f.Calls, so that we
1089 // don't try to do the replacement again in rewriteRef or rewriteCall.
1090 func (p
*Package
) mangle(f
*File
, arg
*ast
.Expr
) (ast
.Expr
, bool) {
1091 needsUnsafe
:= false
1092 f
.walk(arg
, ctxExpr
, func(f
*File
, arg
interface{}, context astContext
) {
1093 px
, ok
:= arg
.(*ast
.Expr
)
1097 sel
, ok
:= (*px
).(*ast
.SelectorExpr
)
1099 if l
, ok
:= sel
.X
.(*ast
.Ident
); !ok || l
.Name
!= "C" {
1103 for _
, r
:= range f
.Ref
{
1105 *px
= p
.rewriteName(f
, r
)
1114 call
, ok
:= (*px
).(*ast
.CallExpr
)
1119 for _
, c
:= range f
.Calls
{
1120 if !c
.Done
&& c
.Call
.Lparen
== call
.Lparen
{
1121 cstr
, nu
:= p
.rewriteCall(f
, c
)
1123 // Smuggle the rewritten call through an ident.
1124 *px
= ast
.NewIdent(cstr
)
1133 return *arg
, needsUnsafe
1136 // checkIndex checks whether arg has the form &a[i], possibly inside
1137 // type conversions. If so, then in the general case it writes
1139 // _cgoNN := &cgoIndexNN[i] // with type conversions, if any
1140 // to sb, and writes
1141 // _cgoCheckPointer(_cgoNN, _cgoIndexNN)
1142 // to sbCheck, and returns true. If a is a simple variable or field reference,
1144 // _cgoIndexNN := &a
1145 // and dereferences the uses of _cgoIndexNN. Taking the address avoids
1146 // making a copy of an array.
1148 // This tells _cgoCheckPointer to check the complete contents of the
1149 // slice or array being indexed, but no other part of the memory allocation.
1150 func (p
*Package
) checkIndex(sb
, sbCheck
*bytes
.Buffer
, arg ast
.Expr
, i
int) bool {
1151 // Strip type conversions.
1154 c
, ok
:= x
.(*ast
.CallExpr
)
1155 if !ok ||
len(c
.Args
) != 1 ||
!p
.isType(c
.Fun
) {
1160 u
, ok
:= x
.(*ast
.UnaryExpr
)
1161 if !ok || u
.Op
!= token
.AND
{
1164 index
, ok
:= u
.X
.(*ast
.IndexExpr
)
1171 if p
.isVariable(index
.X
) {
1176 fmt
.Fprintf(sb
, "_cgoIndex%d := %s%s; ", i
, addr
, gofmtPos(index
.X
, index
.X
.Pos()))
1178 index
.X
= ast
.NewIdent(fmt
.Sprintf("_cgoIndex%d", i
))
1180 index
.X
= &ast
.StarExpr
{X
: index
.X
}
1182 fmt
.Fprintf(sb
, "_cgo%d := %s; ", i
, gofmtPos(arg
, arg
.Pos()))
1185 fmt
.Fprintf(sbCheck
, "_cgoCheckPointer(_cgo%d, %s_cgoIndex%d); ", i
, deref
, i
)
1190 // checkAddr checks whether arg has the form &x, possibly inside type
1191 // conversions. If so, it writes
1193 // _cgoNN := _cgoBaseNN // with type conversions, if any
1194 // to sb, and writes
1195 // _cgoCheckPointer(_cgoBaseNN, true)
1196 // to sbCheck, and returns true. This tells _cgoCheckPointer to check
1197 // just the contents of the pointer being passed, not any other part
1198 // of the memory allocation. This is run after checkIndex, which looks
1199 // for the special case of &a[i], which requires different checks.
1200 func (p
*Package
) checkAddr(sb
, sbCheck
*bytes
.Buffer
, arg ast
.Expr
, i
int) bool {
1201 // Strip type conversions.
1204 c
, ok
:= (*px
).(*ast
.CallExpr
)
1205 if !ok ||
len(c
.Args
) != 1 ||
!p
.isType(c
.Fun
) {
1210 if u
, ok
:= (*px
).(*ast
.UnaryExpr
); !ok || u
.Op
!= token
.AND
{
1214 fmt
.Fprintf(sb
, "_cgoBase%d := %s; ", i
, gofmtPos(*px
, (*px
).Pos()))
1217 *px
= ast
.NewIdent(fmt
.Sprintf("_cgoBase%d", i
))
1218 fmt
.Fprintf(sb
, "_cgo%d := %s; ", i
, gofmtPos(arg
, arg
.Pos()))
1221 // Use "0 == 0" to do the right thing in the unlikely event
1222 // that "true" is shadowed.
1223 fmt
.Fprintf(sbCheck
, "_cgoCheckPointer(_cgoBase%d, 0 == 0); ", i
)
1228 // isType reports whether the expression is definitely a type.
1229 // This is conservative--it returns false for an unknown identifier.
1230 func (p
*Package
) isType(t ast
.Expr
) bool {
1231 switch t
:= t
.(type) {
1232 case *ast
.SelectorExpr
:
1233 id
, ok
:= t
.X
.(*ast
.Ident
)
1237 if id
.Name
== "unsafe" && t
.Sel
.Name
== "Pointer" {
1240 if id
.Name
== "C" && typedef
["_Ctype_"+t
.Sel
.Name
] != nil {
1245 // TODO: This ignores shadowing.
1247 case "unsafe.Pointer", "bool", "byte",
1248 "complex64", "complex128",
1250 "float32", "float64",
1251 "int", "int8", "int16", "int32", "int64",
1253 "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
1257 if strings
.HasPrefix(t
.Name
, "_Ctype_") {
1260 case *ast
.ParenExpr
:
1261 return p
.isType(t
.X
)
1263 return p
.isType(t
.X
)
1264 case *ast
.ArrayType
, *ast
.StructType
, *ast
.FuncType
, *ast
.InterfaceType
,
1265 *ast
.MapType
, *ast
.ChanType
:
1272 // isVariable reports whether x is a variable, possibly with field references.
1273 func (p
*Package
) isVariable(x ast
.Expr
) bool {
1274 switch x
:= x
.(type) {
1277 case *ast
.SelectorExpr
:
1278 return p
.isVariable(x
.X
)
1279 case *ast
.IndexExpr
:
1285 // rewriteUnsafe returns a version of t with references to unsafe.Pointer
1286 // rewritten to use _cgo_unsafe.Pointer instead.
1287 func (p
*Package
) rewriteUnsafe(t ast
.Expr
) ast
.Expr
{
1288 switch t
:= t
.(type) {
1290 // We don't see a SelectorExpr for unsafe.Pointer;
1291 // this is created by code in this file.
1292 if t
.Name
== "unsafe.Pointer" {
1293 return ast
.NewIdent("_cgo_unsafe.Pointer")
1295 case *ast
.ArrayType
:
1296 t1
:= p
.rewriteUnsafe(t
.Elt
)
1302 case *ast
.StructType
:
1306 for _
, f
:= range t
.Fields
.List
{
1307 ft
:= p
.rewriteUnsafe(f
.Type
)
1309 fields
.List
= append(fields
.List
, f
)
1313 fields
.List
= append(fields
.List
, &fn
)
1322 case *ast
.StarExpr
: // Pointer type.
1323 x1
:= p
.rewriteUnsafe(t
.X
)
1333 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
1334 // Go equivalents, now that we have figured out the meaning of all
1335 // the xxx. In *godefs mode, rewriteRef replaces the names
1336 // with full definitions instead of mangled names.
1337 func (p
*Package
) rewriteRef(f
*File
) {
1338 // Keep a list of all the functions, to remove the ones
1339 // only used as expressions and avoid generating bridge
1341 functions
:= make(map[string]bool)
1343 for _
, n
:= range f
.Name
{
1344 if n
.Kind
== "func" {
1345 functions
[n
.Go
] = false
1349 // Now that we have all the name types filled in,
1350 // scan through the Refs to identify the ones that
1351 // are trying to do a ,err call. Also check that
1352 // functions are only used in calls.
1353 for _
, r
:= range f
.Ref
{
1354 if r
.Name
.IsConst() && r
.Name
.Const
== "" {
1355 error_(r
.Pos(), "unable to find value of constant C.%s", fixGo(r
.Name
.Go
))
1358 if r
.Name
.Kind
== "func" {
1360 case ctxCall
, ctxCall2
:
1361 functions
[r
.Name
.Go
] = true
1365 expr
:= p
.rewriteName(f
, r
)
1368 // Substitute definition for mangled type name.
1369 if id
, ok
:= expr
.(*ast
.Ident
); ok
{
1370 if t
:= typedef
[id
.Name
]; t
!= nil {
1373 if id
.Name
== r
.Name
.Mangle
&& r
.Name
.Const
!= "" {
1374 expr
= ast
.NewIdent(r
.Name
.Const
)
1379 // Copy position information from old expr into new expr,
1380 // in case expression being replaced is first on line.
1381 // See golang.org/issue/6563.
1382 pos
:= (*r
.Expr
).Pos()
1383 if x
, ok
:= expr
.(*ast
.Ident
); ok
{
1384 expr
= &ast
.Ident
{NamePos
: pos
, Name
: x
.Name
}
1387 // Change AST, because some later processing depends on it,
1388 // and also because -godefs mode still prints the AST.
1392 // Record source-level edit for cgo output.
1394 // Prepend a space in case the earlier code ends
1395 // with '/', which would give us a "//" comment.
1396 repl
:= " " + gofmtPos(expr
, old
.Pos())
1397 end
:= fset
.Position(old
.End())
1398 // Subtract 1 from the column if we are going to
1399 // append a close parenthesis. That will set the
1400 // correct column for the following characters.
1402 if r
.Name
.Kind
!= "type" {
1405 if end
.Column
> sub
{
1406 repl
= fmt
.Sprintf("%s /*line :%d:%d*/", repl
, end
.Line
, end
.Column
-sub
)
1408 if r
.Name
.Kind
!= "type" {
1409 repl
= "(" + repl
+ ")"
1411 f
.Edit
.Replace(f
.offset(old
.Pos()), f
.offset(old
.End()), repl
)
1415 // Remove functions only used as expressions, so their respective
1416 // bridge functions are not generated.
1417 for name
, used
:= range functions
{
1419 delete(f
.Name
, name
)
1424 // rewriteName returns the expression used to rewrite a reference.
1425 func (p
*Package
) rewriteName(f
*File
, r
*Ref
) ast
.Expr
{
1426 var expr ast
.Expr
= ast
.NewIdent(r
.Name
.Mangle
) // default
1428 case ctxCall
, ctxCall2
:
1429 if r
.Name
.Kind
!= "func" {
1430 if r
.Name
.Kind
== "type" {
1432 if r
.Name
.Type
== nil {
1433 error_(r
.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r
.Name
.Go
), r
.Name
.C
)
1436 expr
= r
.Name
.Type
.Go
1439 error_(r
.Pos(), "call of non-function C.%s", fixGo(r
.Name
.Go
))
1442 if r
.Context
== ctxCall2
{
1443 if r
.Name
.Go
== "_CMalloc" {
1444 error_(r
.Pos(), "no two-result form for C.malloc")
1447 // Invent new Name for the two-result function.
1448 n
:= f
.Name
["2"+r
.Name
.Go
]
1453 n
.Mangle
= "_C2func_" + n
.Go
1454 f
.Name
["2"+r
.Name
.Go
] = n
1456 expr
= ast
.NewIdent(n
.Mangle
)
1461 switch r
.Name
.Kind
{
1463 if builtinDefs
[r
.Name
.C
] != "" {
1464 error_(r
.Pos(), "use of builtin '%s' not in function call", fixGo(r
.Name
.C
))
1467 // Function is being used in an expression, to e.g. pass around a C function pointer.
1468 // Create a new Name for this Ref which causes the variable to be declared in Go land.
1469 fpName
:= "fp_" + r
.Name
.Go
1470 name
:= f
.Name
[fpName
]
1476 Type
: &Type
{Size
: p
.PtrSize
, Align
: p
.PtrSize
, C
: c("void*"), Go
: ast
.NewIdent("unsafe.Pointer")},
1479 f
.Name
[fpName
] = name
1482 // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
1483 // function is defined in out.go and simply returns its argument. See
1485 expr
= &ast
.CallExpr
{
1486 Fun
: &ast
.Ident
{NamePos
: (*r
.Expr
).Pos(), Name
: "_Cgo_ptr"},
1487 Args
: []ast
.Expr
{ast
.NewIdent(name
.Mangle
)},
1490 // Okay - might be new(T)
1491 if r
.Name
.Type
== nil {
1492 error_(r
.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r
.Name
.Go
), r
.Name
.C
)
1495 expr
= r
.Name
.Type
.Go
1497 expr
= &ast
.StarExpr
{Star
: (*r
.Expr
).Pos(), X
: expr
}
1499 expr
= &ast
.CallExpr
{Fun
: expr
}
1502 if r
.Name
.Kind
== "var" {
1503 expr
= &ast
.StarExpr
{Star
: (*r
.Expr
).Pos(), X
: expr
}
1505 error_(r
.Pos(), "only C variables allowed in selector expression %s", fixGo(r
.Name
.Go
))
1508 if r
.Name
.Kind
!= "type" {
1509 error_(r
.Pos(), "expression C.%s used as type", fixGo(r
.Name
.Go
))
1510 } else if r
.Name
.Type
== nil {
1511 // Use of C.enum_x, C.struct_x or C.union_x without C definition.
1512 // GCC won't raise an error when using pointers to such unknown types.
1513 error_(r
.Pos(), "type C.%s: undefined C type '%s'", fixGo(r
.Name
.Go
), r
.Name
.C
)
1515 expr
= r
.Name
.Type
.Go
1518 if r
.Name
.Kind
== "func" {
1519 error_(r
.Pos(), "must call C.%s", fixGo(r
.Name
.Go
))
1525 // gofmtPos returns the gofmt-formatted string for an AST node,
1526 // with a comment setting the position before the node.
1527 func gofmtPos(n ast
.Expr
, pos token
.Pos
) string {
1529 p
:= fset
.Position(pos
)
1533 return fmt
.Sprintf("/*line :%d:%d*/%s", p
.Line
, p
.Column
, s
)
1536 // gccBaseCmd returns the start of the compiler command line.
1537 // It uses $CC if set, or else $GCC, or else the compiler recorded
1538 // during the initial build as defaultCC.
1539 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
1540 func (p
*Package
) gccBaseCmd() []string {
1541 // Use $CC if set, since that's what the build uses.
1542 if ret
:= strings
.Fields(os
.Getenv("CC")); len(ret
) > 0 {
1545 // Try $GCC if set, since that's what we used to use.
1546 if ret
:= strings
.Fields(os
.Getenv("GCC")); len(ret
) > 0 {
1549 return strings
.Fields(defaultCC(goos
, goarch
))
1552 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1553 func (p
*Package
) gccMachine() []string {
1556 return []string{"-m64"}
1558 return []string{"-m32"}
1560 return []string{"-marm"} // not thumb
1562 return []string{"-m31"}
1564 return []string{"-m64"}
1565 case "mips64", "mips64le":
1566 return []string{"-mabi=64"}
1567 case "mips", "mipsle":
1568 return []string{"-mabi=32"}
1571 return []string{"-maix64"}
1577 func gccTmp() string {
1578 return *objDir
+ "_cgo_.o"
1581 // gccCmd returns the gcc command line to use for compiling
1583 func (p
*Package
) gccCmd() []string {
1584 c
:= append(p
.gccBaseCmd(),
1585 "-w", // no warnings
1586 "-Wno-error", // warnings are not errors
1587 "-o"+gccTmp(), // write object to tmp
1588 "-gdwarf-2", // generate DWARF v2 debugging symbols
1589 "-c", // do not link
1590 "-xc", // input language is C
1595 // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
1596 // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
1597 // flag to disable the warning. Yes, really good diagnostics, clang.
1598 "-Wno-unknown-warning-option",
1599 "-Wno-unneeded-internal-declaration",
1600 "-Wno-unused-function",
1601 "-Qunused-arguments",
1602 // Clang embeds prototypes for some builtin functions,
1603 // like malloc and calloc, but all size_t parameters are
1604 // incorrectly typed unsigned long. We work around that
1605 // by disabling the builtin functions (this is safe as
1606 // it won't affect the actual compilation of the C code).
1607 // See: https://golang.org/issue/6506.
1612 c
= append(c
, p
.GccOptions
...)
1613 c
= append(c
, p
.gccMachine()...)
1615 c
= append(c
, "-maix64")
1616 c
= append(c
, "-mcmodel=large")
1618 c
= append(c
, "-") //read input from standard input
1622 // gccDebug runs gcc -gdwarf-2 over the C program stdin and
1623 // returns the corresponding DWARF data and, if present, debug data block.
1624 func (p
*Package
) gccDebug(stdin
[]byte, nnames
int) (d
*dwarf
.Data
, ints
[]int64, floats
[]float64, strs
[]string) {
1625 runGcc(stdin
, p
.gccCmd())
1627 isDebugInts
:= func(s
string) bool {
1628 // Some systems use leading _ to denote non-assembly symbols.
1629 return s
== "__cgodebug_ints" || s
== "___cgodebug_ints"
1631 isDebugFloats
:= func(s
string) bool {
1632 // Some systems use leading _ to denote non-assembly symbols.
1633 return s
== "__cgodebug_floats" || s
== "___cgodebug_floats"
1635 indexOfDebugStr
:= func(s
string) int {
1636 // Some systems use leading _ to denote non-assembly symbols.
1637 if strings
.HasPrefix(s
, "___") {
1640 if strings
.HasPrefix(s
, "__cgodebug_str__") {
1641 if n
, err
:= strconv
.Atoi(s
[len("__cgodebug_str__"):]); err
== nil {
1647 indexOfDebugStrlen
:= func(s
string) int {
1648 // Some systems use leading _ to denote non-assembly symbols.
1649 if strings
.HasPrefix(s
, "___") {
1652 if strings
.HasPrefix(s
, "__cgodebug_strlen__") {
1653 if n
, err
:= strconv
.Atoi(s
[len("__cgodebug_strlen__"):]); err
== nil {
1660 strs
= make([]string, nnames
)
1662 strdata
:= make(map[int]string, nnames
)
1663 strlens
:= make(map[int]int, nnames
)
1665 buildStrings
:= func() {
1666 for n
, strlen
:= range strlens
{
1668 if len(data
) <= strlen
{
1669 fatalf("invalid string literal")
1671 strs
[n
] = data
[:strlen
]
1675 if f
, err
:= macho
.Open(gccTmp()); err
== nil {
1679 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err
)
1682 if f
.Symtab
!= nil {
1683 for i
:= range f
.Symtab
.Syms
{
1684 s
:= &f
.Symtab
.Syms
[i
]
1686 case isDebugInts(s
.Name
):
1687 // Found it. Now find data section.
1688 if i
:= int(s
.Sect
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1689 sect
:= f
.Sections
[i
]
1690 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1691 if sdat
, err
:= sect
.Data(); err
== nil {
1692 data
:= sdat
[s
.Value
-sect
.Addr
:]
1693 ints
= make([]int64, len(data
)/8)
1694 for i
:= range ints
{
1695 ints
[i
] = int64(bo
.Uint64(data
[i
*8:]))
1700 case isDebugFloats(s
.Name
):
1701 // Found it. Now find data section.
1702 if i
:= int(s
.Sect
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1703 sect
:= f
.Sections
[i
]
1704 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1705 if sdat
, err
:= sect
.Data(); err
== nil {
1706 data
:= sdat
[s
.Value
-sect
.Addr
:]
1707 floats
= make([]float64, len(data
)/8)
1708 for i
:= range floats
{
1709 floats
[i
] = math
.Float64frombits(bo
.Uint64(data
[i
*8:]))
1715 if n
:= indexOfDebugStr(s
.Name
); n
!= -1 {
1716 // Found it. Now find data section.
1717 if i
:= int(s
.Sect
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1718 sect
:= f
.Sections
[i
]
1719 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1720 if sdat
, err
:= sect
.Data(); err
== nil {
1721 data
:= sdat
[s
.Value
-sect
.Addr
:]
1722 strdata
[n
] = string(data
)
1728 if n
:= indexOfDebugStrlen(s
.Name
); n
!= -1 {
1729 // Found it. Now find data section.
1730 if i
:= int(s
.Sect
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1731 sect
:= f
.Sections
[i
]
1732 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1733 if sdat
, err
:= sect
.Data(); err
== nil {
1734 data
:= sdat
[s
.Value
-sect
.Addr
:]
1735 strlen
:= bo
.Uint64(data
[:8])
1736 if strlen
> (1<<(uint(p
.IntSize
*8)-1) - 1) { // greater than MaxInt?
1737 fatalf("string literal too big")
1739 strlens
[n
] = int(strlen
)
1750 return d
, ints
, floats
, strs
1753 if f
, err
:= elf
.Open(gccTmp()); err
== nil {
1757 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err
)
1760 symtab
, err
:= f
.Symbols()
1762 for i
:= range symtab
{
1765 case isDebugInts(s
.Name
):
1766 // Found it. Now find data section.
1767 if i
:= int(s
.Section
); 0 <= i
&& i
< len(f
.Sections
) {
1768 sect
:= f
.Sections
[i
]
1769 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1770 if sdat
, err
:= sect
.Data(); err
== nil {
1771 data
:= sdat
[s
.Value
-sect
.Addr
:]
1772 ints
= make([]int64, len(data
)/8)
1773 for i
:= range ints
{
1774 ints
[i
] = int64(bo
.Uint64(data
[i
*8:]))
1779 case isDebugFloats(s
.Name
):
1780 // Found it. Now find data section.
1781 if i
:= int(s
.Section
); 0 <= i
&& i
< len(f
.Sections
) {
1782 sect
:= f
.Sections
[i
]
1783 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1784 if sdat
, err
:= sect
.Data(); err
== nil {
1785 data
:= sdat
[s
.Value
-sect
.Addr
:]
1786 floats
= make([]float64, len(data
)/8)
1787 for i
:= range floats
{
1788 floats
[i
] = math
.Float64frombits(bo
.Uint64(data
[i
*8:]))
1794 if n
:= indexOfDebugStr(s
.Name
); n
!= -1 {
1795 // Found it. Now find data section.
1796 if i
:= int(s
.Section
); 0 <= i
&& i
< len(f
.Sections
) {
1797 sect
:= f
.Sections
[i
]
1798 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1799 if sdat
, err
:= sect
.Data(); err
== nil {
1800 data
:= sdat
[s
.Value
-sect
.Addr
:]
1801 strdata
[n
] = string(data
)
1807 if n
:= indexOfDebugStrlen(s
.Name
); n
!= -1 {
1808 // Found it. Now find data section.
1809 if i
:= int(s
.Section
); 0 <= i
&& i
< len(f
.Sections
) {
1810 sect
:= f
.Sections
[i
]
1811 if sect
.Addr
<= s
.Value
&& s
.Value
< sect
.Addr
+sect
.Size
{
1812 if sdat
, err
:= sect
.Data(); err
== nil {
1813 data
:= sdat
[s
.Value
-sect
.Addr
:]
1814 strlen
:= bo
.Uint64(data
[:8])
1815 if strlen
> (1<<(uint(p
.IntSize
*8)-1) - 1) { // greater than MaxInt?
1816 fatalf("string literal too big")
1818 strlens
[n
] = int(strlen
)
1829 return d
, ints
, floats
, strs
1832 if f
, err
:= pe
.Open(gccTmp()); err
== nil {
1836 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err
)
1838 bo
:= binary
.LittleEndian
1839 for _
, s
:= range f
.Symbols
{
1841 case isDebugInts(s
.Name
):
1842 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1843 sect
:= f
.Sections
[i
]
1844 if s
.Value
< sect
.Size
{
1845 if sdat
, err
:= sect
.Data(); err
== nil {
1846 data
:= sdat
[s
.Value
:]
1847 ints
= make([]int64, len(data
)/8)
1848 for i
:= range ints
{
1849 ints
[i
] = int64(bo
.Uint64(data
[i
*8:]))
1854 case isDebugFloats(s
.Name
):
1855 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1856 sect
:= f
.Sections
[i
]
1857 if s
.Value
< sect
.Size
{
1858 if sdat
, err
:= sect
.Data(); err
== nil {
1859 data
:= sdat
[s
.Value
:]
1860 floats
= make([]float64, len(data
)/8)
1861 for i
:= range floats
{
1862 floats
[i
] = math
.Float64frombits(bo
.Uint64(data
[i
*8:]))
1868 if n
:= indexOfDebugStr(s
.Name
); n
!= -1 {
1869 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1870 sect
:= f
.Sections
[i
]
1871 if s
.Value
< sect
.Size
{
1872 if sdat
, err
:= sect
.Data(); err
== nil {
1873 data
:= sdat
[s
.Value
:]
1874 strdata
[n
] = string(data
)
1880 if n
:= indexOfDebugStrlen(s
.Name
); n
!= -1 {
1881 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1882 sect
:= f
.Sections
[i
]
1883 if s
.Value
< sect
.Size
{
1884 if sdat
, err
:= sect
.Data(); err
== nil {
1885 data
:= sdat
[s
.Value
:]
1886 strlen
:= bo
.Uint64(data
[:8])
1887 if strlen
> (1<<(uint(p
.IntSize
*8)-1) - 1) { // greater than MaxInt?
1888 fatalf("string literal too big")
1890 strlens
[n
] = int(strlen
)
1901 return d
, ints
, floats
, strs
1904 if f
, err
:= xcoff
.Open(gccTmp()); err
== nil {
1908 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err
)
1910 bo
:= binary
.BigEndian
1911 for _
, s
:= range f
.Symbols
{
1913 case isDebugInts(s
.Name
):
1914 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1915 sect
:= f
.Sections
[i
]
1916 if s
.Value
< sect
.Size
{
1917 if sdat
, err
:= sect
.Data(); err
== nil {
1918 data
:= sdat
[s
.Value
:]
1919 ints
= make([]int64, len(data
)/8)
1920 for i
:= range ints
{
1921 ints
[i
] = int64(bo
.Uint64(data
[i
*8:]))
1926 case isDebugFloats(s
.Name
):
1927 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1928 sect
:= f
.Sections
[i
]
1929 if s
.Value
< sect
.Size
{
1930 if sdat
, err
:= sect
.Data(); err
== nil {
1931 data
:= sdat
[s
.Value
:]
1932 floats
= make([]float64, len(data
)/8)
1933 for i
:= range floats
{
1934 floats
[i
] = math
.Float64frombits(bo
.Uint64(data
[i
*8:]))
1940 if n
:= indexOfDebugStr(s
.Name
); n
!= -1 {
1941 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1942 sect
:= f
.Sections
[i
]
1943 if s
.Value
< sect
.Size
{
1944 if sdat
, err
:= sect
.Data(); err
== nil {
1945 data
:= sdat
[s
.Value
:]
1946 strdata
[n
] = string(data
)
1952 if n
:= indexOfDebugStrlen(s
.Name
); n
!= -1 {
1953 if i
:= int(s
.SectionNumber
) - 1; 0 <= i
&& i
< len(f
.Sections
) {
1954 sect
:= f
.Sections
[i
]
1955 if s
.Value
< sect
.Size
{
1956 if sdat
, err
:= sect
.Data(); err
== nil {
1957 data
:= sdat
[s
.Value
:]
1958 strlen
:= bo
.Uint64(data
[:8])
1959 if strlen
> (1<<(uint(p
.IntSize
*8)-1) - 1) { // greater than MaxInt?
1960 fatalf("string literal too big")
1962 strlens
[n
] = int(strlen
)
1972 return d
, ints
, floats
, strs
1974 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
1975 panic("not reached")
1978 // gccDefines runs gcc -E -dM -xc - over the C program stdin
1979 // and returns the corresponding standard output, which is the
1980 // #defines that gcc encountered while processing the input
1981 // and its included files.
1982 func (p
*Package
) gccDefines(stdin
[]byte) string {
1983 base
:= append(p
.gccBaseCmd(), "-E", "-dM", "-xc")
1984 base
= append(base
, p
.gccMachine()...)
1985 stdout
, _
:= runGcc(stdin
, append(append(base
, p
.GccOptions
...), "-"))
1989 // gccErrors runs gcc over the C program stdin and returns
1990 // the errors that gcc prints. That is, this function expects
1992 func (p
*Package
) gccErrors(stdin
[]byte) string {
1993 // TODO(rsc): require failure
1996 // Optimization options can confuse the error messages; remove them.
1997 nargs
:= make([]string, 0, len(args
))
1998 for _
, arg
:= range args
{
1999 if !strings
.HasPrefix(arg
, "-O") {
2000 nargs
= append(nargs
, arg
)
2004 // Force -O0 optimization but keep the trailing "-" at the end.
2005 nargs
= append(nargs
, "-O0")
2007 nargs
[nl
-2], nargs
[nl
-1] = nargs
[nl
-1], nargs
[nl
-2]
2010 fmt
.Fprintf(os
.Stderr
, "$ %s <<EOF\n", strings
.Join(nargs
, " "))
2011 os
.Stderr
.Write(stdin
)
2012 fmt
.Fprint(os
.Stderr
, "EOF\n")
2014 stdout
, stderr
, _
:= run(stdin
, nargs
)
2016 os
.Stderr
.Write(stdout
)
2017 os
.Stderr
.Write(stderr
)
2019 return string(stderr
)
2022 // runGcc runs the gcc command line args with stdin on standard input.
2023 // If the command exits with a non-zero exit status, runGcc prints
2024 // details about what was run and exits.
2025 // Otherwise runGcc returns the data written to standard output and standard error.
2026 // Note that for some of the uses we expect useful data back
2027 // on standard error, but for those uses gcc must still exit 0.
2028 func runGcc(stdin
[]byte, args
[]string) (string, string) {
2030 fmt
.Fprintf(os
.Stderr
, "$ %s <<EOF\n", strings
.Join(args
, " "))
2031 os
.Stderr
.Write(stdin
)
2032 fmt
.Fprint(os
.Stderr
, "EOF\n")
2034 stdout
, stderr
, ok
:= run(stdin
, args
)
2036 os
.Stderr
.Write(stdout
)
2037 os
.Stderr
.Write(stderr
)
2040 os
.Stderr
.Write(stderr
)
2043 return string(stdout
), string(stderr
)
2046 // A typeConv is a translator from dwarf types to Go types
2047 // with equivalent memory layout.
2048 type typeConv
struct {
2049 // Cache of already-translated or in-progress types.
2052 // Map from types to incomplete pointers to those types.
2053 ptrs
map[string][]*Type
2054 // Keys of ptrs in insertion order (deterministic worklist)
2055 // ptrKeys contains exactly the keys in ptrs.
2056 ptrKeys
[]dwarf
.Type
2058 // Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
2059 getTypeIDs
map[string]bool
2061 // Predeclared types.
2063 byte ast
.Expr
// denotes padding
2064 int8, int16, int32, int64 ast
.Expr
2065 uint8, uint16, uint32, uint64, uintptr ast
.Expr
2066 float32, float64 ast
.Expr
2067 complex64
, complex128 ast
.Expr
2070 goVoid ast
.Expr
// _Ctype_void, denotes C's void
2071 goVoidPtr ast
.Expr
// unsafe.Pointer or *byte
2078 var typedef
= make(map[string]*Type
)
2079 var goIdent
= make(map[string]*ast
.Ident
)
2081 // unionWithPointer is true for a Go type that represents a C union (or class)
2082 // that may contain a pointer. This is used for cgo pointer checking.
2083 var unionWithPointer
= make(map[ast
.Expr
]bool)
2085 // anonymousStructTag provides a consistent tag for an anonymous struct.
2086 // The same dwarf.StructType pointer will always get the same tag.
2087 var anonymousStructTag
= make(map[*dwarf
.StructType
]string)
2089 func (c
*typeConv
) Init(ptrSize
, intSize
int64) {
2092 c
.m
= make(map[string]*Type
)
2093 c
.ptrs
= make(map[string][]*Type
)
2094 c
.getTypeIDs
= make(map[string]bool)
2095 c
.bool = c
.Ident("bool")
2096 c
.byte = c
.Ident("byte")
2097 c
.int8 = c
.Ident("int8")
2098 c
.int16 = c
.Ident("int16")
2099 c
.int32 = c
.Ident("int32")
2100 c
.int64 = c
.Ident("int64")
2101 c
.uint8 = c
.Ident("uint8")
2102 c
.uint16 = c
.Ident("uint16")
2103 c
.uint32 = c
.Ident("uint32")
2104 c
.uint64 = c
.Ident("uint64")
2105 c
.uintptr = c
.Ident("uintptr")
2106 c
.float32 = c
.Ident("float32")
2107 c
.float64 = c
.Ident("float64")
2108 c
.complex64
= c
.Ident("complex64")
2109 c
.complex128
= c
.Ident("complex128")
2110 c
.void
= c
.Ident("void")
2111 c
.string = c
.Ident("string")
2112 c
.goVoid
= c
.Ident("_Ctype_void")
2114 // Normally cgo translates void* to unsafe.Pointer,
2115 // but for historical reasons -godefs uses *byte instead.
2117 c
.goVoidPtr
= &ast
.StarExpr
{X
: c
.byte}
2119 c
.goVoidPtr
= c
.Ident("unsafe.Pointer")
2123 // base strips away qualifiers and typedefs to get the underlying type
2124 func base(dt dwarf
.Type
) dwarf
.Type
{
2126 if d
, ok
:= dt
.(*dwarf
.QualType
); ok
{
2130 if d
, ok
:= dt
.(*dwarf
.TypedefType
); ok
{
2139 // unqual strips away qualifiers from a DWARF type.
2140 // In general we don't care about top-level qualifiers.
2141 func unqual(dt dwarf
.Type
) dwarf
.Type
{
2143 if d
, ok
:= dt
.(*dwarf
.QualType
); ok
{
2152 // Map from dwarf text names to aliases we use in package "C".
2153 var dwarfToName
= map[string]string{
2155 "long unsigned int": "ulong",
2156 "unsigned int": "uint",
2157 "short unsigned int": "ushort",
2158 "unsigned short": "ushort", // Used by Clang; issue 13129.
2159 "short int": "short",
2160 "long long int": "longlong",
2161 "long long unsigned int": "ulonglong",
2162 "signed char": "schar",
2163 "unsigned char": "uchar",
2166 const signedDelta
= 64
2168 // String returns the current type representation. Format arguments
2169 // are assembled within this method so that any changes in mutable
2170 // values are taken into account.
2171 func (tr
*TypeRepr
) String() string {
2172 if len(tr
.Repr
) == 0 {
2175 if len(tr
.FormatArgs
) == 0 {
2178 return fmt
.Sprintf(tr
.Repr
, tr
.FormatArgs
...)
2181 // Empty reports whether the result of String would be "".
2182 func (tr
*TypeRepr
) Empty() bool {
2183 return len(tr
.Repr
) == 0
2186 // Set modifies the type representation.
2187 // If fargs are provided, repr is used as a format for fmt.Sprintf.
2188 // Otherwise, repr is used unprocessed as the type representation.
2189 func (tr
*TypeRepr
) Set(repr
string, fargs
...interface{}) {
2191 tr
.FormatArgs
= fargs
2194 // FinishType completes any outstanding type mapping work.
2195 // In particular, it resolves incomplete pointer types.
2196 func (c
*typeConv
) FinishType(pos token
.Pos
) {
2197 // Completing one pointer type might produce more to complete.
2198 // Keep looping until they're all done.
2199 for len(c
.ptrKeys
) > 0 {
2200 dtype
:= c
.ptrKeys
[0]
2201 dtypeKey
:= dtype
.String()
2202 c
.ptrKeys
= c
.ptrKeys
[1:]
2203 ptrs
:= c
.ptrs
[dtypeKey
]
2204 delete(c
.ptrs
, dtypeKey
)
2206 // Note Type might invalidate c.ptrs[dtypeKey].
2207 t
:= c
.Type(dtype
, pos
)
2208 for _
, ptr
:= range ptrs
{
2209 ptr
.Go
.(*ast
.StarExpr
).X
= t
.Go
2210 ptr
.C
.Set("%s*", t
.C
)
2215 // Type returns a *Type with the same memory layout as
2216 // dtype when used as the type of a variable or a struct field.
2217 func (c
*typeConv
) Type(dtype dwarf
.Type
, pos token
.Pos
) *Type
{
2218 return c
.loadType(dtype
, pos
, "")
2221 // loadType recursively loads the requested dtype and its dependency graph.
2222 func (c
*typeConv
) loadType(dtype dwarf
.Type
, pos token
.Pos
, parent
string) *Type
{
2223 // Always recompute bad pointer typedefs, as the set of such
2224 // typedefs changes as we see more types.
2226 if dtt
, ok
:= dtype
.(*dwarf
.TypedefType
); ok
&& c
.badPointerTypedef(dtt
) {
2230 // The cache key should be relative to its parent.
2231 // See issue https://golang.org/issue/31891
2232 key
:= parent
+ " > " + dtype
.String()
2235 if t
, ok
:= c
.m
[key
]; ok
{
2237 fatalf("%s: type conversion loop at %s", lineno(pos
), dtype
)
2244 t
.Size
= dtype
.Size() // note: wrong for array of pointers, corrected below
2246 t
.C
= &TypeRepr
{Repr
: dtype
.Common().Name
}
2249 switch dt
:= dtype
.(type) {
2251 fatalf("%s: unexpected type: %s", lineno(pos
), dtype
)
2253 case *dwarf
.AddrType
:
2254 if t
.Size
!= c
.ptrSize
{
2255 fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos
), t
.Size
, dtype
)
2260 case *dwarf
.ArrayType
:
2261 if dt
.StrideBitSize
> 0 {
2262 // Cannot represent bit-sized elements in Go.
2263 t
.Go
= c
.Opaque(t
.Size
)
2268 // Indicates flexible array member, which Go doesn't support.
2269 // Translate to zero-length array instead.
2272 sub
:= c
.Type(dt
.Type
, pos
)
2274 t
.Go
= &ast
.ArrayType
{
2275 Len
: c
.intExpr(count
),
2278 // Recalculate t.Size now that we know sub.Size.
2279 t
.Size
= count
* sub
.Size
2280 t
.C
.Set("__typeof__(%s[%d])", sub
.C
, dt
.Count
)
2282 case *dwarf
.BoolType
:
2286 case *dwarf
.CharType
:
2288 fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos
), t
.Size
, dtype
)
2293 case *dwarf
.EnumType
:
2294 if t
.Align
= t
.Size
; t
.Align
>= c
.ptrSize
{
2297 t
.C
.Set("enum " + dt
.EnumName
)
2299 t
.EnumValues
= make(map[string]int64)
2300 for _
, ev
:= range dt
.Val
{
2301 t
.EnumValues
[ev
.Name
] = ev
.Val
2303 signed
= signedDelta
2306 switch t
.Size
+ int64(signed
) {
2308 fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos
), t
.Size
, dtype
)
2317 case 1 + signedDelta
:
2319 case 2 + signedDelta
:
2321 case 4 + signedDelta
:
2323 case 8 + signedDelta
:
2327 case *dwarf
.FloatType
:
2330 fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos
), t
.Size
, dtype
)
2336 if t
.Align
= t
.Size
; t
.Align
>= c
.ptrSize
{
2340 case *dwarf
.ComplexType
:
2343 fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos
), t
.Size
, dtype
)
2349 if t
.Align
= t
.Size
/ 2; t
.Align
>= c
.ptrSize
{
2353 case *dwarf
.FuncType
:
2354 // No attempt at translation: would enable calls
2355 // directly between worlds, but we need to moderate those.
2359 case *dwarf
.IntType
:
2361 fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos
), dt
.BitSize
, dtype
)
2365 fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos
), t
.Size
, dtype
)
2375 t
.Go
= &ast
.ArrayType
{
2376 Len
: c
.intExpr(t
.Size
),
2380 if t
.Align
= t
.Size
; t
.Align
>= c
.ptrSize
{
2384 case *dwarf
.PtrType
:
2385 // Clang doesn't emit DW_AT_byte_size for pointer types.
2386 if t
.Size
!= c
.ptrSize
&& t
.Size
!= -1 {
2387 fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos
), t
.Size
, dtype
)
2392 if _
, ok
:= base(dt
.Type
).(*dwarf
.VoidType
); ok
{
2397 if d
, ok
:= dq
.(*dwarf
.QualType
); ok
{
2398 t
.C
.Set(d
.Qual
+ " " + t
.C
.String())
2407 // Placeholder initialization; completed in FinishType.
2408 t
.Go
= &ast
.StarExpr
{}
2409 t
.C
.Set("<incomplete>*")
2410 key
:= dt
.Type
.String()
2411 if _
, ok
:= c
.ptrs
[key
]; !ok
{
2412 c
.ptrKeys
= append(c
.ptrKeys
, dt
.Type
)
2414 c
.ptrs
[key
] = append(c
.ptrs
[key
], t
)
2416 case *dwarf
.QualType
:
2417 t1
:= c
.Type(dt
.Type
, pos
)
2421 if unionWithPointer
[t1
.Go
] {
2422 unionWithPointer
[t
.Go
] = true
2426 t
.C
.Set("%s "+dt
.Qual
, t1
.C
)
2429 case *dwarf
.StructType
:
2430 // Convert to Go struct, being careful about alignment.
2431 // Have to give it a name to simulate C "struct foo" references.
2432 tag
:= dt
.StructName
2433 if dt
.ByteSize
< 0 && tag
== "" { // opaque unnamed struct - should not be possible
2437 tag
= anonymousStructTag
[dt
]
2439 tag
= "__" + strconv
.Itoa(tagGen
)
2441 anonymousStructTag
[dt
] = tag
2443 } else if t
.C
.Empty() {
2444 t
.C
.Set(dt
.Kind
+ " " + tag
)
2446 name
:= c
.Ident("_Ctype_" + dt
.Kind
+ "_" + tag
)
2447 t
.Go
= name
// publish before recursive calls
2448 goIdent
[name
.Name
] = name
2449 if dt
.ByteSize
< 0 {
2450 // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
2451 // so execute the basic things that the struct case would do
2452 // other than try to determine a Go representation.
2454 tt
.C
= &TypeRepr
{"%s %s", []interface{}{dt
.Kind
, tag
}}
2455 tt
.Go
= c
.Ident("struct{}")
2456 typedef
[name
.Name
] = &tt
2460 case "class", "union":
2461 t
.Go
= c
.Opaque(t
.Size
)
2462 if c
.dwarfHasPointer(dt
, pos
) {
2463 unionWithPointer
[t
.Go
] = true
2466 t
.C
.Set("__typeof__(unsigned char[%d])", t
.Size
)
2468 t
.Align
= 1 // TODO: should probably base this on field alignment.
2469 typedef
[name
.Name
] = t
2471 g
, csyntax
, align
:= c
.Struct(dt
, pos
)
2478 tt
.C
= &TypeRepr
{"struct %s", []interface{}{tag
}}
2481 typedef
[name
.Name
] = &tt
2484 case *dwarf
.TypedefType
:
2485 // Record typedef for printing.
2486 if dt
.Name
== "_GoString_" {
2487 // Special C name for Go string type.
2488 // Knows string layout used by compilers: pointer plus length,
2489 // which rounds up to 2 pointers after alignment.
2491 t
.Size
= c
.ptrSize
* 2
2495 if dt
.Name
== "_GoBytes_" {
2496 // Special C name for Go []byte type.
2497 // Knows slice layout used by compilers: pointer, length, cap.
2498 t
.Go
= c
.Ident("[]byte")
2499 t
.Size
= c
.ptrSize
+ 4 + 4
2503 name
:= c
.Ident("_Ctype_" + dt
.Name
)
2504 goIdent
[name
.Name
] = name
2506 if c
.anonymousStructTypedef(dt
) {
2507 // only load type recursively for typedefs of anonymous
2508 // structs, see issues 37479 and 37621.
2511 sub
:= c
.loadType(dt
.Type
, pos
, akey
)
2512 if c
.badPointerTypedef(dt
) {
2513 // Treat this typedef as a uintptr.
2518 // Make sure we update any previously computed type.
2519 if oldType
:= typedef
[name
.Name
]; oldType
!= nil {
2521 oldType
.BadPointer
= true
2525 t
.BadPointer
= sub
.BadPointer
2526 if unionWithPointer
[sub
.Go
] {
2527 unionWithPointer
[t
.Go
] = true
2531 oldType
:= typedef
[name
.Name
]
2535 tt
.BadPointer
= sub
.BadPointer
2536 typedef
[name
.Name
] = &tt
2539 // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
2540 // use that as the Go form for this typedef too, so that the typedef will be interchangeable
2541 // with the base type.
2542 // In -godefs mode, do this for all typedefs.
2543 if isStructUnionClass(sub
.Go
) ||
*godefs
{
2546 if isStructUnionClass(sub
.Go
) {
2547 // Use the typedef name for C code.
2548 typedef
[sub
.Go
.(*ast
.Ident
).Name
].C
= t
.C
2551 // If we've seen this typedef before, and it
2552 // was an anonymous struct/union/class before
2553 // too, use the old definition.
2554 // TODO: it would be safer to only do this if
2555 // we verify that the types are the same.
2556 if oldType
!= nil && isStructUnionClass(oldType
.Go
) {
2561 case *dwarf
.UcharType
:
2563 fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos
), t
.Size
, dtype
)
2568 case *dwarf
.UintType
:
2570 fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos
), dt
.BitSize
, dtype
)
2574 fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos
), t
.Size
, dtype
)
2584 t
.Go
= &ast
.ArrayType
{
2585 Len
: c
.intExpr(t
.Size
),
2589 if t
.Align
= t
.Size
; t
.Align
>= c
.ptrSize
{
2593 case *dwarf
.VoidType
:
2599 switch dtype
.(type) {
2600 case *dwarf
.AddrType
, *dwarf
.BoolType
, *dwarf
.CharType
, *dwarf
.ComplexType
, *dwarf
.IntType
, *dwarf
.FloatType
, *dwarf
.UcharType
, *dwarf
.UintType
:
2601 s
:= dtype
.Common().Name
2603 if ss
, ok
:= dwarfToName
[s
]; ok
{
2606 s
= strings
.Replace(s
, " ", "", -1)
2607 name
:= c
.Ident("_Ctype_" + s
)
2609 typedef
[name
.Name
] = &tt
2617 // Unsized types are [0]byte, unless they're typedefs of other types
2618 // or structs with tags.
2619 // if so, use the name we've already defined.
2621 switch dt
:= dtype
.(type) {
2622 case *dwarf
.TypedefType
:
2624 case *dwarf
.StructType
:
2625 if dt
.StructName
!= "" {
2638 fatalf("%s: internal error: did not create C name for %s", lineno(pos
), dtype
)
2644 // isStructUnionClass reports whether the type described by the Go syntax x
2645 // is a struct, union, or class with a tag.
2646 func isStructUnionClass(x ast
.Expr
) bool {
2647 id
, ok
:= x
.(*ast
.Ident
)
2652 return strings
.HasPrefix(name
, "_Ctype_struct_") ||
2653 strings
.HasPrefix(name
, "_Ctype_union_") ||
2654 strings
.HasPrefix(name
, "_Ctype_class_")
2657 // FuncArg returns a Go type with the same memory layout as
2658 // dtype when used as the type of a C function argument.
2659 func (c
*typeConv
) FuncArg(dtype dwarf
.Type
, pos token
.Pos
) *Type
{
2660 t
:= c
.Type(unqual(dtype
), pos
)
2661 switch dt
:= dtype
.(type) {
2662 case *dwarf
.ArrayType
:
2663 // Arrays are passed implicitly as pointers in C.
2664 // In Go, we must be explicit.
2670 Go
: &ast
.StarExpr
{X
: t
.Go
},
2673 case *dwarf
.TypedefType
:
2674 // C has much more relaxed rules than Go for
2675 // implicit type conversions. When the parameter
2676 // is type T defined as *X, simulate a little of the
2677 // laxness of C by making the argument *X instead of T.
2678 if ptr
, ok
:= base(dt
.Type
).(*dwarf
.PtrType
); ok
{
2679 // Unless the typedef happens to point to void* since
2680 // Go has special rules around using unsafe.Pointer.
2681 if _
, void
:= base(ptr
.Type
).(*dwarf
.VoidType
); void
{
2684 // ...or the typedef is one in which we expect bad pointers.
2685 // It will be a uintptr instead of *X.
2686 if c
.baseBadPointerTypedef(dt
) {
2690 t
= c
.Type(ptr
, pos
)
2695 // For a struct/union/class, remember the C spelling,
2696 // in case it has __attribute__((unavailable)).
2698 if isStructUnionClass(t
.Go
) {
2706 // FuncType returns the Go type analogous to dtype.
2707 // There is no guarantee about matching memory layout.
2708 func (c
*typeConv
) FuncType(dtype
*dwarf
.FuncType
, pos token
.Pos
) *FuncType
{
2709 p
:= make([]*Type
, len(dtype
.ParamType
))
2710 gp
:= make([]*ast
.Field
, len(dtype
.ParamType
))
2711 for i
, f
:= range dtype
.ParamType
{
2712 // gcc's DWARF generator outputs a single DotDotDotType parameter for
2713 // function pointers that specify no parameters (e.g. void
2714 // (*__cgo_0)()). Treat this special case as void. This case is
2715 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
2717 if _
, ok
:= f
.(*dwarf
.DotDotDotType
); ok
&& i
== 0 {
2721 p
[i
] = c
.FuncArg(f
, pos
)
2722 gp
[i
] = &ast
.Field
{Type
: p
[i
].Go
}
2726 if _
, ok
:= base(dtype
.ReturnType
).(*dwarf
.VoidType
); ok
{
2727 gr
= []*ast
.Field
{{Type
: c
.goVoid
}}
2728 } else if dtype
.ReturnType
!= nil {
2729 r
= c
.Type(unqual(dtype
.ReturnType
), pos
)
2730 gr
= []*ast
.Field
{{Type
: r
.Go
}}
2736 Params
: &ast
.FieldList
{List
: gp
},
2737 Results
: &ast
.FieldList
{List
: gr
},
2743 func (c
*typeConv
) Ident(s
string) *ast
.Ident
{
2744 return ast
.NewIdent(s
)
2747 // Opaque type of n bytes.
2748 func (c
*typeConv
) Opaque(n
int64) ast
.Expr
{
2749 return &ast
.ArrayType
{
2755 // Expr for integer n.
2756 func (c
*typeConv
) intExpr(n
int64) ast
.Expr
{
2757 return &ast
.BasicLit
{
2759 Value
: strconv
.FormatInt(n
, 10),
2763 // Add padding of given size to fld.
2764 func (c
*typeConv
) pad(fld
[]*ast
.Field
, sizes
[]int64, size
int64) ([]*ast
.Field
, []int64) {
2767 fld
[n
] = &ast
.Field
{Names
: []*ast
.Ident
{c
.Ident("_")}, Type
: c
.Opaque(size
)}
2768 sizes
= sizes
[0 : n
+1]
2773 // Struct conversion: return Go and (gc) C syntax for type.
2774 func (c
*typeConv
) Struct(dt
*dwarf
.StructType
, pos token
.Pos
) (expr
*ast
.StructType
, csyntax
string, align
int64) {
2775 // Minimum alignment for a struct is 1 byte.
2778 var buf bytes
.Buffer
2779 buf
.WriteString("struct {")
2780 fld
:= make([]*ast
.Field
, 0, 2*len(dt
.Field
)+1) // enough for padding around every field
2781 sizes
:= make([]int64, 0, 2*len(dt
.Field
)+1)
2784 // Rename struct fields that happen to be named Go keywords into
2785 // _{keyword}. Create a map from C ident -> Go ident. The Go ident will
2786 // be mangled. Any existing identifier that already has the same name on
2787 // the C-side will cause the Go-mangled version to be prefixed with _.
2788 // (e.g. in a struct with fields '_type' and 'type', the latter would be
2789 // rendered as '__type' in Go).
2790 ident
:= make(map[string]string)
2791 used
:= make(map[string]bool)
2792 for _
, f
:= range dt
.Field
{
2793 ident
[f
.Name
] = f
.Name
2798 for cid
, goid
:= range ident
{
2799 if token
.Lookup(goid
).IsKeyword() {
2803 // Also avoid existing fields
2804 for _
, exist
:= used
[goid
]; exist
; _
, exist
= used
[goid
] {
2815 for _
, f
:= range dt
.Field
{
2819 // In godefs mode, if this field is a C11
2820 // anonymous union then treat the first field in the
2821 // union as the field in the struct. This handles
2822 // cases like the glibc <sys/resource.h> file; see
2825 if st
, ok
:= f
.Type
.(*dwarf
.StructType
); ok
&& name
== "" && st
.Kind
== "union" && len(st
.Field
) > 0 && !used
[st
.Field
[0].Name
] {
2826 name
= st
.Field
[0].Name
2828 ft
= st
.Field
[0].Type
2832 // TODO: Handle fields that are anonymous structs by
2833 // promoting the fields of the inner struct.
2835 t
:= c
.Type(ft
, pos
)
2845 size
= f
.BitSize
/ 8
2846 name
:= tgo
.(*ast
.Ident
).String()
2847 if strings
.HasPrefix(name
, "int") {
2852 tgo
= ast
.NewIdent(name
+ fmt
.Sprint(f
.BitSize
))
2856 if talign
> 0 && f
.ByteOffset%talign
!= 0 {
2857 // Drop misaligned fields, the same way we drop integer bit fields.
2858 // The goal is to make available what can be made available.
2859 // Otherwise one bad and unneeded field in an otherwise okay struct
2860 // makes the whole program not compile. Much of the time these
2861 // structs are in system headers that cannot be corrected.
2865 // Round off up to talign, assumed to be a power of 2.
2866 off
= (off
+ talign
- 1) &^ (talign
- 1)
2868 if f
.ByteOffset
> off
{
2869 fld
, sizes
= c
.pad(fld
, sizes
, f
.ByteOffset
-off
)
2872 if f
.ByteOffset
< off
{
2873 // Drop a packed field that we can't represent.
2880 name
= fmt
.Sprintf("anon%d", anon
)
2884 fld
[n
] = &ast
.Field
{Names
: []*ast
.Ident
{c
.Ident(ident
[name
])}, Type
: tgo
}
2885 sizes
= sizes
[0 : n
+1]
2888 buf
.WriteString(t
.C
.String())
2889 buf
.WriteString(" ")
2890 buf
.WriteString(name
)
2891 buf
.WriteString("; ")
2896 if off
< dt
.ByteSize
{
2897 fld
, sizes
= c
.pad(fld
, sizes
, dt
.ByteSize
-off
)
2901 // If the last field in a non-zero-sized struct is zero-sized
2902 // the compiler is going to pad it by one (see issue 9401).
2903 // We can't permit that, because then the size of the Go
2904 // struct will not be the same as the size of the C struct.
2905 // Our only option in such a case is to remove the field,
2906 // which means that it cannot be referenced from Go.
2907 for off
> 0 && sizes
[len(sizes
)-1] == 0 {
2910 sizes
= sizes
[0 : n
-1]
2913 if off
!= dt
.ByteSize
{
2914 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos
), off
, dt
.ByteSize
)
2916 buf
.WriteString("}")
2917 csyntax
= buf
.String()
2922 expr
= &ast
.StructType
{Fields
: &ast
.FieldList
{List
: fld
}}
2926 // dwarfHasPointer reports whether the DWARF type dt contains a pointer.
2927 func (c
*typeConv
) dwarfHasPointer(dt dwarf
.Type
, pos token
.Pos
) bool {
2928 switch dt
:= dt
.(type) {
2930 fatalf("%s: unexpected type: %s", lineno(pos
), dt
)
2933 case *dwarf
.AddrType
, *dwarf
.BoolType
, *dwarf
.CharType
, *dwarf
.EnumType
,
2934 *dwarf
.FloatType
, *dwarf
.ComplexType
, *dwarf
.FuncType
,
2935 *dwarf
.IntType
, *dwarf
.UcharType
, *dwarf
.UintType
, *dwarf
.VoidType
:
2939 case *dwarf
.ArrayType
:
2940 return c
.dwarfHasPointer(dt
.Type
, pos
)
2942 case *dwarf
.PtrType
:
2945 case *dwarf
.QualType
:
2946 return c
.dwarfHasPointer(dt
.Type
, pos
)
2948 case *dwarf
.StructType
:
2949 for _
, f
:= range dt
.Field
{
2950 if c
.dwarfHasPointer(f
.Type
, pos
) {
2956 case *dwarf
.TypedefType
:
2957 if dt
.Name
== "_GoString_" || dt
.Name
== "_GoBytes_" {
2960 return c
.dwarfHasPointer(dt
.Type
, pos
)
2964 func upper(s
string) string {
2968 r
, size
:= utf8
.DecodeRuneInString(s
)
2972 return string(unicode
.ToUpper(r
)) + s
[size
:]
2975 // godefsFields rewrites field names for use in Go or C definitions.
2976 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
2977 // converts names to upper case, and rewrites _ into Pad_godefs_n,
2978 // so that all fields are exported.
2979 func godefsFields(fld
[]*ast
.Field
) {
2980 prefix
:= fieldPrefix(fld
)
2982 for _
, f
:= range fld
{
2983 for _
, n
:= range f
.Names
{
2984 if n
.Name
!= prefix
{
2985 n
.Name
= strings
.TrimPrefix(n
.Name
, prefix
)
2988 // Use exported name instead.
2989 n
.Name
= "Pad_cgo_" + strconv
.Itoa(npad
)
2992 n
.Name
= upper(n
.Name
)
2997 // fieldPrefix returns the prefix that should be removed from all the
2998 // field names when generating the C or Go code. For generated
2999 // C, we leave the names as is (tv_sec, tv_usec), since that's what
3000 // people are used to seeing in C. For generated Go code, such as
3001 // package syscall's data structures, we drop a common prefix
3002 // (so sec, usec, which will get turned into Sec, Usec for exporting).
3003 func fieldPrefix(fld
[]*ast
.Field
) string {
3005 for _
, f
:= range fld
{
3006 for _
, n
:= range f
.Names
{
3007 // Ignore field names that don't have the prefix we're
3008 // looking for. It is common in C headers to have fields
3009 // named, say, _pad in an otherwise prefixed header.
3010 // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
3011 // still want to remove the tv_ prefix.
3012 // The check for "orig_" here handles orig_eax in the
3013 // x86 ptrace register sets, which otherwise have all fields
3014 // with reg_ prefixes.
3015 if strings
.HasPrefix(n
.Name
, "orig_") || strings
.HasPrefix(n
.Name
, "_") {
3018 i
:= strings
.Index(n
.Name
, "_")
3023 prefix
= n
.Name
[:i
+1]
3024 } else if prefix
!= n
.Name
[:i
+1] {
3032 // anonymousStructTypedef reports whether dt is a C typedef for an anonymous
3034 func (c
*typeConv
) anonymousStructTypedef(dt
*dwarf
.TypedefType
) bool {
3035 st
, ok
:= dt
.Type
.(*dwarf
.StructType
)
3036 return ok
&& st
.StructName
== ""
3039 // badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
3040 // A typedef is bad if C code sometimes stores non-pointers in this type.
3041 // TODO: Currently our best solution is to find these manually and list them as
3042 // they come up. A better solution is desired.
3043 func (c
*typeConv
) badPointerTypedef(dt
*dwarf
.TypedefType
) bool {
3044 if c
.badCFType(dt
) {
3050 if c
.badEGLDisplay(dt
) {
3056 // baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef
3057 // as badPointerTypedef reports.
3058 func (c
*typeConv
) baseBadPointerTypedef(dt
*dwarf
.TypedefType
) bool {
3060 if t
, ok
:= dt
.Type
.(*dwarf
.TypedefType
); ok
{
3066 return c
.badPointerTypedef(dt
)
3069 func (c
*typeConv
) badCFType(dt
*dwarf
.TypedefType
) bool {
3070 // The real bad types are CFNumberRef and CFDateRef.
3071 // Sometimes non-pointers are stored in these types.
3072 // CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
3073 // We return true for the other *Ref types just so casting between them is easier.
3074 // We identify the correct set of types as those ending in Ref and for which
3075 // there exists a corresponding GetTypeID function.
3076 // See comment below for details about the bad pointers.
3077 if goos
!= "darwin" {
3081 if !strings
.HasSuffix(s
, "Ref") {
3088 if c
.getTypeIDs
[s
] {
3091 if i
:= strings
.Index(s
, "Mutable"); i
>= 0 && c
.getTypeIDs
[s
[:i
]+s
[i
+7:]] {
3092 // Mutable and immutable variants share a type ID.
3098 // Comment from Darwin's CFInternal.h
3100 // Tagged pointer support
3101 // Low-bit set means tagged object, next 3 bits (currently)
3102 // define the tagged object class, next 4 bits are for type
3103 // information for the specific tagged object class. Thus,
3104 // the low byte is for type info, and the rest of a pointer
3105 // (32 or 64-bit) is for payload, whatever the tagged class.
3107 // Note that the specific integers used to identify the
3108 // specific tagged classes can and will change from release
3109 // to release (that's why this stuff is in CF*Internal*.h),
3110 // as can the definition of type info vs payload above.
3113 #define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1)
3114 #define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF)
3116 #define CF_IS_TAGGED_OBJ(PTR) 0
3117 #define CF_TAGGED_OBJ_TYPE(PTR) 0
3121 kCFTaggedObjectID_Invalid = 0,
3122 kCFTaggedObjectID_Atom = (0 << 1) + 1,
3123 kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
3124 kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
3125 kCFTaggedObjectID_Integer = (3 << 1) + 1,
3126 kCFTaggedObjectID_DateTS = (4 << 1) + 1,
3127 kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data
3128 kCFTaggedObjectID_Date = (6 << 1) + 1,
3129 kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
3133 func (c
*typeConv
) badJNI(dt
*dwarf
.TypedefType
) bool {
3134 // In Dalvik and ART, the jobject type in the JNI interface of the JVM has the
3135 // property that it is sometimes (always?) a small integer instead of a real pointer.
3136 // Note: although only the android JVMs are bad in this respect, we declare the JNI types
3137 // bad regardless of platform, so the same Go code compiles on both android and non-android.
3138 if parent
, ok
:= jniTypes
[dt
.Name
]; ok
{
3139 // Try to make sure we're talking about a JNI type, not just some random user's
3140 // type that happens to use the same name.
3141 // C doesn't have the notion of a package, so it's hard to be certain.
3143 // Walk up to jobject, checking each typedef on the way.
3146 t
, ok
:= w
.Type
.(*dwarf
.TypedefType
)
3147 if !ok || t
.Name
!= parent
{
3151 parent
, ok
= jniTypes
[w
.Name
]
3157 // Check that the typedef is either:
3160 // typedef struct _jobject *jobject;
3161 // 2: (in NDK16 in C++)
3162 // class _jobject {};
3163 // typedef _jobject* jobject;
3164 // 3: (in NDK16 in C)
3165 // typedef void* jobject;
3166 if ptr
, ok
:= w
.Type
.(*dwarf
.PtrType
); ok
{
3167 switch v
:= ptr
.Type
.(type) {
3168 case *dwarf
.VoidType
:
3170 case *dwarf
.StructType
:
3171 if v
.StructName
== "_jobject" && len(v
.Field
) == 0 {
3189 func (c
*typeConv
) badEGLDisplay(dt
*dwarf
.TypedefType
) bool {
3190 if dt
.Name
!= "EGLDisplay" {
3193 // Check that the typedef is "typedef void *EGLDisplay".
3194 if ptr
, ok
:= dt
.Type
.(*dwarf
.PtrType
); ok
{
3195 if _
, ok
:= ptr
.Type
.(*dwarf
.VoidType
); ok
{
3202 // jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which
3203 // they are mapped. The base "jobject" maps to the empty string.
3204 var jniTypes
= map[string]string{
3206 "jclass": "jobject",
3207 "jthrowable": "jobject",
3208 "jstring": "jobject",
3209 "jarray": "jobject",
3210 "jbooleanArray": "jarray",
3211 "jbyteArray": "jarray",
3212 "jcharArray": "jarray",
3213 "jshortArray": "jarray",
3214 "jintArray": "jarray",
3215 "jlongArray": "jarray",
3216 "jfloatArray": "jarray",
3217 "jdoubleArray": "jarray",
3218 "jobjectArray": "jarray",