gcc.go 87.1 KB
Newer Older
1
// Copyright 2009 The Go Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

Russ Cox's avatar
Russ Cox committed
5
// Annotate Ref in Prog with C types by parsing gcc debug output.
Russ Cox's avatar
Russ Cox committed
6
// Conversion of debug output to Go types.
7 8 9 10

package main

import (
11 12 13 14
	"bytes"
	"debug/dwarf"
	"debug/elf"
	"debug/macho"
15
	"debug/pe"
16
	"encoding/binary"
17
	"errors"
Russ Cox's avatar
Russ Cox committed
18
	"flag"
19 20
	"fmt"
	"go/ast"
21
	"go/parser"
22
	"go/token"
23
	"internal/xcoff"
24
	"math"
25 26 27
	"os"
	"strconv"
	"strings"
28
	"unicode"
29
	"unicode/utf8"
30 31
)

Russ Cox's avatar
Russ Cox committed
32 33 34 35
var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")

var nameToC = map[string]string{
36 37 38 39 40 41 42
	"schar":         "signed char",
	"uchar":         "unsigned char",
	"ushort":        "unsigned short",
	"uint":          "unsigned int",
	"ulong":         "unsigned long",
	"longlong":      "long long",
	"ulonglong":     "unsigned long long",
43 44
	"complexfloat":  "float _Complex",
	"complexdouble": "double _Complex",
Russ Cox's avatar
Russ Cox committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
}

// cname returns the C name to use for C.s.
// The expansions are listed in nameToC and also
// struct_foo becomes "struct foo", and similarly for
// union and enum.
func cname(s string) string {
	if t, ok := nameToC[s]; ok {
		return t
	}

	if strings.HasPrefix(s, "struct_") {
		return "struct " + s[len("struct_"):]
	}
	if strings.HasPrefix(s, "union_") {
		return "union " + s[len("union_"):]
	}
	if strings.HasPrefix(s, "enum_") {
		return "enum " + s[len("enum_"):]
	}
65 66 67
	if strings.HasPrefix(s, "sizeof_") {
		return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
	}
Russ Cox's avatar
Russ Cox committed
68 69 70
	return s
}

71 72 73 74
// DiscardCgoDirectives processes the import C preamble, and discards
// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
// way into _cgo_export.h.
func (f *File) DiscardCgoDirectives() {
75
	linesIn := strings.Split(f.Preamble, "\n")
76 77 78
	linesOut := make([]string, 0, len(linesIn))
	for _, line := range linesIn {
		l := strings.TrimSpace(line)
79
		if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
80
			linesOut = append(linesOut, line)
81 82
		} else {
			linesOut = append(linesOut, "")
83 84 85 86 87
		}
	}
	f.Preamble = strings.Join(linesOut, "\n")
}

88
// addToFlag appends args to flag. All flags are later written out onto the
89 90
// _cgo_flags file for the build system to use.
func (p *Package) addToFlag(flag string, args []string) {
91
	p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
92 93
	if flag == "CFLAGS" {
		// We'll also need these when preprocessing for dwarf information.
94 95 96 97 98 99 100
		// However, discard any -g options: we need to be able
		// to parse the debug info, so stick to what we expect.
		for _, arg := range args {
			if !strings.HasPrefix(arg, "-g") {
				p.GccOptions = append(p.GccOptions, arg)
			}
		}
101 102 103
	}
}

104 105 106 107 108 109
// splitQuoted splits the string s around each instance of one or more consecutive
// white space characters while taking into account quotes and escaping, and
// returns an array of substrings of s or an empty list if s contains only white space.
// Single quotes and double quotes are recognized to prevent splitting within the
// quoted region, and are removed from the resulting substrings. If a quote in s
// isn't closed err will be set and r will have the unclosed argument as the
110
// last element. The backslash is used for escaping.
111 112 113 114 115 116 117 118 119
//
// For example, the following string:
//
//     `a b:"c d" 'e''f'  "g\""`
//
// Would be parsed as:
//
//     []string{"a", "b:c d", "ef", `g"`}
//
120
func splitQuoted(s string) (r []string, err error) {
121
	var args []string
122
	arg := make([]rune, len(s))
123 124
	escaped := false
	quoted := false
125
	quote := '\x00'
126
	i := 0
127
	for _, r := range s {
128 129 130
		switch {
		case escaped:
			escaped = false
131
		case r == '\\':
132 133 134
			escaped = true
			continue
		case quote != 0:
135
			if r == quote {
136 137 138
				quote = 0
				continue
			}
139
		case r == '"' || r == '\'':
140
			quoted = true
141
			quote = r
142
			continue
143
		case unicode.IsSpace(r):
144 145 146 147 148 149 150
			if quoted || i > 0 {
				quoted = false
				args = append(args, string(arg[:i]))
				i = 0
			}
			continue
		}
151
		arg[i] = r
152 153 154 155 156 157
		i++
	}
	if quoted || i > 0 {
		args = append(args, string(arg[:i]))
	}
	if quote != 0 {
158
		err = errors.New("unclosed quote")
159
	} else if escaped {
160
		err = errors.New("unfinished escaping")
161 162 163 164
	}
	return args, err
}

Russ Cox's avatar
Russ Cox committed
165 166 167 168 169 170 171 172
// Translate rewrites f.AST, the original Go input, to remove
// references to the imported package C, replacing them with
// references to the equivalent Go types, functions, and variables.
func (p *Package) Translate(f *File) {
	for _, cref := range f.Ref {
		// Convert C.ulong to C.unsigned long, etc.
		cref.Name.C = cname(cref.Name.Go)
	}
173 174 175 176

	var conv typeConv
	conv.Init(p.PtrSize, p.IntSize)

Russ Cox's avatar
Russ Cox committed
177
	p.loadDefines(f)
178 179 180 181 182 183
	p.typedefs = map[string]bool{}
	p.typedefList = nil
	numTypedefs := -1
	for len(p.typedefs) > numTypedefs {
		numTypedefs = len(p.typedefs)
		// Also ask about any typedefs we've seen so far.
184 185 186 187
		for _, info := range p.typedefList {
			n := &Name{
				Go: info.typedef,
				C:  info.typedef,
188
			}
189 190
			f.Name[info.typedef] = n
			f.NamePos[n] = info.pos
191
		}
192 193
		needType := p.guessKinds(f)
		if len(needType) > 0 {
194
			p.loadDWARF(f, &conv, needType)
195
		}
196 197 198 199 200 201 202

		// In godefs mode we're OK with the typedefs, which
		// will presumably also be defined in the file, we
		// don't want to resolve them to their base types.
		if *godefs {
			break
		}
Russ Cox's avatar
Russ Cox committed
203
	}
204
	p.prepareNames(f)
205
	if p.rewriteCalls(f) {
206 207
		// Add `import _cgo_unsafe "unsafe"` after the package statement.
		f.Edit.Insert(f.offset(f.AST.Name.End()), "; import _cgo_unsafe \"unsafe\"")
208
	}
Russ Cox's avatar
Russ Cox committed
209 210 211 212 213 214
	p.rewriteRef(f)
}

// loadDefines coerces gcc into spitting out the #defines in use
// in the file f and saves relevant renamings in f.Name[name].Define.
func (p *Package) loadDefines(f *File) {
215
	var b bytes.Buffer
216
	b.WriteString(builtinProlog)
217
	b.WriteString(f.Preamble)
Russ Cox's avatar
Russ Cox committed
218
	stdout := p.gccDefines(b.Bytes())
219

220
	for _, line := range strings.Split(stdout, "\n") {
221 222 223 224 225 226 227
		if len(line) < 9 || line[0:7] != "#define" {
			continue
		}

		line = strings.TrimSpace(line[8:])

		var key, val string
228
		spaceIndex := strings.Index(line, " ")
229 230 231 232 233 234 235 236 237 238 239 240
		tabIndex := strings.Index(line, "\t")

		if spaceIndex == -1 && tabIndex == -1 {
			continue
		} else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
			key = line[0:spaceIndex]
			val = strings.TrimSpace(line[spaceIndex:])
		} else {
			key = line[0:tabIndex]
			val = strings.TrimSpace(line[tabIndex:])
		}

241 242 243 244
		if key == "__clang__" {
			p.GccIsClang = true
		}

Russ Cox's avatar
Russ Cox committed
245 246 247
		if n := f.Name[key]; n != nil {
			if *debugDefine {
				fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
248
			}
Russ Cox's avatar
Russ Cox committed
249
			n.Define = val
250
		}
251
	}
Russ Cox's avatar
Russ Cox committed
252
}
253

Russ Cox's avatar
Russ Cox committed
254 255 256 257
// guessKinds tricks gcc into revealing the kind of each
// name xxx for the references C.xxx in the Go input.
// The kind is either a constant, type, or variable.
func (p *Package) guessKinds(f *File) []*Name {
258 259 260
	// Determine kinds for names we already know about,
	// like #defines or 'struct foo', before bothering with gcc.
	var names, needType []*Name
261
	optional := map[*Name]bool{}
262 263
	for _, key := range nameKeys(f.Name) {
		n := f.Name[key]
Russ Cox's avatar
Russ Cox committed
264 265 266
		// If we've already found this name as a #define
		// and we can translate it as a constant value, do so.
		if n.Define != "" {
267 268
			if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
				n.Kind = "iconst"
269
				// Turn decimal into hex, just for consistency
270
				// with enum-derived constants. Otherwise
271 272
				// in the cgo -godefs output half the constants
				// are in hex and half are in whatever the #define used.
273 274 275 276 277 278 279 280 281
				n.Const = fmt.Sprintf("%#x", i)
			} else if n.Define[0] == '\'' {
				if _, err := parser.ParseExpr(n.Define); err == nil {
					n.Kind = "iconst"
					n.Const = n.Define
				}
			} else if n.Define[0] == '"' {
				if _, err := parser.ParseExpr(n.Define); err == nil {
					n.Kind = "sconst"
282 283
					n.Const = n.Define
				}
284 285 286
			}

			if n.IsConst() {
Russ Cox's avatar
Russ Cox committed
287 288 289 290
				continue
			}
		}

291
		// If this is a struct, union, or enum type name, no need to guess the kind.
Russ Cox's avatar
Russ Cox committed
292 293
		if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
			n.Kind = "type"
294
			needType = append(needType, n)
Russ Cox's avatar
Russ Cox committed
295 296 297
			continue
		}

298 299 300 301 302 303 304 305
		if goos == "darwin" && strings.HasSuffix(n.C, "Ref") {
			// For FooRef, find out if FooGetTypeID exists.
			s := n.C[:len(n.C)-3] + "GetTypeID"
			n := &Name{Go: s, C: s}
			names = append(names, n)
			optional[n] = true
		}

306 307
		// Otherwise, we'll need to find out from gcc.
		names = append(names, n)
Russ Cox's avatar
Russ Cox committed
308 309
	}

310 311
	// Bypass gcc if there's nothing left to find out.
	if len(names) == 0 {
Russ Cox's avatar
Russ Cox committed
312 313 314
		return needType
	}

315 316 317 318 319 320 321 322 323 324
	// Coerce gcc into telling us whether each name is a type, a value, or undeclared.
	// For names, find out whether they are integer constants.
	// We used to look at specific warning or error messages here, but that tied the
	// behavior too closely to specific versions of the compilers.
	// Instead, arrange that we can infer what we need from only the presence or absence
	// of an error on a specific line.
	//
	// For each name, we generate these lines, where xxx is the index in toSniff plus one.
	//
	//	#line xxx "not-declared"
325
	//	void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__1; }
326
	//	#line xxx "not-type"
327
	//	void __cgo_f_xxx_2(void) { name *__cgo_undefined__2; }
328
	//	#line xxx "not-int-const"
329
	//	void __cgo_f_xxx_3(void) { enum { __cgo_undefined__3 = (name)*1 }; }
330
	//	#line xxx "not-num-const"
331
	//	void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
332
	//	#line xxx "not-str-lit"
333
	//	void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
334 335 336
	//
	// If we see an error at not-declared:xxx, the corresponding name is not declared.
	// If we see an error at not-type:xxx, the corresponding name is a type.
337 338 339
	// If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
	// If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
	// If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
340 341 342 343
	//
	// The specific input forms are chosen so that they are valid C syntax regardless of
	// whether name denotes a type or an expression.

Russ Cox's avatar
Russ Cox committed
344
	var b bytes.Buffer
345
	b.WriteString(builtinProlog)
346
	b.WriteString(f.Preamble)
347 348 349

	for i, n := range names {
		fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
350
			"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__1; }\n"+
351
			"#line %d \"not-type\"\n"+
352
			"void __cgo_f_%d_2(void) { %s *__cgo_undefined__2; }\n"+
353
			"#line %d \"not-int-const\"\n"+
354
			"void __cgo_f_%d_3(void) { enum { __cgo_undefined__3 = (%s)*1 }; }\n"+
355
			"#line %d \"not-num-const\"\n"+
356
			"void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
357
			"#line %d \"not-str-lit\"\n"+
358
			"void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
359 360
			i+1, i+1, n.C,
			i+1, i+1, n.C,
361 362
			i+1, i+1, n.C,
			i+1, i+1, n.C,
363 364
			i+1, i+1, n.C,
		)
365 366 367 368
	}
	fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
		"int __cgo__1 = __cgo__2;\n")

Russ Cox's avatar
Russ Cox committed
369
	stderr := p.gccErrors(b.Bytes())
370
	if stderr == "" {
371
		fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
Russ Cox's avatar
Russ Cox committed
372 373
	}

374 375 376 377
	completed := false
	sniff := make([]int, len(names))
	const (
		notType = 1 << iota
378 379 380
		notIntConst
		notNumConst
		notStrLiteral
381
		notDeclared
382
	)
383
	sawUnmatchedErrors := false
384
	for _, line := range strings.Split(stderr, "\n") {
385 386 387 388 389 390 391 392 393
		// Ignore warnings and random comments, with one
		// exception: newer GCC versions will sometimes emit
		// an error on a macro #define with a note referring
		// to where the expansion occurs. We care about where
		// the expansion occurs, so in that case treat the note
		// as an error.
		isError := strings.Contains(line, ": error:")
		isErrorNote := strings.Contains(line, ": note:") && sawUnmatchedErrors
		if !isError && !isErrorNote {
394
			continue
395
		}
396

397
		c1 := strings.Index(line, ":")
398
		if c1 < 0 {
399
			continue
400
		}
401
		c2 := strings.Index(line[c1+1:], ":")
402
		if c2 < 0 {
Russ Cox's avatar
Russ Cox committed
403
			continue
404
		}
405 406 407 408 409 410
		c2 += c1 + 1

		filename := line[:c1]
		i, _ := strconv.Atoi(line[c1+1 : c2])
		i--
		if i < 0 || i >= len(names) {
411 412 413
			if isError {
				sawUnmatchedErrors = true
			}
Russ Cox's avatar
Russ Cox committed
414
			continue
415
		}
Russ Cox's avatar
Russ Cox committed
416

417 418 419 420 421 422 423 424 425
		switch filename {
		case "completed":
			// Strictly speaking, there is no guarantee that seeing the error at completed:1
			// (at the end of the file) means we've seen all the errors from earlier in the file,
			// but usually it does. Certainly if we don't see the completed:1 error, we did
			// not get all the errors we expected.
			completed = true

		case "not-declared":
426
			sniff[i] |= notDeclared
427 428
		case "not-type":
			sniff[i] |= notType
429 430 431 432 433 434
		case "not-int-const":
			sniff[i] |= notIntConst
		case "not-num-const":
			sniff[i] |= notNumConst
		case "not-str-lit":
			sniff[i] |= notStrLiteral
435 436 437 438 439
		default:
			if isError {
				sawUnmatchedErrors = true
			}
			continue
440
		}
441 442

		sawUnmatchedErrors = false
443
	}
444 445

	if !completed {
446
		fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr)
447 448 449
	}

	for i, n := range names {
450
		switch sniff[i] {
451
		default:
452 453 454 455 456
			if sniff[i]&notDeclared != 0 && optional[n] {
				// Ignore optional undeclared identifiers.
				// Don't report an error, and skip adding n to the needType array.
				continue
			}
457
			error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
458
		case notStrLiteral | notType:
459
			n.Kind = "iconst"
460 461 462 463 464
		case notIntConst | notStrLiteral | notType:
			n.Kind = "fconst"
		case notIntConst | notNumConst | notType:
			n.Kind = "sconst"
		case notIntConst | notNumConst | notStrLiteral:
465
			n.Kind = "type"
466
		case notIntConst | notNumConst | notStrLiteral | notType:
467
			n.Kind = "not-type"
Russ Cox's avatar
Russ Cox committed
468
		}
469
		needType = append(needType, n)
Russ Cox's avatar
Russ Cox committed
470
	}
471
	if nerrors > 0 {
472 473
		// Check if compiling the preamble by itself causes any errors,
		// because the messages we've printed out so far aren't helpful
474
		// to users debugging preamble mistakes. See issue 8442.
475 476 477 478 479
		preambleErrors := p.gccErrors([]byte(f.Preamble))
		if len(preambleErrors) > 0 {
			error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
		}

480
		fatalf("unresolved names")
481
	}
482

Russ Cox's avatar
Russ Cox committed
483 484
	return needType
}
485

Russ Cox's avatar
Russ Cox committed
486 487 488
// loadDWARF parses the DWARF debug information generated
// by gcc to learn the details of the constants, variables, and types
// being referred to as C.xxx.
489
func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
490
	// Extract the types from the DWARF section of an object
491
	// from a well-formed C program. Gcc only generates DWARF info
492 493 494
	// for symbols in the object file, so it is not enough to print the
	// preamble and hope the symbols we care about will be there.
	// Instead, emit
495
	//	__typeof__(names[i]) *__cgo__i;
496 497
	// for each entry in names and then dereference the type we
	// learn for __cgo__i.
Russ Cox's avatar
Russ Cox committed
498
	var b bytes.Buffer
499
	b.WriteString(builtinProlog)
500
	b.WriteString(f.Preamble)
501
	b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
502
	for i, n := range names {
503
		fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
504
		if n.Kind == "iconst" {
Russ Cox's avatar
Russ Cox committed
505 506
			fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
		}
507
	}
508

509 510
	// We create a data block initialized with the values,
	// so we can read them out of the object file.
511
	fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
512
	for _, n := range names {
513
		if n.Kind == "iconst" {
514 515 516 517 518
			fmt.Fprintf(&b, "\t%s,\n", n.C)
		} else {
			fmt.Fprintf(&b, "\t0,\n")
		}
	}
519
	// for the last entry, we cannot use 0, otherwise
520 521 522 523 524
	// in case all __cgodebug_data is zero initialized,
	// LLVM-based gcc will place the it in the __DATA.__common
	// zero-filled section (our debug/macho doesn't support
	// this)
	fmt.Fprintf(&b, "\t1\n")
525 526
	fmt.Fprintf(&b, "};\n")

527 528 529 530 531 532 533 534
	// do the same work for floats.
	fmt.Fprintf(&b, "double __cgodebug_floats[] = {\n")
	for _, n := range names {
		if n.Kind == "fconst" {
			fmt.Fprintf(&b, "\t%s,\n", n.C)
		} else {
			fmt.Fprintf(&b, "\t0,\n")
		}
535
	}
536 537 538
	fmt.Fprintf(&b, "\t1\n")
	fmt.Fprintf(&b, "};\n")

539 540 541 542 543 544 545 546 547
	// do the same work for strings.
	for i, n := range names {
		if n.Kind == "sconst" {
			fmt.Fprintf(&b, "const char __cgodebug_str__%d[] = %s;\n", i, n.C)
			fmt.Fprintf(&b, "const unsigned long long __cgodebug_strlen__%d = sizeof(%s)-1;\n", i, n.C)
		}
	}

	d, ints, floats, strs := p.gccDebug(b.Bytes(), len(names))
548

Adam Langley's avatar
Adam Langley committed
549
	// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
550 551
	types := make([]dwarf.Type, len(names))
	r := d.Reader()
552
	for {
553
		e, err := r.Next()
554
		if err != nil {
555
			fatalf("reading DWARF entry: %s", err)
556 557
		}
		if e == nil {
558
			break
559
		}
560 561 562 563 564
		switch e.Tag {
		case dwarf.TagVariable:
			name, _ := e.Val(dwarf.AttrName).(string)
			typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
			if name == "" || typOff == 0 {
565 566 567 568 569
				if e.Val(dwarf.AttrSpecification) != nil {
					// Since we are reading all the DWARF,
					// assume we will see the variable elsewhere.
					break
				}
570
				fatalf("malformed DWARF TagVariable entry")
571 572 573 574 575 576
			}
			if !strings.HasPrefix(name, "__cgo__") {
				break
			}
			typ, err := d.Type(typOff)
			if err != nil {
577
				fatalf("loading DWARF type: %s", err)
578 579 580
			}
			t, ok := typ.(*dwarf.PtrType)
			if !ok || t == nil {
581
				fatalf("internal error: %s has non-pointer type", name)
582 583 584
			}
			i, err := strconv.Atoi(name[7:])
			if err != nil {
585
				fatalf("malformed __cgo__ name: %s", name)
586
			}
587
			types[i] = t.Type
588
			p.recordTypedefs(t.Type, f.NamePos[names[i]])
589 590
		}
		if e.Tag != dwarf.TagCompileUnit {
591
			r.SkipChildren()
592 593 594
		}
	}

Russ Cox's avatar
Russ Cox committed
595
	// Record types and typedef information.
596 597 598 599 600
	for i, n := range names {
		if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
			conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true
		}
	}
Russ Cox's avatar
Russ Cox committed
601
	for i, n := range names {
602 603 604
		if types[i] == nil {
			continue
		}
605
		pos := f.NamePos[n]
606
		f, fok := types[i].(*dwarf.FuncType)
Russ Cox's avatar
Russ Cox committed
607 608
		if n.Kind != "type" && fok {
			n.Kind = "func"
609
			n.FuncType = conv.FuncType(f, pos)
Russ Cox's avatar
Russ Cox committed
610
		} else {
611
			n.Type = conv.Type(types[i], pos)
612 613 614
			switch n.Kind {
			case "iconst":
				if i < len(ints) {
615 616 617 618 619
					if _, ok := types[i].(*dwarf.UintType); ok {
						n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
					} else {
						n.Const = fmt.Sprintf("%#x", ints[i])
					}
620
				}
621
			case "fconst":
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
				if i >= len(floats) {
					break
				}
				switch base(types[i]).(type) {
				case *dwarf.IntType, *dwarf.UintType:
					// This has an integer type so it's
					// not really a floating point
					// constant. This can happen when the
					// C compiler complains about using
					// the value as an integer constant,
					// but not as a general constant.
					// Treat this as a variable of the
					// appropriate type, not a constant,
					// to get C-style type handling,
					// avoiding the problem that C permits
					// uint64(-1) but Go does not.
					// See issue 26066.
					n.Kind = "var"
				default:
641 642
					n.Const = fmt.Sprintf("%f", floats[i])
				}
643 644 645 646
			case "sconst":
				if i < len(strs) {
					n.Const = fmt.Sprintf("%q", strs[i])
				}
647
			}
Russ Cox's avatar
Russ Cox committed
648
		}
649
		conv.FinishType(pos)
650
	}
651 652 653
}

// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
654 655
func (p *Package) recordTypedefs(dtype dwarf.Type, pos token.Pos) {
	p.recordTypedefs1(dtype, pos, map[dwarf.Type]bool{})
656
}
657 658

func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) {
659 660 661 662 663 664 665 666 667
	if dtype == nil {
		return
	}
	if visited[dtype] {
		return
	}
	visited[dtype] = true
	switch dt := dtype.(type) {
	case *dwarf.TypedefType:
668 669 670 671
		if strings.HasPrefix(dt.Name, "__builtin") {
			// Don't look inside builtin types. There be dragons.
			return
		}
672 673
		if !p.typedefs[dt.Name] {
			p.typedefs[dt.Name] = true
674 675
			p.typedefList = append(p.typedefList, typedefInfo{dt.Name, pos})
			p.recordTypedefs1(dt.Type, pos, visited)
676 677
		}
	case *dwarf.PtrType:
678
		p.recordTypedefs1(dt.Type, pos, visited)
679
	case *dwarf.ArrayType:
680
		p.recordTypedefs1(dt.Type, pos, visited)
681
	case *dwarf.QualType:
682
		p.recordTypedefs1(dt.Type, pos, visited)
683
	case *dwarf.FuncType:
684
		p.recordTypedefs1(dt.ReturnType, pos, visited)
685
		for _, a := range dt.ParamType {
686
			p.recordTypedefs1(a, pos, visited)
687 688 689
		}
	case *dwarf.StructType:
		for _, f := range dt.Field {
690
			p.recordTypedefs1(f.Type, pos, visited)
691 692
		}
	}
693 694
}

695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
// prepareNames finalizes the Kind field of not-type names and sets
// the mangled name of all names.
func (p *Package) prepareNames(f *File) {
	for _, n := range f.Name {
		if n.Kind == "not-type" {
			if n.Define == "" {
				n.Kind = "var"
			} else {
				n.Kind = "macro"
				n.FuncType = &FuncType{
					Result: n.Type,
					Go: &ast.FuncType{
						Results: &ast.FieldList{List: []*ast.Field{{Type: n.Type.Go}}},
					},
				}
			}
		}
		p.mangleName(n)
	}
}

716 717 718 719 720 721 722 723 724 725 726 727 728 729
// mangleName does name mangling to translate names
// from the original Go source files to the names
// used in the final Go files generated by cgo.
func (p *Package) mangleName(n *Name) {
	// When using gccgo variables have to be
	// exported so that they become global symbols
	// that the C code can refer to.
	prefix := "_C"
	if *gccgo && n.IsVar() {
		prefix = "C"
	}
	n.Mangle = prefix + n.Kind + "_" + n.Go
}

730 731 732 733 734 735 736 737 738 739 740 741 742
func (f *File) isMangledName(s string) bool {
	prefix := "_C"
	if strings.HasPrefix(s, prefix) {
		t := s[len(prefix):]
		for _, k := range nameKinds {
			if strings.HasPrefix(t, k+"_") {
				return true
			}
		}
	}
	return false
}

743 744
// rewriteCalls rewrites all calls that pass pointers to check that
// they follow the rules for passing pointers between Go and C.
745
// This reports whether the package needs to import unsafe as _cgo_unsafe.
746 747
func (p *Package) rewriteCalls(f *File) bool {
	needsUnsafe := false
748
	// Walk backward so that in C.f1(C.f2()) we rewrite C.f2 first.
749 750
	for _, call := range f.Calls {
		if call.Done {
751 752
			continue
		}
753 754 755 756 757 758 759 760
		start := f.offset(call.Call.Pos())
		end := f.offset(call.Call.End())
		str, nu := p.rewriteCall(f, call)
		if str != "" {
			f.Edit.Replace(start, end, str)
			if nu {
				needsUnsafe = true
			}
761
		}
762
	}
763
	return needsUnsafe
764 765
}

766 767 768 769
// rewriteCall rewrites one call to add pointer checks.
// If any pointer checks are required, we rewrite the call into a
// function literal that calls _cgoCheckPointer for each pointer
// argument and then calls the original function.
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
// This returns the rewritten call and whether the package needs to
// import unsafe as _cgo_unsafe.
// If it returns the empty string, the call did not need to be rewritten.
func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
	// This is a call to C.xxx; set goname to "xxx".
	// It may have already been mangled by rewriteName.
	var goname string
	switch fun := call.Call.Fun.(type) {
	case *ast.SelectorExpr:
		goname = fun.Sel.Name
	case *ast.Ident:
		goname = strings.TrimPrefix(fun.Name, "_C2func_")
		goname = strings.TrimPrefix(goname, "_Cfunc_")
	}
	if goname == "" || goname == "malloc" {
		return "", false
	}
	name := f.Name[goname]
	if name == nil || name.Kind != "func" {
		// Probably a type conversion.
		return "", false
	}

793 794 795
	params := name.FuncType.Params
	args := call.Call.Args

796 797 798
	// Avoid a crash if the number of arguments is
	// less than the number of parameters.
	// This will be caught when the generated file is compiled.
799
	if len(args) < len(params) {
800
		return "", false
801 802
	}

803
	any := false
804 805
	for i, param := range params {
		if p.needsPointerCheck(f, param.Go, args[i]) {
806 807 808 809 810
			any = true
			break
		}
	}
	if !any {
811
		return "", false
812
	}
813

814 815
	// We need to rewrite this call.
	//
816 817 818
	// Rewrite C.f(p) to
	//    func() {
	//            _cgo0 := p
819 820
	//            _cgoCheckPointer(_cgo0)
	//            C.f(_cgo0)
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
	//    }()
	// Using a function literal like this lets us evaluate the
	// function arguments only once while doing pointer checks.
	// This is particularly useful when passing additional arguments
	// to _cgoCheckPointer, as done in checkIndex and checkAddr.
	//
	// When the function argument is a conversion to unsafe.Pointer,
	// we unwrap the conversion before checking the pointer,
	// and then wrap again when calling C.f. This lets us check
	// the real type of the pointer in some cases. See issue #25941.
	//
	// When the call to C.f is deferred, we use an additional function
	// literal to evaluate the arguments at the right time.
	//    defer func() func() {
	//            _cgo0 := p
	//            return func() {
	//                    _cgoCheckPointer(_cgo0)
	//                    C.f(_cgo0)
	//            }
	//    }()()
	// This works because the defer statement evaluates the first
	// function literal in order to get the function to call.
843

844 845 846 847
	var sb bytes.Buffer
	sb.WriteString("func() ")
	if call.Deferred {
		sb.WriteString("func() ")
848
	}
849

850
	needsUnsafe := false
851 852
	result := false
	twoResults := false
853 854 855 856 857 858 859 860 861 862 863 864
	if !call.Deferred {
		// Check whether this call expects two results.
		for _, ref := range f.Ref {
			if ref.Expr != &call.Call.Fun {
				continue
			}
			if ref.Context == ctxCall2 {
				sb.WriteString("(")
				result = true
				twoResults = true
			}
			break
865
		}
866

867 868 869 870 871 872 873 874
		// Add the result type, if any.
		if name.FuncType.Result != nil {
			rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
			if rtype != name.FuncType.Result.Go {
				needsUnsafe = true
			}
			sb.WriteString(gofmtLine(rtype))
			result = true
875 876
		}

877 878 879 880 881 882 883 884
		// Add the second result type, if any.
		if twoResults {
			if name.FuncType.Result == nil {
				// An explicit void result looks odd but it
				// seems to be how cgo has worked historically.
				sb.WriteString("_Ctype_void")
			}
			sb.WriteString(", error)")
885
		}
886
	}
887

888
	sb.WriteString("{ ")
889

890 891 892
	// Define _cgoN for each argument value.
	// Write _cgoCheckPointer calls to sbCheck.
	var sbCheck bytes.Buffer
893
	for i, param := range params {
894
		origArg := args[i]
895 896 897 898
		arg, nu := p.mangle(f, &args[i])
		if nu {
			needsUnsafe = true
		}
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913

		// Explicitly convert untyped constants to the
		// parameter type, to avoid a type mismatch.
		if p.isConst(f, arg) {
			ptype := p.rewriteUnsafe(param.Go)
			if ptype != param.Go {
				needsUnsafe = true
			}
			arg = &ast.CallExpr{
				Fun:  ptype,
				Args: []ast.Expr{arg},
			}
		}

		if !p.needsPointerCheck(f, param.Go, args[i]) {
914
			fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
915
			continue
916
		}
917 918

		// Check for &a[i].
919
		if p.checkIndex(&sb, &sbCheck, arg, i) {
920
			continue
921
		}
922 923

		// Check for &x.
924
		if p.checkAddr(&sb, &sbCheck, arg, i) {
925 926 927
			continue
		}

928
		fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
929 930 931 932 933
		fmt.Fprintf(&sbCheck, "_cgoCheckPointer(_cgo%d); ", i)
	}

	if call.Deferred {
		sb.WriteString("return func() { ")
934
	}
935

936 937 938
	// Write out the calls to _cgoCheckPointer.
	sb.WriteString(sbCheck.String())

939 940 941 942
	if result {
		sb.WriteString("return ")
	}

943 944 945 946 947
	m, nu := p.mangle(f, &call.Call.Fun)
	if nu {
		needsUnsafe = true
	}
	sb.WriteString(gofmtLine(m))
948 949 950 951 952 953 954

	sb.WriteString("(")
	for i := range params {
		if i > 0 {
			sb.WriteString(", ")
		}
		fmt.Fprintf(&sb, "_cgo%d", i)
955
	}
956 957 958 959 960 961 962 963 964
	sb.WriteString("); ")
	if call.Deferred {
		sb.WriteString("}")
	}
	sb.WriteString("}")
	if call.Deferred {
		sb.WriteString("()")
	}
	sb.WriteString("()")
965

966
	return sb.String(), needsUnsafe
967 968
}

969
// needsPointerCheck reports whether the type t needs a pointer check.
970 971
// This is true if t is a pointer and if the value to which it points
// might contain a pointer.
972 973 974 975 976 977 978 979 980
func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
	// An untyped nil does not need a pointer check, and when
	// _cgoCheckPointer returns the untyped nil the type assertion we
	// are going to insert will fail.  Easier to just skip nil arguments.
	// TODO: Note that this fails if nil is shadowed.
	if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
		return false
	}

981 982 983
	return p.hasPointer(f, t, true)
}

984
// hasPointer is used by needsPointerCheck. If top is true it returns
985
// whether t is or contains a pointer that might point to a pointer.
986
// If top is false it reports whether t is or contains a pointer.
987
// f may be nil.
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
	switch t := t.(type) {
	case *ast.ArrayType:
		if t.Len == nil {
			if !top {
				return true
			}
			return p.hasPointer(f, t.Elt, false)
		}
		return p.hasPointer(f, t.Elt, top)
	case *ast.StructType:
		for _, field := range t.Fields.List {
			if p.hasPointer(f, field.Type, top) {
				return true
			}
		}
		return false
	case *ast.StarExpr: // Pointer type.
		if !top {
			return true
		}
1009 1010 1011 1012 1013
		// Check whether this is a pointer to a C union (or class)
		// type that contains a pointer.
		if unionWithPointer[t.X] {
			return true
		}
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
		return p.hasPointer(f, t.X, false)
	case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
		return true
	case *ast.Ident:
		// TODO: Handle types defined within function.
		for _, d := range p.Decl {
			gd, ok := d.(*ast.GenDecl)
			if !ok || gd.Tok != token.TYPE {
				continue
			}
			for _, spec := range gd.Specs {
				ts, ok := spec.(*ast.TypeSpec)
				if !ok {
					continue
				}
				if ts.Name.Name == t.Name {
					return p.hasPointer(f, ts.Type, top)
				}
			}
		}
		if def := typedef[t.Name]; def != nil {
			return p.hasPointer(f, def.Go, top)
		}
		if t.Name == "string" {
			return !top
		}
		if t.Name == "error" {
			return true
		}
		if goTypes[t.Name] != nil {
			return false
		}
1046
		// We can't figure out the type. Conservative
1047 1048 1049 1050 1051 1052 1053 1054 1055
		// approach is to assume it has a pointer.
		return true
	case *ast.SelectorExpr:
		if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
			// Type defined in a different package.
			// Conservative approach is to assume it has a
			// pointer.
			return true
		}
1056 1057 1058 1059
		if f == nil {
			// Conservative approach: assume pointer.
			return true
		}
1060 1061 1062 1063
		name := f.Name[t.Sel.Name]
		if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
			return p.hasPointer(f, name.Type.Go, top)
		}
1064
		// We can't figure out the type. Conservative
1065 1066 1067 1068 1069 1070 1071 1072
		// approach is to assume it has a pointer.
		return true
	default:
		error_(t.Pos(), "could not understand type %s", gofmt(t))
		return true
	}
}

1073 1074 1075 1076 1077 1078
// mangle replaces references to C names in arg with the mangled names,
// rewriting calls when it finds them.
// It removes the corresponding references in f.Ref and f.Calls, so that we
// don't try to do the replacement again in rewriteRef or rewriteCall.
func (p *Package) mangle(f *File, arg *ast.Expr) (ast.Expr, bool) {
	needsUnsafe := false
1079 1080 1081 1082 1083 1084
	f.walk(arg, ctxExpr, func(f *File, arg interface{}, context astContext) {
		px, ok := arg.(*ast.Expr)
		if !ok {
			return
		}
		sel, ok := (*px).(*ast.SelectorExpr)
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
		if ok {
			if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
				return
			}

			for _, r := range f.Ref {
				if r.Expr == px {
					*px = p.rewriteName(f, r)
					r.Done = true
					break
				}
			}

1098 1099
			return
		}
1100 1101 1102

		call, ok := (*px).(*ast.CallExpr)
		if !ok {
1103 1104 1105
			return
		}

1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
		for _, c := range f.Calls {
			if !c.Done && c.Call.Lparen == call.Lparen {
				cstr, nu := p.rewriteCall(f, c)
				if cstr != "" {
					// Smuggle the rewritten call through an ident.
					*px = ast.NewIdent(cstr)
					if nu {
						needsUnsafe = true
					}
					c.Done = true
				}
1117 1118 1119
			}
		}
	})
1120
	return *arg, needsUnsafe
1121 1122
}

1123
// checkIndex checks whether arg has the form &a[i], possibly inside
1124
// type conversions. If so, then in the general case it writes
1125 1126 1127 1128
//    _cgoIndexNN := a
//    _cgoNN := &cgoIndexNN[i] // with type conversions, if any
// to sb, and writes
//    _cgoCheckPointer(_cgoNN, _cgoIndexNN)
1129 1130 1131 1132 1133 1134 1135 1136
// to sbCheck, and returns true. If a is a simple variable or field reference,
// it writes
//    _cgoIndexNN := &a
// and dereferences the uses of _cgoIndexNN. Taking the address avoids
// making a copy of an array.
//
// This tells _cgoCheckPointer to check the complete contents of the
// slice or array being indexed, but no other part of the memory allocation.
1137
func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1138
	// Strip type conversions.
1139
	x := arg
1140 1141 1142 1143 1144 1145 1146 1147 1148
	for {
		c, ok := x.(*ast.CallExpr)
		if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
			break
		}
		x = c.Args[0]
	}
	u, ok := x.(*ast.UnaryExpr)
	if !ok || u.Op != token.AND {
1149
		return false
1150 1151
	}
	index, ok := u.X.(*ast.IndexExpr)
1152
	if !ok {
1153
		return false
1154
	}
1155

1156 1157 1158 1159 1160 1161 1162 1163
	addr := ""
	deref := ""
	if p.isVariable(index.X) {
		addr = "&"
		deref = "*"
	}

	fmt.Fprintf(sb, "_cgoIndex%d := %s%s; ", i, addr, gofmtPos(index.X, index.X.Pos()))
1164 1165
	origX := index.X
	index.X = ast.NewIdent(fmt.Sprintf("_cgoIndex%d", i))
1166 1167 1168
	if deref == "*" {
		index.X = &ast.StarExpr{X: index.X}
	}
1169
	fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1170 1171
	index.X = origX

1172
	fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgo%d, %s_cgoIndex%d); ", i, deref, i)
1173 1174 1175 1176 1177

	return true
}

// checkAddr checks whether arg has the form &x, possibly inside type
1178
// conversions. If so, it writes
1179 1180 1181 1182 1183 1184 1185 1186 1187
//    _cgoBaseNN := &x
//    _cgoNN := _cgoBaseNN // with type conversions, if any
// to sb, and writes
//    _cgoCheckPointer(_cgoBaseNN, true)
// to sbCheck, and returns true. This tells _cgoCheckPointer to check
// just the contents of the pointer being passed, not any other part
// of the memory allocation. This is run after checkIndex, which looks
// for the special case of &a[i], which requires different checks.
func (p *Package) checkAddr(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
	// Strip type conversions.
	px := &arg
	for {
		c, ok := (*px).(*ast.CallExpr)
		if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
			break
		}
		px = &c.Args[0]
	}
	if u, ok := (*px).(*ast.UnaryExpr); !ok || u.Op != token.AND {
		return false
	}

1201
	fmt.Fprintf(sb, "_cgoBase%d := %s; ", i, gofmtPos(*px, (*px).Pos()))
1202 1203 1204

	origX := *px
	*px = ast.NewIdent(fmt.Sprintf("_cgoBase%d", i))
1205
	fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1206 1207
	*px = origX

1208 1209
	// Use "0 == 0" to do the right thing in the unlikely event
	// that "true" is shadowed.
1210
	fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgoBase%d, 0 == 0); ", i)
1211 1212

	return true
1213 1214
}

1215
// isType reports whether the expression is definitely a type.
1216 1217 1218 1219 1220 1221 1222 1223
// This is conservative--it returns false for an unknown identifier.
func (p *Package) isType(t ast.Expr) bool {
	switch t := t.(type) {
	case *ast.SelectorExpr:
		id, ok := t.X.(*ast.Ident)
		if !ok {
			return false
		}
1224 1225 1226 1227 1228 1229 1230
		if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
			return true
		}
		if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
			return true
		}
		return false
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243
	case *ast.Ident:
		// TODO: This ignores shadowing.
		switch t.Name {
		case "unsafe.Pointer", "bool", "byte",
			"complex64", "complex128",
			"error",
			"float32", "float64",
			"int", "int8", "int16", "int32", "int64",
			"rune", "string",
			"uint", "uint8", "uint16", "uint32", "uint64", "uintptr":

			return true
		}
1244 1245 1246
		if strings.HasPrefix(t.Name, "_Ctype_") {
			return true
		}
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
	case *ast.StarExpr:
		return p.isType(t.X)
	case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
		*ast.MapType, *ast.ChanType:

		return true
	}
	return false
}

1257
// isConst reports whether x is an untyped constant expression.
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
func (p *Package) isConst(f *File, x ast.Expr) bool {
	switch x := x.(type) {
	case *ast.BasicLit:
		return true
	case *ast.SelectorExpr:
		id, ok := x.X.(*ast.Ident)
		if !ok || id.Name != "C" {
			return false
		}
		name := f.Name[x.Sel.Name]
		if name != nil {
			return name.IsConst()
		}
	case *ast.Ident:
		return x.Name == "nil" ||
			strings.HasPrefix(x.Name, "_Ciconst_") ||
			strings.HasPrefix(x.Name, "_Cfconst_") ||
1275
			strings.HasPrefix(x.Name, "_Csconst_") ||
1276
			consts[x.Name]
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
	case *ast.UnaryExpr:
		return p.isConst(f, x.X)
	case *ast.BinaryExpr:
		return p.isConst(f, x.X) && p.isConst(f, x.Y)
	case *ast.ParenExpr:
		return p.isConst(f, x.X)
	case *ast.CallExpr:
		// Calling the builtin function complex on two untyped
		// constants returns an untyped constant.
		// TODO: It's possible to construct a case that will
		// erroneously succeed if there is a local function
		// named "complex", shadowing the builtin, that returns
		// a numeric type. I can't think of any cases that will
		// erroneously fail.
		if id, ok := x.Fun.(*ast.Ident); ok && id.Name == "complex" && len(x.Args) == 2 {
			return p.isConst(f, x.Args[0]) && p.isConst(f, x.Args[1])
		}
1294 1295 1296 1297
	}
	return false
}

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
// isVariable reports whether x is a variable, possibly with field references.
func (p *Package) isVariable(x ast.Expr) bool {
	switch x := x.(type) {
	case *ast.Ident:
		return true
	case *ast.SelectorExpr:
		return p.isVariable(x.X)
	}
	return false
}

1309 1310 1311
// rewriteUnsafe returns a version of t with references to unsafe.Pointer
// rewritten to use _cgo_unsafe.Pointer instead.
func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr {
1312 1313
	switch t := t.(type) {
	case *ast.Ident:
1314 1315
		// We don't see a SelectorExpr for unsafe.Pointer;
		// this is created by code in this file.
1316 1317 1318
		if t.Name == "unsafe.Pointer" {
			return ast.NewIdent("_cgo_unsafe.Pointer")
		}
1319
	case *ast.ArrayType:
1320 1321 1322 1323 1324 1325
		t1 := p.rewriteUnsafe(t.Elt)
		if t1 != t.Elt {
			r := *t
			r.Elt = t1
			return &r
		}
1326
	case *ast.StructType:
1327 1328 1329
		changed := false
		fields := *t.Fields
		fields.List = nil
1330
		for _, f := range t.Fields.List {
1331 1332 1333 1334 1335 1336 1337 1338
			ft := p.rewriteUnsafe(f.Type)
			if ft == f.Type {
				fields.List = append(fields.List, f)
			} else {
				fn := *f
				fn.Type = ft
				fields.List = append(fields.List, &fn)
				changed = true
1339 1340
			}
		}
1341 1342 1343 1344 1345
		if changed {
			r := *t
			r.Fields = &fields
			return &r
		}
1346
	case *ast.StarExpr: // Pointer type.
1347 1348 1349 1350 1351 1352
		x1 := p.rewriteUnsafe(t.X)
		if x1 != t.X {
			r := *t
			r.X = x1
			return &r
		}
1353
	}
1354
	return t
1355 1356
}

Russ Cox's avatar
Russ Cox committed
1357 1358
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
// Go equivalents, now that we have figured out the meaning of all
1359
// the xxx. In *godefs mode, rewriteRef replaces the names
1360
// with full definitions instead of mangled names.
Russ Cox's avatar
Russ Cox committed
1361
func (p *Package) rewriteRef(f *File) {
1362 1363 1364 1365 1366
	// Keep a list of all the functions, to remove the ones
	// only used as expressions and avoid generating bridge
	// code for them.
	functions := make(map[string]bool)

Russ Cox's avatar
Russ Cox committed
1367
	for _, n := range f.Name {
1368 1369
		if n.Kind == "func" {
			functions[n.Go] = false
Russ Cox's avatar
Russ Cox committed
1370
		}
Russ Cox's avatar
Russ Cox committed
1371
	}
Russ Cox's avatar
Russ Cox committed
1372 1373 1374

	// Now that we have all the name types filled in,
	// scan through the Refs to identify the ones that
1375
	// are trying to do a ,err call. Also check that
Russ Cox's avatar
Russ Cox committed
1376 1377
	// functions are only used in calls.
	for _, r := range f.Ref {
1378
		if r.Name.IsConst() && r.Name.Const == "" {
1379
			error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
1380
		}
1381

1382 1383 1384 1385
		if r.Name.Kind == "func" {
			switch r.Context {
			case ctxCall, ctxCall2:
				functions[r.Name.Go] = true
Russ Cox's avatar
Russ Cox committed
1386 1387
			}
		}
1388

1389 1390
		expr := p.rewriteName(f, r)

1391
		if *godefs {
1392 1393 1394
			// Substitute definition for mangled type name.
			if id, ok := expr.(*ast.Ident); ok {
				if t := typedef[id.Name]; t != nil {
Russ Cox's avatar
Russ Cox committed
1395
					expr = t.Go
1396 1397 1398 1399 1400 1401
				}
				if id.Name == r.Name.Mangle && r.Name.Const != "" {
					expr = ast.NewIdent(r.Name.Const)
				}
			}
		}
1402 1403 1404 1405 1406

		// Copy position information from old expr into new expr,
		// in case expression being replaced is first on line.
		// See golang.org/issue/6563.
		pos := (*r.Expr).Pos()
1407
		if x, ok := expr.(*ast.Ident); ok {
1408 1409 1410
			expr = &ast.Ident{NamePos: pos, Name: x.Name}
		}

1411 1412 1413
		// Change AST, because some later processing depends on it,
		// and also because -godefs mode still prints the AST.
		old := *r.Expr
Russ Cox's avatar
Russ Cox committed
1414
		*r.Expr = expr
1415 1416

		// Record source-level edit for cgo output.
1417
		if !r.Done {
1418 1419 1420
			// Prepend a space in case the earlier code ends
			// with '/', which would give us a "//" comment.
			repl := " " + gofmtPos(expr, old.Pos())
1421 1422 1423 1424 1425 1426 1427 1428 1429
			end := fset.Position(old.End())
			// Subtract 1 from the column if we are going to
			// append a close parenthesis. That will set the
			// correct column for the following characters.
			sub := 0
			if r.Name.Kind != "type" {
				sub = 1
			}
			if end.Column > sub {
1430
				repl = fmt.Sprintf("%s /*line :%d:%d*/", repl, end.Line, end.Column-sub)
1431
			}
1432 1433 1434 1435
			if r.Name.Kind != "type" {
				repl = "(" + repl + ")"
			}
			f.Edit.Replace(f.offset(old.Pos()), f.offset(old.End()), repl)
1436
		}
Russ Cox's avatar
Russ Cox committed
1437
	}
1438 1439 1440 1441 1442 1443 1444 1445

	// Remove functions only used as expressions, so their respective
	// bridge functions are not generated.
	for name, used := range functions {
		if !used {
			delete(f.Name, name)
		}
	}
Russ Cox's avatar
Russ Cox committed
1446 1447
}

1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
// rewriteName returns the expression used to rewrite a reference.
func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
	var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
	switch r.Context {
	case ctxCall, ctxCall2:
		if r.Name.Kind != "func" {
			if r.Name.Kind == "type" {
				r.Context = ctxType
				if r.Name.Type == nil {
					error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
					break
				}
				expr = r.Name.Type.Go
				break
			}
			error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
			break
		}
		if r.Context == ctxCall2 {
			if r.Name.Go == "_CMalloc" {
				error_(r.Pos(), "no two-result form for C.malloc")
				break
			}
			// Invent new Name for the two-result function.
			n := f.Name["2"+r.Name.Go]
			if n == nil {
				n = new(Name)
				*n = *r.Name
				n.AddError = true
				n.Mangle = "_C2func_" + n.Go
				f.Name["2"+r.Name.Go] = n
			}
			expr = ast.NewIdent(n.Mangle)
			r.Name = n
			break
		}
	case ctxExpr:
		switch r.Name.Kind {
		case "func":
			if builtinDefs[r.Name.C] != "" {
				error_(r.Pos(), "use of builtin '%s' not in function call", fixGo(r.Name.C))
			}

			// Function is being used in an expression, to e.g. pass around a C function pointer.
			// Create a new Name for this Ref which causes the variable to be declared in Go land.
			fpName := "fp_" + r.Name.Go
			name := f.Name[fpName]
			if name == nil {
				name = &Name{
					Go:   fpName,
					C:    r.Name.C,
					Kind: "fpvar",
					Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
				}
				p.mangleName(name)
				f.Name[fpName] = name
			}
			r.Name = name
			// Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
			// function is defined in out.go and simply returns its argument. See
			// issue 7757.
			expr = &ast.CallExpr{
				Fun:  &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
				Args: []ast.Expr{ast.NewIdent(name.Mangle)},
			}
		case "type":
			// Okay - might be new(T)
			if r.Name.Type == nil {
				error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
				break
			}
			expr = r.Name.Type.Go
		case "var":
			expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
		case "macro":
			expr = &ast.CallExpr{Fun: expr}
		}
	case ctxSelector:
		if r.Name.Kind == "var" {
			expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
		} else {
			error_(r.Pos(), "only C variables allowed in selector expression %s", fixGo(r.Name.Go))
		}
	case ctxType:
		if r.Name.Kind != "type" {
			error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
		} else if r.Name.Type == nil {
			// Use of C.enum_x, C.struct_x or C.union_x without C definition.
			// GCC won't raise an error when using pointers to such unknown types.
			error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
		} else {
			expr = r.Name.Type.Go
		}
	default:
		if r.Name.Kind == "func" {
			error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
		}
	}
	return expr
}

1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
// gofmtPos returns the gofmt-formatted string for an AST node,
// with a comment setting the position before the node.
func gofmtPos(n ast.Expr, pos token.Pos) string {
	s := gofmtLine(n)
	p := fset.Position(pos)
	if p.Column == 0 {
		return s
	}
	return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s)
}

1560 1561 1562 1563 1564
// gccBaseCmd returns the start of the compiler command line.
// It uses $CC if set, or else $GCC, or else the compiler recorded
// during the initial build as defaultCC.
// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
func (p *Package) gccBaseCmd() []string {
Russ Cox's avatar
Russ Cox committed
1565
	// Use $CC if set, since that's what the build uses.
1566
	if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
Russ Cox's avatar
Russ Cox committed
1567
		return ret
1568
	}
1569 1570
	// Try $GCC if set, since that's what we used to use.
	if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
Russ Cox's avatar
Russ Cox committed
1571 1572
		return ret
	}
1573
	return strings.Fields(defaultCC(goos, goarch))
1574 1575
}

Shenghou Ma's avatar
Shenghou Ma committed
1576
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1577
func (p *Package) gccMachine() []string {
1578
	switch goarch {
1579 1580 1581 1582
	case "amd64":
		return []string{"-m64"}
	case "386":
		return []string{"-m32"}
Shenghou Ma's avatar
Shenghou Ma committed
1583
	case "arm":
1584
		return []string{"-marm"} // not thumb
1585 1586 1587 1588
	case "s390":
		return []string{"-m31"}
	case "s390x":
		return []string{"-m64"}
1589 1590
	case "mips64", "mips64le":
		return []string{"-mabi=64"}
1591 1592
	case "mips", "mipsle":
		return []string{"-mabi=32"}
1593 1594
	}
	return nil
Russ Cox's avatar
Russ Cox committed
1595
}
1596

Russ Cox's avatar
Russ Cox committed
1597 1598 1599
func gccTmp() string {
	return *objDir + "_cgo_.o"
}
Russ Cox's avatar
Russ Cox committed
1600 1601 1602 1603

// gccCmd returns the gcc command line to use for compiling
// the input.
func (p *Package) gccCmd() []string {
1604
	c := append(p.gccBaseCmd(),
1605 1606 1607 1608 1609 1610
		"-w",          // no warnings
		"-Wno-error",  // warnings are not errors
		"-o"+gccTmp(), // write object to tmp
		"-gdwarf-2",   // generate DWARF v2 debugging symbols
		"-c",          // do not link
		"-xc",         // input language is C
1611
	)
1612
	if p.GccIsClang {
Russ Cox's avatar
Russ Cox committed
1613 1614
		c = append(c,
			"-ferror-limit=0",
1615 1616 1617 1618
			// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
			// doesn't have -Wno-unneeded-internal-declaration, so we need yet another
			// flag to disable the warning. Yes, really good diagnostics, clang.
			"-Wno-unknown-warning-option",
Russ Cox's avatar
Russ Cox committed
1619
			"-Wno-unneeded-internal-declaration",
1620 1621
			"-Wno-unused-function",
			"-Qunused-arguments",
1622 1623 1624 1625 1626
			// Clang embeds prototypes for some builtin functions,
			// like malloc and calloc, but all size_t parameters are
			// incorrectly typed unsigned long. We work around that
			// by disabling the builtin functions (this is safe as
			// it won't affect the actual compilation of the C code).
1627
			// See: https://golang.org/issue/6506.
1628
			"-fno-builtin",
Russ Cox's avatar
Russ Cox committed
1629 1630 1631
		)
	}

1632
	c = append(c, p.GccOptions...)
1633
	c = append(c, p.gccMachine()...)
1634 1635 1636
	if goos == "aix" {
		c = append(c, "-maix64")
	}
1637 1638
	c = append(c, "-") //read input from standard input
	return c
Russ Cox's avatar
Russ Cox committed
1639 1640 1641
}

// gccDebug runs gcc -gdwarf-2 over the C program stdin and
1642
// returns the corresponding DWARF data and, if present, debug data block.
1643
func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
1644
	runGcc(stdin, p.gccCmd())
1645

1646
	isDebugInts := func(s string) bool {
1647
		// Some systems use leading _ to denote non-assembly symbols.
1648 1649 1650 1651 1652
		return s == "__cgodebug_ints" || s == "___cgodebug_ints"
	}
	isDebugFloats := func(s string) bool {
		// Some systems use leading _ to denote non-assembly symbols.
		return s == "__cgodebug_floats" || s == "___cgodebug_floats"
1653
	}
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689
	indexOfDebugStr := func(s string) int {
		// Some systems use leading _ to denote non-assembly symbols.
		if strings.HasPrefix(s, "___") {
			s = s[1:]
		}
		if strings.HasPrefix(s, "__cgodebug_str__") {
			if n, err := strconv.Atoi(s[len("__cgodebug_str__"):]); err == nil {
				return n
			}
		}
		return -1
	}
	indexOfDebugStrlen := func(s string) int {
		// Some systems use leading _ to denote non-assembly symbols.
		if strings.HasPrefix(s, "___") {
			s = s[1:]
		}
		if strings.HasPrefix(s, "__cgodebug_strlen__") {
			if n, err := strconv.Atoi(s[len("__cgodebug_strlen__"):]); err == nil {
				return n
			}
		}
		return -1
	}

	strs = make([]string, nnames)

	strdata := make(map[int]string, nnames)
	strlens := make(map[int]int, nnames)

	buildStrings := func() {
		for n, strlen := range strlens {
			data := strdata[n]
			if len(data) <= strlen {
				fatalf("invalid string literal")
			}
1690
			strs[n] = data[:strlen]
1691 1692
		}
	}
1693

Russ Cox's avatar
Russ Cox committed
1694
	if f, err := macho.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1695
		defer f.Close()
1696 1697
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1698
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1699
		}
1700
		bo := f.ByteOrder
1701 1702 1703
		if f.Symtab != nil {
			for i := range f.Symtab.Syms {
				s := &f.Symtab.Syms[i]
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
				switch {
				case isDebugInts(s.Name):
					// Found it. Now find data section.
					if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value-sect.Addr:]
								ints = make([]int64, len(data)/8)
								for i := range ints {
									ints[i] = int64(bo.Uint64(data[i*8:]))
								}
							}
						}
					}
				case isDebugFloats(s.Name):
1720
					// Found it. Now find data section.
1721 1722 1723 1724
					if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
							if sdat, err := sect.Data(); err == nil {
1725 1726 1727 1728 1729
								data := sdat[s.Value-sect.Addr:]
								floats = make([]float64, len(data)/8)
								for i := range floats {
									floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
								}
1730 1731 1732
							}
						}
					}
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
				default:
					if n := indexOfDebugStr(s.Name); n != -1 {
						// Found it. Now find data section.
						if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
							sect := f.Sections[i]
							if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
								if sdat, err := sect.Data(); err == nil {
									data := sdat[s.Value-sect.Addr:]
									strdata[n] = string(data)
								}
							}
						}
						break
					}
					if n := indexOfDebugStrlen(s.Name); n != -1 {
						// Found it. Now find data section.
						if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
							sect := f.Sections[i]
							if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
								if sdat, err := sect.Data(); err == nil {
									data := sdat[s.Value-sect.Addr:]
									strlen := bo.Uint64(data[:8])
									if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
										fatalf("string literal too big")
									}
									strlens[n] = int(strlen)
								}
							}
						}
						break
					}
1764
				}
1765
			}
1766 1767

			buildStrings()
1768
		}
1769
		return d, ints, floats, strs
1770 1771
	}

Russ Cox's avatar
Russ Cox committed
1772
	if f, err := elf.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1773
		defer f.Close()
1774 1775
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1776
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1777
		}
1778
		bo := f.ByteOrder
1779 1780 1781 1782
		symtab, err := f.Symbols()
		if err == nil {
			for i := range symtab {
				s := &symtab[i]
1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
				switch {
				case isDebugInts(s.Name):
					// Found it. Now find data section.
					if i := int(s.Section); 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value-sect.Addr:]
								ints = make([]int64, len(data)/8)
								for i := range ints {
									ints[i] = int64(bo.Uint64(data[i*8:]))
								}
							}
						}
					}
				case isDebugFloats(s.Name):
1799
					// Found it. Now find data section.
1800 1801 1802 1803
					if i := int(s.Section); 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
							if sdat, err := sect.Data(); err == nil {
1804 1805 1806 1807 1808
								data := sdat[s.Value-sect.Addr:]
								floats = make([]float64, len(data)/8)
								for i := range floats {
									floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
								}
1809 1810 1811
							}
						}
					}
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842
				default:
					if n := indexOfDebugStr(s.Name); n != -1 {
						// Found it. Now find data section.
						if i := int(s.Section); 0 <= i && i < len(f.Sections) {
							sect := f.Sections[i]
							if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
								if sdat, err := sect.Data(); err == nil {
									data := sdat[s.Value-sect.Addr:]
									strdata[n] = string(data)
								}
							}
						}
						break
					}
					if n := indexOfDebugStrlen(s.Name); n != -1 {
						// Found it. Now find data section.
						if i := int(s.Section); 0 <= i && i < len(f.Sections) {
							sect := f.Sections[i]
							if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
								if sdat, err := sect.Data(); err == nil {
									data := sdat[s.Value-sect.Addr:]
									strlen := bo.Uint64(data[:8])
									if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
										fatalf("string literal too big")
									}
									strlens[n] = int(strlen)
								}
							}
						}
						break
					}
1843 1844
				}
			}
1845 1846

			buildStrings()
1847
		}
1848
		return d, ints, floats, strs
1849
	}
1850

Russ Cox's avatar
Russ Cox committed
1851
	if f, err := pe.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1852
		defer f.Close()
1853 1854
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1855
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1856
		}
1857
		bo := binary.LittleEndian
1858
		for _, s := range f.Symbols {
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
			switch {
			case isDebugInts(s.Name):
				if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
					sect := f.Sections[i]
					if s.Value < sect.Size {
						if sdat, err := sect.Data(); err == nil {
							data := sdat[s.Value:]
							ints = make([]int64, len(data)/8)
							for i := range ints {
								ints[i] = int64(bo.Uint64(data[i*8:]))
							}
						}
					}
				}
			case isDebugFloats(s.Name):
1874 1875 1876 1877
				if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
					sect := f.Sections[i]
					if s.Value < sect.Size {
						if sdat, err := sect.Data(); err == nil {
1878 1879 1880 1881 1882
							data := sdat[s.Value:]
							floats = make([]float64, len(data)/8)
							for i := range floats {
								floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
							}
1883 1884 1885
						}
					}
				}
1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914
			default:
				if n := indexOfDebugStr(s.Name); n != -1 {
					if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if s.Value < sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value:]
								strdata[n] = string(data)
							}
						}
					}
					break
				}
				if n := indexOfDebugStrlen(s.Name); n != -1 {
					if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if s.Value < sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value:]
								strlen := bo.Uint64(data[:8])
								if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
									fatalf("string literal too big")
								}
								strlens[n] = int(strlen)
							}
						}
					}
					break
				}
1915 1916
			}
		}
1917 1918 1919 1920

		buildStrings()

		return d, ints, floats, strs
1921 1922
	}

1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
	if f, err := xcoff.Open(gccTmp()); err == nil {
		defer f.Close()
		d, err := f.DWARF()
		if err != nil {
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
		}
		bo := binary.BigEndian
		for _, s := range f.Symbols {
			switch {
			case isDebugInts(s.Name):
				if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
					sect := f.Sections[i]
					if s.Value < sect.Size {
						if sdat, err := sect.Data(); err == nil {
							data := sdat[s.Value:]
							ints = make([]int64, len(data)/8)
							for i := range ints {
								ints[i] = int64(bo.Uint64(data[i*8:]))
							}
						}
					}
				}
			case isDebugFloats(s.Name):
				if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
					sect := f.Sections[i]
					if s.Value < sect.Size {
						if sdat, err := sect.Data(); err == nil {
							data := sdat[s.Value:]
							floats = make([]float64, len(data)/8)
							for i := range floats {
								floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
							}
						}
					}
				}
			default:
				if n := indexOfDebugStr(s.Name); n != -1 {
					if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if s.Value < sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value:]
								strdata[n] = string(data)
							}
						}
					}
					break
				}
				if n := indexOfDebugStrlen(s.Name); n != -1 {
					if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
						sect := f.Sections[i]
						if s.Value < sect.Size {
							if sdat, err := sect.Data(); err == nil {
								data := sdat[s.Value:]
								strlen := bo.Uint64(data[:8])
								if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
									fatalf("string literal too big")
								}
								strlens[n] = int(strlen)
							}
						}
					}
					break
				}
			}
		}

		buildStrings()
		return d, ints, floats, strs
	}
	fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
1994
	panic("not reached")
1995 1996
}

Russ Cox's avatar
Russ Cox committed
1997 1998 1999 2000 2001
// gccDefines runs gcc -E -dM -xc - over the C program stdin
// and returns the corresponding standard output, which is the
// #defines that gcc encountered while processing the input
// and its included files.
func (p *Package) gccDefines(stdin []byte) string {
2002
	base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
2003
	base = append(base, p.gccMachine()...)
2004
	stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
Russ Cox's avatar
Russ Cox committed
2005 2006 2007 2008
	return stdout
}

// gccErrors runs gcc over the C program stdin and returns
2009
// the errors that gcc prints. That is, this function expects
Russ Cox's avatar
Russ Cox committed
2010 2011 2012
// gcc to fail.
func (p *Package) gccErrors(stdin []byte) string {
	// TODO(rsc): require failure
2013
	args := p.gccCmd()
2014

2015 2016 2017 2018 2019 2020 2021 2022
	// Optimization options can confuse the error messages; remove them.
	nargs := make([]string, 0, len(args))
	for _, arg := range args {
		if !strings.HasPrefix(arg, "-O") {
			nargs = append(nargs, arg)
		}
	}

2023
	// Force -O0 optimization but keep the trailing "-" at the end.
2024
	nargs = append(nargs, "-O0")
2025 2026
	nl := len(nargs)
	nargs[nl-2], nargs[nl-1] = nargs[nl-1], nargs[nl-2]
2027

Russ Cox's avatar
Russ Cox committed
2028
	if *debugGcc {
2029
		fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
Russ Cox's avatar
Russ Cox committed
2030 2031 2032
		os.Stderr.Write(stdin)
		fmt.Fprint(os.Stderr, "EOF\n")
	}
2033
	stdout, stderr, _ := run(stdin, nargs)
Russ Cox's avatar
Russ Cox committed
2034 2035 2036
	if *debugGcc {
		os.Stderr.Write(stdout)
		os.Stderr.Write(stderr)
2037
	}
Russ Cox's avatar
Russ Cox committed
2038 2039
	return string(stderr)
}
2040

Russ Cox's avatar
Russ Cox committed
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057
// runGcc runs the gcc command line args with stdin on standard input.
// If the command exits with a non-zero exit status, runGcc prints
// details about what was run and exits.
// Otherwise runGcc returns the data written to standard output and standard error.
// Note that for some of the uses we expect useful data back
// on standard error, but for those uses gcc must still exit 0.
func runGcc(stdin []byte, args []string) (string, string) {
	if *debugGcc {
		fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
		os.Stderr.Write(stdin)
		fmt.Fprint(os.Stderr, "EOF\n")
	}
	stdout, stderr, ok := run(stdin, args)
	if *debugGcc {
		os.Stderr.Write(stdout)
		os.Stderr.Write(stderr)
	}
2058
	if !ok {
Russ Cox's avatar
Russ Cox committed
2059 2060
		os.Stderr.Write(stderr)
		os.Exit(2)
2061
	}
Russ Cox's avatar
Russ Cox committed
2062
	return string(stdout), string(stderr)
2063 2064
}

Russ Cox's avatar
Russ Cox committed
2065 2066 2067 2068
// A typeConv is a translator from dwarf types to Go types
// with equivalent memory layout.
type typeConv struct {
	// Cache of already-translated or in-progress types.
2069
	m map[string]*Type
Russ Cox's avatar
Russ Cox committed
2070

2071
	// Map from types to incomplete pointers to those types.
2072
	ptrs map[string][]*Type
2073
	// Keys of ptrs in insertion order (deterministic worklist)
2074
	// ptrKeys contains exactly the keys in ptrs.
2075
	ptrKeys []dwarf.Type
2076

2077 2078 2079
	// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
	getTypeIDs map[string]bool

Russ Cox's avatar
Russ Cox committed
2080
	// Predeclared types.
Devon H. O'Dell's avatar
Devon H. O'Dell committed
2081
	bool                                   ast.Expr
2082 2083 2084 2085
	byte                                   ast.Expr // denotes padding
	int8, int16, int32, int64              ast.Expr
	uint8, uint16, uint32, uint64, uintptr ast.Expr
	float32, float64                       ast.Expr
2086
	complex64, complex128                  ast.Expr
2087 2088
	void                                   ast.Expr
	string                                 ast.Expr
2089
	goVoid                                 ast.Expr // _Ctype_void, denotes C's void
2090
	goVoidPtr                              ast.Expr // unsafe.Pointer or *byte
Russ Cox's avatar
Russ Cox committed
2091

2092
	ptrSize int64
Russ Cox's avatar
Russ Cox committed
2093
	intSize int64
Russ Cox's avatar
Russ Cox committed
2094 2095
}

2096
var tagGen int
Russ Cox's avatar
Russ Cox committed
2097
var typedef = make(map[string]*Type)
2098
var goIdent = make(map[string]*ast.Ident)
2099

2100
// unionWithPointer is true for a Go type that represents a C union (or class)
2101
// that may contain a pointer. This is used for cgo pointer checking.
2102 2103
var unionWithPointer = make(map[ast.Expr]bool)

Russ Cox's avatar
Russ Cox committed
2104
func (c *typeConv) Init(ptrSize, intSize int64) {
2105
	c.ptrSize = ptrSize
Russ Cox's avatar
Russ Cox committed
2106
	c.intSize = intSize
2107 2108
	c.m = make(map[string]*Type)
	c.ptrs = make(map[string][]*Type)
2109
	c.getTypeIDs = make(map[string]bool)
Devon H. O'Dell's avatar
Devon H. O'Dell committed
2110
	c.bool = c.Ident("bool")
2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122
	c.byte = c.Ident("byte")
	c.int8 = c.Ident("int8")
	c.int16 = c.Ident("int16")
	c.int32 = c.Ident("int32")
	c.int64 = c.Ident("int64")
	c.uint8 = c.Ident("uint8")
	c.uint16 = c.Ident("uint16")
	c.uint32 = c.Ident("uint32")
	c.uint64 = c.Ident("uint64")
	c.uintptr = c.Ident("uintptr")
	c.float32 = c.Ident("float32")
	c.float64 = c.Ident("float64")
2123 2124
	c.complex64 = c.Ident("complex64")
	c.complex128 = c.Ident("complex128")
2125 2126
	c.void = c.Ident("void")
	c.string = c.Ident("string")
2127
	c.goVoid = c.Ident("_Ctype_void")
2128 2129

	// Normally cgo translates void* to unsafe.Pointer,
2130 2131
	// but for historical reasons -godefs uses *byte instead.
	if *godefs {
2132 2133 2134 2135
		c.goVoidPtr = &ast.StarExpr{X: c.byte}
	} else {
		c.goVoidPtr = c.Ident("unsafe.Pointer")
	}
Russ Cox's avatar
Russ Cox committed
2136 2137 2138 2139 2140 2141
}

// base strips away qualifiers and typedefs to get the underlying type
func base(dt dwarf.Type) dwarf.Type {
	for {
		if d, ok := dt.(*dwarf.QualType); ok {
2142 2143
			dt = d.Type
			continue
Russ Cox's avatar
Russ Cox committed
2144 2145
		}
		if d, ok := dt.(*dwarf.TypedefType); ok {
2146 2147
			dt = d.Type
			continue
Russ Cox's avatar
Russ Cox committed
2148
		}
2149
		break
Russ Cox's avatar
Russ Cox committed
2150
	}
2151
	return dt
Russ Cox's avatar
Russ Cox committed
2152 2153
}

2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166
// unqual strips away qualifiers from a DWARF type.
// In general we don't care about top-level qualifiers.
func unqual(dt dwarf.Type) dwarf.Type {
	for {
		if d, ok := dt.(*dwarf.QualType); ok {
			dt = d.Type
		} else {
			break
		}
	}
	return dt
}

Russ Cox's avatar
Russ Cox committed
2167
// Map from dwarf text names to aliases we use in package "C".
Russ Cox's avatar
Russ Cox committed
2168
var dwarfToName = map[string]string{
2169 2170 2171 2172
	"long int":               "long",
	"long unsigned int":      "ulong",
	"unsigned int":           "uint",
	"short unsigned int":     "ushort",
2173
	"unsigned short":         "ushort", // Used by Clang; issue 13129.
2174 2175
	"short int":              "short",
	"long long int":          "longlong",
Russ Cox's avatar
Russ Cox committed
2176
	"long long unsigned int": "ulonglong",
2177
	"signed char":            "schar",
2178
	"unsigned char":          "uchar",
Robert Griesemer's avatar
Robert Griesemer committed
2179
}
Russ Cox's avatar
Russ Cox committed
2180

2181 2182
const signedDelta = 64

2183
// String returns the current type representation. Format arguments
2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195
// are assembled within this method so that any changes in mutable
// values are taken into account.
func (tr *TypeRepr) String() string {
	if len(tr.Repr) == 0 {
		return ""
	}
	if len(tr.FormatArgs) == 0 {
		return tr.Repr
	}
	return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
}

2196
// Empty reports whether the result of String would be "".
2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208
func (tr *TypeRepr) Empty() bool {
	return len(tr.Repr) == 0
}

// Set modifies the type representation.
// If fargs are provided, repr is used as a format for fmt.Sprintf.
// Otherwise, repr is used unprocessed as the type representation.
func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
	tr.Repr = repr
	tr.FormatArgs = fargs
}

2209
// FinishType completes any outstanding type mapping work.
2210
// In particular, it resolves incomplete pointer types.
2211 2212 2213
func (c *typeConv) FinishType(pos token.Pos) {
	// Completing one pointer type might produce more to complete.
	// Keep looping until they're all done.
2214 2215
	for len(c.ptrKeys) > 0 {
		dtype := c.ptrKeys[0]
2216
		dtypeKey := dtype.String()
2217
		c.ptrKeys = c.ptrKeys[1:]
2218 2219
		ptrs := c.ptrs[dtypeKey]
		delete(c.ptrs, dtypeKey)
2220

2221
		// Note Type might invalidate c.ptrs[dtypeKey].
2222
		t := c.Type(dtype, pos)
2223
		for _, ptr := range ptrs {
2224 2225
			ptr.Go.(*ast.StarExpr).X = t.Go
			ptr.C.Set("%s*", t.C)
2226 2227 2228 2229
		}
	}
}

Russ Cox's avatar
Russ Cox committed
2230 2231
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
2232
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
2233 2234 2235 2236 2237 2238 2239
	// Always recompute bad pointer typedefs, as the set of such
	// typedefs changes as we see more types.
	checkCache := true
	if dtt, ok := dtype.(*dwarf.TypedefType); ok && c.badPointerTypedef(dtt) {
		checkCache = false
	}

2240
	key := dtype.String()
2241 2242 2243 2244 2245 2246 2247

	if checkCache {
		if t, ok := c.m[key]; ok {
			if t.Go == nil {
				fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
			}
			return t
Russ Cox's avatar
Russ Cox committed
2248 2249 2250
		}
	}

2251
	t := new(Type)
2252
	t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
2253
	t.Align = -1
2254
	t.C = &TypeRepr{Repr: dtype.Common().Name}
2255
	c.m[key] = t
Russ Cox's avatar
Russ Cox committed
2256

Russ Cox's avatar
Russ Cox committed
2257 2258
	switch dt := dtype.(type) {
	default:
2259
		fatalf("%s: unexpected type: %s", lineno(pos), dtype)
Russ Cox's avatar
Russ Cox committed
2260 2261 2262

	case *dwarf.AddrType:
		if t.Size != c.ptrSize {
2263
			fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2264
		}
2265 2266
		t.Go = c.uintptr
		t.Align = t.Size
Russ Cox's avatar
Russ Cox committed
2267 2268 2269 2270

	case *dwarf.ArrayType:
		if dt.StrideBitSize > 0 {
			// Cannot represent bit-sized elements in Go.
2271 2272
			t.Go = c.Opaque(t.Size)
			break
Russ Cox's avatar
Russ Cox committed
2273
		}
2274 2275 2276 2277 2278 2279
		count := dt.Count
		if count == -1 {
			// Indicates flexible array member, which Go doesn't support.
			// Translate to zero-length array instead.
			count = 0
		}
2280
		sub := c.Type(dt.Type, pos)
2281
		t.Align = sub.Align
2282
		t.Go = &ast.ArrayType{
2283
			Len: c.intExpr(count),
2284 2285
			Elt: sub.Go,
		}
2286 2287
		// Recalculate t.Size now that we know sub.Size.
		t.Size = count * sub.Size
2288
		t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
Russ Cox's avatar
Russ Cox committed
2289

Devon H. O'Dell's avatar
Devon H. O'Dell committed
2290 2291
	case *dwarf.BoolType:
		t.Go = c.bool
2292
		t.Align = 1
Devon H. O'Dell's avatar
Devon H. O'Dell committed
2293

Russ Cox's avatar
Russ Cox committed
2294 2295
	case *dwarf.CharType:
		if t.Size != 1 {
2296
			fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2297
		}
2298 2299
		t.Go = c.int8
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
2300 2301

	case *dwarf.EnumType:
2302 2303 2304
		if t.Align = t.Size; t.Align >= c.ptrSize {
			t.Align = c.ptrSize
		}
2305
		t.C.Set("enum " + dt.EnumName)
2306 2307 2308 2309 2310 2311 2312 2313 2314
		signed := 0
		t.EnumValues = make(map[string]int64)
		for _, ev := range dt.Val {
			t.EnumValues[ev.Name] = ev.Val
			if ev.Val < 0 {
				signed = signedDelta
			}
		}
		switch t.Size + int64(signed) {
Russ Cox's avatar
Russ Cox committed
2315
		default:
2316
			fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2317
		case 1:
2318
			t.Go = c.uint8
Russ Cox's avatar
Russ Cox committed
2319
		case 2:
2320
			t.Go = c.uint16
Russ Cox's avatar
Russ Cox committed
2321
		case 4:
2322
			t.Go = c.uint32
Russ Cox's avatar
Russ Cox committed
2323
		case 8:
2324
			t.Go = c.uint64
2325 2326 2327 2328 2329 2330 2331 2332
		case 1 + signedDelta:
			t.Go = c.int8
		case 2 + signedDelta:
			t.Go = c.int16
		case 4 + signedDelta:
			t.Go = c.int32
		case 8 + signedDelta:
			t.Go = c.int64
2333
		}
Russ Cox's avatar
Russ Cox committed
2334 2335 2336 2337

	case *dwarf.FloatType:
		switch t.Size {
		default:
2338
			fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2339
		case 4:
2340
			t.Go = c.float32
Russ Cox's avatar
Russ Cox committed
2341
		case 8:
2342
			t.Go = c.float64
Russ Cox's avatar
Russ Cox committed
2343 2344
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2345
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2346 2347
		}

2348 2349 2350
	case *dwarf.ComplexType:
		switch t.Size {
		default:
2351
			fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
2352 2353 2354 2355 2356
		case 8:
			t.Go = c.complex64
		case 16:
			t.Go = c.complex128
		}
2357
		if t.Align = t.Size / 2; t.Align >= c.ptrSize {
2358 2359 2360
			t.Align = c.ptrSize
		}

Russ Cox's avatar
Russ Cox committed
2361 2362 2363
	case *dwarf.FuncType:
		// No attempt at translation: would enable calls
		// directly between worlds, but we need to moderate those.
2364 2365
		t.Go = c.uintptr
		t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2366 2367 2368

	case *dwarf.IntType:
		if dt.BitSize > 0 {
2369
			fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
Russ Cox's avatar
Russ Cox committed
2370 2371 2372
		}
		switch t.Size {
		default:
2373
			fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2374
		case 1:
2375
			t.Go = c.int8
Russ Cox's avatar
Russ Cox committed
2376
		case 2:
2377
			t.Go = c.int16
Russ Cox's avatar
Russ Cox committed
2378
		case 4:
2379
			t.Go = c.int32
Russ Cox's avatar
Russ Cox committed
2380
		case 8:
2381
			t.Go = c.int64
2382 2383 2384 2385 2386
		case 16:
			t.Go = &ast.ArrayType{
				Len: c.intExpr(t.Size),
				Elt: c.uint8,
			}
Russ Cox's avatar
Russ Cox committed
2387 2388
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2389
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2390 2391 2392
		}

	case *dwarf.PtrType:
2393 2394 2395 2396 2397
		// Clang doesn't emit DW_AT_byte_size for pointer types.
		if t.Size != c.ptrSize && t.Size != -1 {
			fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
		}
		t.Size = c.ptrSize
2398
		t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2399 2400

		if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
2401
			t.Go = c.goVoidPtr
2402
			t.C.Set("void*")
2403 2404 2405 2406 2407 2408 2409 2410 2411
			dq := dt.Type
			for {
				if d, ok := dq.(*dwarf.QualType); ok {
					t.C.Set(d.Qual + " " + t.C.String())
					dq = d.Type
				} else {
					break
				}
			}
2412
			break
Russ Cox's avatar
Russ Cox committed
2413 2414
		}

2415 2416 2417
		// Placeholder initialization; completed in FinishType.
		t.Go = &ast.StarExpr{}
		t.C.Set("<incomplete>*")
2418 2419
		key := dt.Type.String()
		if _, ok := c.ptrs[key]; !ok {
2420 2421
			c.ptrKeys = append(c.ptrKeys, dt.Type)
		}
2422
		c.ptrs[key] = append(c.ptrs[key], t)
Russ Cox's avatar
Russ Cox committed
2423 2424

	case *dwarf.QualType:
2425 2426 2427 2428
		t1 := c.Type(dt.Type, pos)
		t.Size = t1.Size
		t.Align = t1.Align
		t.Go = t1.Go
2429 2430 2431
		if unionWithPointer[t1.Go] {
			unionWithPointer[t.Go] = true
		}
2432 2433 2434
		t.EnumValues = nil
		t.Typedef = ""
		t.C.Set("%s "+dt.Qual, t1.C)
2435
		return t
Russ Cox's avatar
Russ Cox committed
2436 2437 2438 2439

	case *dwarf.StructType:
		// Convert to Go struct, being careful about alignment.
		// Have to give it a name to simulate C "struct foo" references.
2440
		tag := dt.StructName
2441 2442 2443
		if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
			break
		}
Russ Cox's avatar
Russ Cox committed
2444
		if tag == "" {
2445 2446
			tag = "__" + strconv.Itoa(tagGen)
			tagGen++
2447 2448
		} else if t.C.Empty() {
			t.C.Set(dt.Kind + " " + tag)
Russ Cox's avatar
Russ Cox committed
2449
		}
Russ Cox's avatar
Russ Cox committed
2450
		name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
2451
		t.Go = name // publish before recursive calls
2452
		goIdent[name.Name] = name
2453 2454 2455 2456 2457 2458 2459 2460 2461 2462
		if dt.ByteSize < 0 {
			// Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
			// so execute the basic things that the struct case would do
			// other than try to determine a Go representation.
			tt := *t
			tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
			tt.Go = c.Ident("struct{}")
			typedef[name.Name] = &tt
			break
		}
Russ Cox's avatar
Russ Cox committed
2463
		switch dt.Kind {
2464
		case "class", "union":
2465
			t.Go = c.Opaque(t.Size)
2466 2467 2468
			if c.dwarfHasPointer(dt, pos) {
				unionWithPointer[t.Go] = true
			}
2469
			if t.C.Empty() {
2470
				t.C.Set("__typeof__(unsigned char[%d])", t.Size)
Russ Cox's avatar
Russ Cox committed
2471
			}
2472
			t.Align = 1 // TODO: should probably base this on field alignment.
Russ Cox's avatar
Russ Cox committed
2473
			typedef[name.Name] = t
Russ Cox's avatar
Russ Cox committed
2474
		case "struct":
2475
			g, csyntax, align := c.Struct(dt, pos)
2476 2477
			if t.C.Empty() {
				t.C.Set(csyntax)
Russ Cox's avatar
Russ Cox committed
2478
			}
2479
			t.Align = align
Russ Cox's avatar
Russ Cox committed
2480 2481 2482 2483 2484 2485
			tt := *t
			if tag != "" {
				tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
			}
			tt.Go = g
			typedef[name.Name] = &tt
Russ Cox's avatar
Russ Cox committed
2486 2487 2488 2489 2490 2491 2492 2493
		}

	case *dwarf.TypedefType:
		// Record typedef for printing.
		if dt.Name == "_GoString_" {
			// Special C name for Go string type.
			// Knows string layout used by compilers: pointer plus length,
			// which rounds up to 2 pointers after alignment.
2494 2495 2496 2497 2498
			t.Go = c.string
			t.Size = c.ptrSize * 2
			t.Align = c.ptrSize
			break
		}
Russ Cox's avatar
Russ Cox committed
2499 2500 2501 2502 2503 2504 2505 2506
		if dt.Name == "_GoBytes_" {
			// Special C name for Go []byte type.
			// Knows slice layout used by compilers: pointer, length, cap.
			t.Go = c.Ident("[]byte")
			t.Size = c.ptrSize + 4 + 4
			t.Align = c.ptrSize
			break
		}
2507 2508
		name := c.Ident("_Ctype_" + dt.Name)
		goIdent[name.Name] = name
2509
		sub := c.Type(dt.Type, pos)
2510
		if c.badPointerTypedef(dt) {
2511 2512 2513 2514
			// Treat this typedef as a uintptr.
			s := *sub
			s.Go = c.uintptr
			sub = &s
2515 2516 2517 2518
			// Make sure we update any previously computed type.
			if oldType := typedef[name.Name]; oldType != nil {
				oldType.Go = sub.Go
			}
2519
		}
2520
		t.Go = name
2521 2522 2523
		if unionWithPointer[sub.Go] {
			unionWithPointer[t.Go] = true
		}
2524 2525
		t.Size = sub.Size
		t.Align = sub.Align
2526 2527
		oldType := typedef[name.Name]
		if oldType == nil {
Russ Cox's avatar
Russ Cox committed
2528 2529 2530
			tt := *t
			tt.Go = sub.Go
			typedef[name.Name] = &tt
Russ Cox's avatar
Russ Cox committed
2531
		}
2532 2533 2534 2535

		// If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
		// use that as the Go form for this typedef too, so that the typedef will be interchangeable
		// with the base type.
2536 2537
		// In -godefs mode, do this for all typedefs.
		if isStructUnionClass(sub.Go) || *godefs {
2538
			t.Go = sub.Go
2539

2540 2541 2542 2543 2544
			if isStructUnionClass(sub.Go) {
				// Use the typedef name for C code.
				typedef[sub.Go.(*ast.Ident).Name].C = t.C
			}

2545 2546 2547 2548 2549 2550 2551 2552
			// If we've seen this typedef before, and it
			// was an anonymous struct/union/class before
			// too, use the old definition.
			// TODO: it would be safer to only do this if
			// we verify that the types are the same.
			if oldType != nil && isStructUnionClass(oldType.Go) {
				t.Go = oldType.Go
			}
2553
		}
Russ Cox's avatar
Russ Cox committed
2554 2555 2556

	case *dwarf.UcharType:
		if t.Size != 1 {
2557
			fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2558
		}
2559 2560
		t.Go = c.uint8
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
2561 2562 2563

	case *dwarf.UintType:
		if dt.BitSize > 0 {
2564
			fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
Russ Cox's avatar
Russ Cox committed
2565 2566 2567
		}
		switch t.Size {
		default:
2568
			fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2569
		case 1:
2570
			t.Go = c.uint8
Russ Cox's avatar
Russ Cox committed
2571
		case 2:
2572
			t.Go = c.uint16
Russ Cox's avatar
Russ Cox committed
2573
		case 4:
2574
			t.Go = c.uint32
Russ Cox's avatar
Russ Cox committed
2575
		case 8:
2576
			t.Go = c.uint64
2577 2578 2579 2580 2581
		case 16:
			t.Go = &ast.ArrayType{
				Len: c.intExpr(t.Size),
				Elt: c.uint8,
			}
Russ Cox's avatar
Russ Cox committed
2582 2583
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2584
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2585 2586 2587
		}

	case *dwarf.VoidType:
2588
		t.Go = c.goVoid
2589
		t.C.Set("void")
2590
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
2591 2592 2593
	}

	switch dtype.(type) {
2594
	case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
2595
		s := dtype.Common().Name
Russ Cox's avatar
Russ Cox committed
2596
		if s != "" {
Russ Cox's avatar
Russ Cox committed
2597
			if ss, ok := dwarfToName[s]; ok {
2598
				s = ss
Russ Cox's avatar
Russ Cox committed
2599
			}
2600
			s = strings.Replace(s, " ", "", -1)
Russ Cox's avatar
Russ Cox committed
2601
			name := c.Ident("_Ctype_" + s)
Russ Cox's avatar
Russ Cox committed
2602 2603
			tt := *t
			typedef[name.Name] = &tt
2604
			if !*godefs {
2605 2606
				t.Go = name
			}
Russ Cox's avatar
Russ Cox committed
2607 2608 2609
		}
	}

2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620
	if t.Size < 0 {
		// Unsized types are [0]byte, unless they're typedefs of other types
		// or structs with tags.
		// if so, use the name we've already defined.
		t.Size = 0
		switch dt := dtype.(type) {
		case *dwarf.TypedefType:
			// ok
		case *dwarf.StructType:
			if dt.StructName != "" {
				break
2621
			}
2622 2623 2624 2625 2626 2627
			t.Go = c.Opaque(0)
		default:
			t.Go = c.Opaque(0)
		}
		if t.C.Empty() {
			t.C.Set("void")
2628 2629 2630
		}
	}

2631
	if t.C.Empty() {
2632
		fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
Russ Cox's avatar
Russ Cox committed
2633 2634
	}

2635
	return t
Russ Cox's avatar
Russ Cox committed
2636 2637
}

2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
// isStructUnionClass reports whether the type described by the Go syntax x
// is a struct, union, or class with a tag.
func isStructUnionClass(x ast.Expr) bool {
	id, ok := x.(*ast.Ident)
	if !ok {
		return false
	}
	name := id.Name
	return strings.HasPrefix(name, "_Ctype_struct_") ||
		strings.HasPrefix(name, "_Ctype_union_") ||
		strings.HasPrefix(name, "_Ctype_class_")
}

Russ Cox's avatar
Russ Cox committed
2651 2652
// FuncArg returns a Go type with the same memory layout as
// dtype when used as the type of a C function argument.
2653
func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
2654
	t := c.Type(unqual(dtype), pos)
Russ Cox's avatar
Russ Cox committed
2655 2656 2657 2658
	switch dt := dtype.(type) {
	case *dwarf.ArrayType:
		// Arrays are passed implicitly as pointers in C.
		// In Go, we must be explicit.
2659 2660
		tr := &TypeRepr{}
		tr.Set("%s*", t.C)
Russ Cox's avatar
Russ Cox committed
2661
		return &Type{
2662
			Size:  c.ptrSize,
Russ Cox's avatar
Russ Cox committed
2663
			Align: c.ptrSize,
2664
			Go:    &ast.StarExpr{X: t.Go},
2665
			C:     tr,
2666
		}
Russ Cox's avatar
Russ Cox committed
2667 2668
	case *dwarf.TypedefType:
		// C has much more relaxed rules than Go for
2669
		// implicit type conversions. When the parameter
Russ Cox's avatar
Russ Cox committed
2670 2671 2672
		// is type T defined as *X, simulate a little of the
		// laxness of C by making the argument *X instead of T.
		if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
2673 2674
			// Unless the typedef happens to point to void* since
			// Go has special rules around using unsafe.Pointer.
Russ Cox's avatar
Russ Cox committed
2675 2676
			if _, void := base(ptr.Type).(*dwarf.VoidType); void {
				break
2677
			}
2678 2679
			// ...or the typedef is one in which we expect bad pointers.
			// It will be a uintptr instead of *X.
2680
			if c.baseBadPointerTypedef(dt) {
2681 2682
				break
			}
Russ Cox's avatar
Russ Cox committed
2683 2684 2685 2686 2687 2688

			t = c.Type(ptr, pos)
			if t == nil {
				return nil
			}

2689 2690 2691 2692 2693 2694
			// For a struct/union/class, remember the C spelling,
			// in case it has __attribute__((unavailable)).
			// See issue 2888.
			if isStructUnionClass(t.Go) {
				t.Typedef = dt.Name
			}
Russ Cox's avatar
Russ Cox committed
2695 2696
		}
	}
2697
	return t
Russ Cox's avatar
Russ Cox committed
2698 2699 2700 2701
}

// FuncType returns the Go type analogous to dtype.
// There is no guarantee about matching memory layout.
2702
func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
2703 2704
	p := make([]*Type, len(dtype.ParamType))
	gp := make([]*ast.Field, len(dtype.ParamType))
Russ Cox's avatar
Russ Cox committed
2705
	for i, f := range dtype.ParamType {
2706 2707
		// gcc's DWARF generator outputs a single DotDotDotType parameter for
		// function pointers that specify no parameters (e.g. void
2708
		// (*__cgo_0)()).  Treat this special case as void. This case is
2709 2710 2711
		// invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
		// legal).
		if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
2712 2713
			p, gp = nil, nil
			break
2714
		}
2715
		p[i] = c.FuncArg(f, pos)
2716
		gp[i] = &ast.Field{Type: p[i].Go}
Russ Cox's avatar
Russ Cox committed
2717
	}
2718 2719
	var r *Type
	var gr []*ast.Field
2720
	if _, ok := base(dtype.ReturnType).(*dwarf.VoidType); ok {
2721 2722
		gr = []*ast.Field{{Type: c.goVoid}}
	} else if dtype.ReturnType != nil {
2723
		r = c.Type(unqual(dtype.ReturnType), pos)
Russ Cox's avatar
Russ Cox committed
2724
		gr = []*ast.Field{{Type: r.Go}}
Russ Cox's avatar
Russ Cox committed
2725 2726 2727 2728 2729
	}
	return &FuncType{
		Params: p,
		Result: r,
		Go: &ast.FuncType{
2730
			Params:  &ast.FieldList{List: gp},
2731
			Results: &ast.FieldList{List: gr},
Robert Griesemer's avatar
Robert Griesemer committed
2732
		},
2733
	}
Russ Cox's avatar
Russ Cox committed
2734 2735 2736
}

// Identifier
Russ Cox's avatar
Russ Cox committed
2737 2738 2739
func (c *typeConv) Ident(s string) *ast.Ident {
	return ast.NewIdent(s)
}
Russ Cox's avatar
Russ Cox committed
2740 2741 2742 2743 2744

// Opaque type of n bytes.
func (c *typeConv) Opaque(n int64) ast.Expr {
	return &ast.ArrayType{
		Len: c.intExpr(n),
Robert Griesemer's avatar
Robert Griesemer committed
2745
		Elt: c.byte,
2746
	}
Russ Cox's avatar
Russ Cox committed
2747 2748 2749 2750 2751
}

// Expr for integer n.
func (c *typeConv) intExpr(n int64) ast.Expr {
	return &ast.BasicLit{
2752
		Kind:  token.INT,
Russ Cox's avatar
Russ Cox committed
2753
		Value: strconv.FormatInt(n, 10),
2754
	}
Russ Cox's avatar
Russ Cox committed
2755 2756 2757
}

// Add padding of given size to fld.
2758
func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
2759 2760 2761
	n := len(fld)
	fld = fld[0 : n+1]
	fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
2762 2763 2764
	sizes = sizes[0 : n+1]
	sizes[n] = size
	return fld, sizes
Russ Cox's avatar
Russ Cox committed
2765 2766
}

2767
// Struct conversion: return Go and (gc) C syntax for type.
2768
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
2769 2770 2771
	// Minimum alignment for a struct is 1 byte.
	align = 1

Russ Cox's avatar
Russ Cox committed
2772 2773
	var buf bytes.Buffer
	buf.WriteString("struct {")
2774
	fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
2775
	sizes := make([]int64, 0, 2*len(dt.Field)+1)
2776
	off := int64(0)
2777

Russ Cox's avatar
Russ Cox committed
2778
	// Rename struct fields that happen to be named Go keywords into
2779 2780
	// _{keyword}.  Create a map from C ident -> Go ident. The Go ident will
	// be mangled. Any existing identifier that already has the same name on
2781 2782 2783
	// the C-side will cause the Go-mangled version to be prefixed with _.
	// (e.g. in a struct with fields '_type' and 'type', the latter would be
	// rendered as '__type' in Go).
2784 2785
	ident := make(map[string]string)
	used := make(map[string]bool)
2786
	for _, f := range dt.Field {
2787 2788
		ident[f.Name] = f.Name
		used[f.Name] = true
2789 2790
	}

2791
	if !*godefs {
2792
		for cid, goid := range ident {
2793
			if token.Lookup(goid).IsKeyword() {
2794
				// Avoid keyword
2795 2796
				goid = "_" + goid

2797 2798 2799 2800 2801 2802 2803 2804
				// Also avoid existing fields
				for _, exist := used[goid]; exist; _, exist = used[goid] {
					goid = "_" + goid
				}

				used[goid] = true
				ident[cid] = goid
			}
2805 2806 2807
		}
	}

2808
	anon := 0
Russ Cox's avatar
Russ Cox committed
2809
	for _, f := range dt.Field {
2810 2811 2812
		name := f.Name
		ft := f.Type

2813
		// In godefs mode, if this field is a C11
2814
		// anonymous union then treat the first field in the
2815
		// union as the field in the struct. This handles
2816 2817
		// cases like the glibc <sys/resource.h> file; see
		// issue 6677.
2818
		if *godefs {
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829
			if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
				name = st.Field[0].Name
				ident[name] = name
				ft = st.Field[0].Type
			}
		}

		// TODO: Handle fields that are anonymous structs by
		// promoting the fields of the inner struct.

		t := c.Type(ft, pos)
2830 2831
		tgo := t.Go
		size := t.Size
2832
		talign := t.Align
2833
		if f.BitSize > 0 {
2834 2835 2836
			switch f.BitSize {
			case 8, 16, 32, 64:
			default:
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
				continue
			}
			size = f.BitSize / 8
			name := tgo.(*ast.Ident).String()
			if strings.HasPrefix(name, "int") {
				name = "int"
			} else {
				name = "uint"
			}
			tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
2847
			talign = size
2848 2849
		}

2850
		if talign > 0 && f.ByteOffset%talign != 0 {
2851 2852 2853 2854 2855 2856 2857
			// Drop misaligned fields, the same way we drop integer bit fields.
			// The goal is to make available what can be made available.
			// Otherwise one bad and unneeded field in an otherwise okay struct
			// makes the whole program not compile. Much of the time these
			// structs are in system headers that cannot be corrected.
			continue
		}
2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870

		// Round off up to talign, assumed to be a power of 2.
		off = (off + talign - 1) &^ (talign - 1)

		if f.ByteOffset > off {
			fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
			off = f.ByteOffset
		}
		if f.ByteOffset < off {
			// Drop a packed field that we can't represent.
			continue
		}

2871 2872
		n := len(fld)
		fld = fld[0 : n+1]
2873 2874 2875 2876 2877 2878
		if name == "" {
			name = fmt.Sprintf("anon%d", anon)
			anon++
			ident[name] = name
		}
		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
2879 2880
		sizes = sizes[0 : n+1]
		sizes[n] = size
2881
		off += size
2882
		buf.WriteString(t.C.String())
Russ Cox's avatar
Russ Cox committed
2883
		buf.WriteString(" ")
2884
		buf.WriteString(name)
Russ Cox's avatar
Russ Cox committed
2885
		buf.WriteString("; ")
2886 2887
		if talign > align {
			align = talign
Russ Cox's avatar
Russ Cox committed
2888 2889 2890
		}
	}
	if off < dt.ByteSize {
2891
		fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
2892
		off = dt.ByteSize
Russ Cox's avatar
Russ Cox committed
2893
	}
2894 2895 2896 2897 2898 2899

	// If the last field in a non-zero-sized struct is zero-sized
	// the compiler is going to pad it by one (see issue 9401).
	// We can't permit that, because then the size of the Go
	// struct will not be the same as the size of the C struct.
	// Our only option in such a case is to remove the field,
2900
	// which means that it cannot be referenced from Go.
2901 2902 2903 2904 2905 2906
	for off > 0 && sizes[len(sizes)-1] == 0 {
		n := len(sizes)
		fld = fld[0 : n-1]
		sizes = sizes[0 : n-1]
	}

Russ Cox's avatar
Russ Cox committed
2907
	if off != dt.ByteSize {
Russ Cox's avatar
Russ Cox committed
2908
		fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
Russ Cox's avatar
Russ Cox committed
2909
	}
Russ Cox's avatar
Russ Cox committed
2910 2911
	buf.WriteString("}")
	csyntax = buf.String()
2912

2913
	if *godefs {
2914
		godefsFields(fld)
2915
	}
2916
	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
2917
	return
Russ Cox's avatar
Russ Cox committed
2918
}
2919

2920
// dwarfHasPointer reports whether the DWARF type dt contains a pointer.
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957
func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
	switch dt := dt.(type) {
	default:
		fatalf("%s: unexpected type: %s", lineno(pos), dt)
		return false

	case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
		*dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
		*dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:

		return false

	case *dwarf.ArrayType:
		return c.dwarfHasPointer(dt.Type, pos)

	case *dwarf.PtrType:
		return true

	case *dwarf.QualType:
		return c.dwarfHasPointer(dt.Type, pos)

	case *dwarf.StructType:
		for _, f := range dt.Field {
			if c.dwarfHasPointer(f.Type, pos) {
				return true
			}
		}
		return false

	case *dwarf.TypedefType:
		if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
			return true
		}
		return c.dwarfHasPointer(dt.Type, pos)
	}
}

2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977
func upper(s string) string {
	if s == "" {
		return ""
	}
	r, size := utf8.DecodeRuneInString(s)
	if r == '_' {
		return "X" + s
	}
	return string(unicode.ToUpper(r)) + s[size:]
}

// godefsFields rewrites field names for use in Go or C definitions.
// It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
// converts names to upper case, and rewrites _ into Pad_godefs_n,
// so that all fields are exported.
func godefsFields(fld []*ast.Field) {
	prefix := fieldPrefix(fld)
	npad := 0
	for _, f := range fld {
		for _, n := range f.Names {
2978 2979
			if n.Name != prefix {
				n.Name = strings.TrimPrefix(n.Name, prefix)
2980 2981 2982 2983 2984 2985
			}
			if n.Name == "_" {
				// Use exported name instead.
				n.Name = "Pad_cgo_" + strconv.Itoa(npad)
				npad++
			}
2986
			n.Name = upper(n.Name)
2987 2988 2989 2990 2991
		}
	}
}

// fieldPrefix returns the prefix that should be removed from all the
2992
// field names when generating the C or Go code. For generated
2993 2994 2995 2996 2997 2998 2999 3000 3001
// C, we leave the names as is (tv_sec, tv_usec), since that's what
// people are used to seeing in C.  For generated Go code, such as
// package syscall's data structures, we drop a common prefix
// (so sec, usec, which will get turned into Sec, Usec for exporting).
func fieldPrefix(fld []*ast.Field) string {
	prefix := ""
	for _, f := range fld {
		for _, n := range f.Names {
			// Ignore field names that don't have the prefix we're
3002
			// looking for. It is common in C headers to have fields
3003 3004 3005
			// named, say, _pad in an otherwise prefixed header.
			// If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
			// still want to remove the tv_ prefix.
3006
			// The check for "orig_" here handles orig_eax in the
3007 3008 3009 3010 3011
			// x86 ptrace register sets, which otherwise have all fields
			// with reg_ prefixes.
			if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
				continue
			}
3012
			i := strings.Index(n.Name, "_")
3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
			if i < 0 {
				continue
			}
			if prefix == "" {
				prefix = n.Name[:i+1]
			} else if prefix != n.Name[:i+1] {
				return ""
			}
		}
	}
	return prefix
}
3025 3026 3027 3028 3029

// badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
// A typedef is bad if C code sometimes stores non-pointers in this type.
// TODO: Currently our best solution is to find these manually and list them as
// they come up. A better solution is desired.
3030 3031
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
	if c.badCFType(dt) {
3032 3033
		return true
	}
3034
	if c.badJNI(dt) {
3035 3036
		return true
	}
3037 3038 3039
	if c.badEGLDisplay(dt) {
		return true
	}
3040 3041 3042
	return false
}

3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055
// baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef
// as badPointerTypedef reports.
func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool {
	for {
		if t, ok := dt.Type.(*dwarf.TypedefType); ok {
			dt = t
			continue
		}
		break
	}
	return c.badPointerTypedef(dt)
}

3056
func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
3057
	// The real bad types are CFNumberRef and CFDateRef.
3058 3059
	// Sometimes non-pointers are stored in these types.
	// CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
3060 3061 3062
	// We return true for the other *Ref types just so casting between them is easier.
	// We identify the correct set of types as those ending in Ref and for which
	// there exists a corresponding GetTypeID function.
3063
	// See comment below for details about the bad pointers.
3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
	if goos != "darwin" {
		return false
	}
	s := dt.Name
	if !strings.HasSuffix(s, "Ref") {
		return false
	}
	s = s[:len(s)-3]
	if s == "CFType" {
		return true
	}
	if c.getTypeIDs[s] {
		return true
	}
	if i := strings.Index(s, "Mutable"); i >= 0 && c.getTypeIDs[s[:i]+s[i+7:]] {
		// Mutable and immutable variants share a type ID.
		return true
	}
	return false
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118
}

// Comment from Darwin's CFInternal.h
/*
// Tagged pointer support
// Low-bit set means tagged object, next 3 bits (currently)
// define the tagged object class, next 4 bits are for type
// information for the specific tagged object class.  Thus,
// the low byte is for type info, and the rest of a pointer
// (32 or 64-bit) is for payload, whatever the tagged class.
//
// Note that the specific integers used to identify the
// specific tagged classes can and will change from release
// to release (that's why this stuff is in CF*Internal*.h),
// as can the definition of type info vs payload above.
//
#if __LP64__
#define CF_IS_TAGGED_OBJ(PTR)	((uintptr_t)(PTR) & 0x1)
#define CF_TAGGED_OBJ_TYPE(PTR)	((uintptr_t)(PTR) & 0xF)
#else
#define CF_IS_TAGGED_OBJ(PTR)	0
#define CF_TAGGED_OBJ_TYPE(PTR)	0
#endif

enum {
    kCFTaggedObjectID_Invalid = 0,
    kCFTaggedObjectID_Atom = (0 << 1) + 1,
    kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
    kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
    kCFTaggedObjectID_Integer = (3 << 1) + 1,
    kCFTaggedObjectID_DateTS = (4 << 1) + 1,
    kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data
    kCFTaggedObjectID_Date = (6 << 1) + 1,
    kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
};
*/
3119

3120
func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143
	// In Dalvik and ART, the jobject type in the JNI interface of the JVM has the
	// property that it is sometimes (always?) a small integer instead of a real pointer.
	// Note: although only the android JVMs are bad in this respect, we declare the JNI types
	// bad regardless of platform, so the same Go code compiles on both android and non-android.
	if parent, ok := jniTypes[dt.Name]; ok {
		// Try to make sure we're talking about a JNI type, not just some random user's
		// type that happens to use the same name.
		// C doesn't have the notion of a package, so it's hard to be certain.

		// Walk up to jobject, checking each typedef on the way.
		w := dt
		for parent != "" {
			t, ok := w.Type.(*dwarf.TypedefType)
			if !ok || t.Name != parent {
				return false
			}
			w = t
			parent, ok = jniTypes[w.Name]
			if !ok {
				return false
			}
		}

3144 3145 3146 3147 3148 3149 3150 3151 3152
		// Check that the typedef is either:
		// 1:
		//     	struct _jobject;
		//     	typedef struct _jobject *jobject;
		// 2: (in NDK16 in C++)
		//     	class _jobject {};
		//     	typedef _jobject* jobject;
		// 3: (in NDK16 in C)
		//     	typedef void* jobject;
3153
		if ptr, ok := w.Type.(*dwarf.PtrType); ok {
3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168
			switch v := ptr.Type.(type) {
			case *dwarf.VoidType:
				return true
			case *dwarf.StructType:
				if v.StructName == "_jobject" && len(v.Field) == 0 {
					switch v.Kind {
					case "struct":
						if v.Incomplete {
							return true
						}
					case "class":
						if !v.Incomplete {
							return true
						}
					}
3169 3170 3171 3172 3173 3174 3175
				}
			}
		}
	}
	return false
}

3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188
func (c *typeConv) badEGLDisplay(dt *dwarf.TypedefType) bool {
	if dt.Name != "EGLDisplay" {
		return false
	}
	// Check that the typedef is "typedef void *EGLDisplay".
	if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
		if _, ok := ptr.Type.(*dwarf.VoidType); ok {
			return true
		}
	}
	return false
}

3189
// jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which
3190
// they are mapped. The base "jobject" maps to the empty string.
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207
var jniTypes = map[string]string{
	"jobject":       "",
	"jclass":        "jobject",
	"jthrowable":    "jobject",
	"jstring":       "jobject",
	"jarray":        "jobject",
	"jbooleanArray": "jarray",
	"jbyteArray":    "jarray",
	"jcharArray":    "jarray",
	"jshortArray":   "jarray",
	"jintArray":     "jarray",
	"jlongArray":    "jarray",
	"jfloatArray":   "jarray",
	"jdoubleArray":  "jarray",
	"jobjectArray":  "jarray",
	"jweak":         "jobject",
}