gcc.go 77.5 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
	"math"
24 25 26
	"os"
	"strconv"
	"strings"
27
	"unicode"
28
	"unicode/utf8"
29 30
)

Russ Cox's avatar
Russ Cox committed
31 32 33 34
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{
35 36 37 38 39 40 41
	"schar":         "signed char",
	"uchar":         "unsigned char",
	"ushort":        "unsigned short",
	"uint":          "unsigned int",
	"ulong":         "unsigned long",
	"longlong":      "long long",
	"ulonglong":     "unsigned long long",
42 43
	"complexfloat":  "float _Complex",
	"complexdouble": "double _Complex",
Russ Cox's avatar
Russ Cox committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
}

// 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_"):]
	}
64 65 66
	if strings.HasPrefix(s, "sizeof_") {
		return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
	}
Russ Cox's avatar
Russ Cox committed
67 68 69
	return s
}

70 71 72 73
// 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() {
74
	linesIn := strings.Split(f.Preamble, "\n")
75 76 77
	linesOut := make([]string, 0, len(linesIn))
	for _, line := range linesIn {
		l := strings.TrimSpace(line)
78
		if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
79
			linesOut = append(linesOut, line)
80 81
		} else {
			linesOut = append(linesOut, "")
82 83 84 85 86
		}
	}
	f.Preamble = strings.Join(linesOut, "\n")
}

87
// addToFlag appends args to flag. All flags are later written out onto the
88 89
// _cgo_flags file for the build system to use.
func (p *Package) addToFlag(flag string, args []string) {
90
	p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
91 92 93 94 95 96
	if flag == "CFLAGS" {
		// We'll also need these when preprocessing for dwarf information.
		p.GccOptions = append(p.GccOptions, args...)
	}
}

97 98 99 100 101 102
// 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
103
// last element. The backslash is used for escaping.
104 105 106 107 108 109 110 111 112
//
// For example, the following string:
//
//     `a b:"c d" 'e''f'  "g\""`
//
// Would be parsed as:
//
//     []string{"a", "b:c d", "ef", `g"`}
//
113
func splitQuoted(s string) (r []string, err error) {
114
	var args []string
115
	arg := make([]rune, len(s))
116 117
	escaped := false
	quoted := false
118
	quote := '\x00'
119
	i := 0
120
	for _, r := range s {
121 122 123
		switch {
		case escaped:
			escaped = false
124
		case r == '\\':
125 126 127
			escaped = true
			continue
		case quote != 0:
128
			if r == quote {
129 130 131
				quote = 0
				continue
			}
132
		case r == '"' || r == '\'':
133
			quoted = true
134
			quote = r
135
			continue
136
		case unicode.IsSpace(r):
137 138 139 140 141 142 143
			if quoted || i > 0 {
				quoted = false
				args = append(args, string(arg[:i]))
				i = 0
			}
			continue
		}
144
		arg[i] = r
145 146 147 148 149 150
		i++
	}
	if quoted || i > 0 {
		args = append(args, string(arg[:i]))
	}
	if quote != 0 {
151
		err = errors.New("unclosed quote")
152
	} else if escaped {
153
		err = errors.New("unfinished escaping")
154 155 156 157
	}
	return args, err
}

Russ Cox's avatar
Russ Cox committed
158 159 160 161 162 163 164 165 166
// 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)
	}
	p.loadDefines(f)
167 168 169 170 171 172 173 174 175 176
	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.
		for _, a := range p.typedefList {
			f.Name[a] = &Name{
				Go: a,
				C:  a,
177 178
			}
		}
179 180 181 182
		needType := p.guessKinds(f)
		if len(needType) > 0 {
			p.loadDWARF(f, needType)
		}
183 184 185 186 187 188 189

		// 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
190
	}
191
	p.prepareNames(f)
192
	if p.rewriteCalls(f) {
193 194
		// Add `import _cgo_unsafe "unsafe"` after the package statement.
		f.Edit.Insert(f.offset(f.AST.Name.End()), "; import _cgo_unsafe \"unsafe\"")
195
	}
Russ Cox's avatar
Russ Cox committed
196 197 198 199 200 201
	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) {
202
	var b bytes.Buffer
203
	b.WriteString(builtinProlog)
204
	b.WriteString(f.Preamble)
Russ Cox's avatar
Russ Cox committed
205
	stdout := p.gccDefines(b.Bytes())
206

207
	for _, line := range strings.Split(stdout, "\n") {
208 209 210 211 212 213 214
		if len(line) < 9 || line[0:7] != "#define" {
			continue
		}

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

		var key, val string
215
		spaceIndex := strings.Index(line, " ")
216 217 218 219 220 221 222 223 224 225 226 227
		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:])
		}

228 229 230 231
		if key == "__clang__" {
			p.GccIsClang = true
		}

Russ Cox's avatar
Russ Cox committed
232 233 234
		if n := f.Name[key]; n != nil {
			if *debugDefine {
				fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
235
			}
Russ Cox's avatar
Russ Cox committed
236
			n.Define = val
237
		}
238
	}
Russ Cox's avatar
Russ Cox committed
239
}
240

Russ Cox's avatar
Russ Cox committed
241 242 243 244
// 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 {
245 246 247
	// Determine kinds for names we already know about,
	// like #defines or 'struct foo', before bothering with gcc.
	var names, needType []*Name
248
	optional := map[*Name]bool{}
249 250
	for _, key := range nameKeys(f.Name) {
		n := f.Name[key]
Russ Cox's avatar
Russ Cox committed
251 252 253
		// If we've already found this name as a #define
		// and we can translate it as a constant value, do so.
		if n.Define != "" {
254 255
			if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
				n.Kind = "iconst"
256
				// Turn decimal into hex, just for consistency
257
				// with enum-derived constants. Otherwise
258 259
				// in the cgo -godefs output half the constants
				// are in hex and half are in whatever the #define used.
260 261 262 263 264 265 266 267 268
				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"
269 270
					n.Const = n.Define
				}
271 272 273
			}

			if n.IsConst() {
Russ Cox's avatar
Russ Cox committed
274 275 276 277
				continue
			}
		}

278
		// If this is a struct, union, or enum type name, no need to guess the kind.
Russ Cox's avatar
Russ Cox committed
279 280
		if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
			n.Kind = "type"
281
			needType = append(needType, n)
Russ Cox's avatar
Russ Cox committed
282 283 284
			continue
		}

285 286 287 288 289 290 291 292
		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
		}

293 294
		// Otherwise, we'll need to find out from gcc.
		names = append(names, n)
Russ Cox's avatar
Russ Cox committed
295 296
	}

297 298
	// Bypass gcc if there's nothing left to find out.
	if len(names) == 0 {
Russ Cox's avatar
Russ Cox committed
299 300 301
		return needType
	}

302 303 304 305 306 307 308 309 310 311
	// 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"
312
	//	void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__1; }
313
	//	#line xxx "not-type"
314
	//	void __cgo_f_xxx_2(void) { name *__cgo_undefined__2; }
315
	//	#line xxx "not-int-const"
316
	//	void __cgo_f_xxx_3(void) { enum { __cgo_undefined__3 = (name)*1 }; }
317
	//	#line xxx "not-num-const"
318
	//	void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
319
	//	#line xxx "not-str-lit"
320
	//	void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
321 322 323
	//
	// 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.
324 325 326
	// 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.
327 328 329 330
	//
	// 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
331
	var b bytes.Buffer
332
	b.WriteString(builtinProlog)
333
	b.WriteString(f.Preamble)
334 335 336

	for i, n := range names {
		fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
337
			"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__1; }\n"+
338
			"#line %d \"not-type\"\n"+
339
			"void __cgo_f_%d_2(void) { %s *__cgo_undefined__2; }\n"+
340
			"#line %d \"not-int-const\"\n"+
341
			"void __cgo_f_%d_3(void) { enum { __cgo_undefined__3 = (%s)*1 }; }\n"+
342
			"#line %d \"not-num-const\"\n"+
343
			"void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
344
			"#line %d \"not-str-lit\"\n"+
345
			"void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
346 347
			i+1, i+1, n.C,
			i+1, i+1, n.C,
348 349
			i+1, i+1, n.C,
			i+1, i+1, n.C,
350 351
			i+1, i+1, n.C,
		)
352 353 354 355
	}
	fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
		"int __cgo__1 = __cgo__2;\n")

Russ Cox's avatar
Russ Cox committed
356
	stderr := p.gccErrors(b.Bytes())
357
	if stderr == "" {
358
		fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
Russ Cox's avatar
Russ Cox committed
359 360
	}

361 362 363 364
	completed := false
	sniff := make([]int, len(names))
	const (
		notType = 1 << iota
365 366 367
		notIntConst
		notNumConst
		notStrLiteral
368
		notDeclared
369
	)
370
	sawUnmatchedErrors := false
371
	for _, line := range strings.Split(stderr, "\n") {
372 373 374 375 376 377 378 379 380
		// 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 {
381
			continue
382
		}
383

384
		c1 := strings.Index(line, ":")
385
		if c1 < 0 {
386
			continue
387
		}
388
		c2 := strings.Index(line[c1+1:], ":")
389
		if c2 < 0 {
Russ Cox's avatar
Russ Cox committed
390
			continue
391
		}
392 393 394 395 396 397
		c2 += c1 + 1

		filename := line[:c1]
		i, _ := strconv.Atoi(line[c1+1 : c2])
		i--
		if i < 0 || i >= len(names) {
398 399 400
			if isError {
				sawUnmatchedErrors = true
			}
Russ Cox's avatar
Russ Cox committed
401
			continue
402
		}
Russ Cox's avatar
Russ Cox committed
403

404 405 406 407 408 409 410 411 412
		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":
413
			sniff[i] |= notDeclared
414 415
		case "not-type":
			sniff[i] |= notType
416 417 418 419 420 421
		case "not-int-const":
			sniff[i] |= notIntConst
		case "not-num-const":
			sniff[i] |= notNumConst
		case "not-str-lit":
			sniff[i] |= notStrLiteral
422 423 424 425 426
		default:
			if isError {
				sawUnmatchedErrors = true
			}
			continue
427
		}
428 429

		sawUnmatchedErrors = false
430
	}
431 432

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

	for i, n := range names {
437
		switch sniff[i] {
438
		default:
439 440 441 442 443
			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
			}
444
			error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
445
		case notStrLiteral | notType:
446
			n.Kind = "iconst"
447 448 449 450 451
		case notIntConst | notStrLiteral | notType:
			n.Kind = "fconst"
		case notIntConst | notNumConst | notType:
			n.Kind = "sconst"
		case notIntConst | notNumConst | notStrLiteral:
452
			n.Kind = "type"
453
		case notIntConst | notNumConst | notStrLiteral | notType:
454
			n.Kind = "not-type"
Russ Cox's avatar
Russ Cox committed
455
		}
456
		needType = append(needType, n)
Russ Cox's avatar
Russ Cox committed
457
	}
458
	if nerrors > 0 {
459 460
		// Check if compiling the preamble by itself causes any errors,
		// because the messages we've printed out so far aren't helpful
461
		// to users debugging preamble mistakes. See issue 8442.
462 463 464 465 466
		preambleErrors := p.gccErrors([]byte(f.Preamble))
		if len(preambleErrors) > 0 {
			error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors)
		}

467
		fatalf("unresolved names")
468
	}
469

Russ Cox's avatar
Russ Cox committed
470 471
	return needType
}
472

Russ Cox's avatar
Russ Cox committed
473 474 475 476
// 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.
func (p *Package) loadDWARF(f *File, names []*Name) {
477
	// Extract the types from the DWARF section of an object
478
	// from a well-formed C program. Gcc only generates DWARF info
479 480 481
	// 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
482
	//	__typeof__(names[i]) *__cgo__i;
483 484
	// for each entry in names and then dereference the type we
	// learn for __cgo__i.
Russ Cox's avatar
Russ Cox committed
485
	var b bytes.Buffer
486
	b.WriteString(builtinProlog)
487
	b.WriteString(f.Preamble)
488
	b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
489
	for i, n := range names {
490
		fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
491
		if n.Kind == "iconst" {
Russ Cox's avatar
Russ Cox committed
492 493
			fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
		}
494
	}
495

496 497
	// We create a data block initialized with the values,
	// so we can read them out of the object file.
498
	fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
499
	for _, n := range names {
500
		if n.Kind == "iconst" {
501 502 503 504 505
			fmt.Fprintf(&b, "\t%s,\n", n.C)
		} else {
			fmt.Fprintf(&b, "\t0,\n")
		}
	}
506
	// for the last entry, we cannot use 0, otherwise
507 508 509 510 511
	// 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")
512 513
	fmt.Fprintf(&b, "};\n")

514 515 516 517 518 519 520 521
	// 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")
		}
522
	}
523 524 525
	fmt.Fprintf(&b, "\t1\n")
	fmt.Fprintf(&b, "};\n")

526 527 528 529 530 531 532 533 534
	// 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))
535

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

Russ Cox's avatar
Russ Cox committed
582
	// Record types and typedef information.
583
	var conv typeConv
Russ Cox's avatar
Russ Cox committed
584
	conv.Init(p.PtrSize, p.IntSize)
585 586 587 588 589
	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
590
	for i, n := range names {
591 592 593
		if types[i] == nil {
			continue
		}
594
		pos := f.NamePos[n]
595
		f, fok := types[i].(*dwarf.FuncType)
Russ Cox's avatar
Russ Cox committed
596 597
		if n.Kind != "type" && fok {
			n.Kind = "func"
598
			n.FuncType = conv.FuncType(f, pos)
Russ Cox's avatar
Russ Cox committed
599
		} else {
600
			n.Type = conv.Type(types[i], pos)
601 602 603
			switch n.Kind {
			case "iconst":
				if i < len(ints) {
604 605 606 607 608
					if _, ok := types[i].(*dwarf.UintType); ok {
						n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
					} else {
						n.Const = fmt.Sprintf("%#x", ints[i])
					}
609
				}
610
			case "fconst":
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
				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:
630 631
					n.Const = fmt.Sprintf("%f", floats[i])
				}
632 633 634 635
			case "sconst":
				if i < len(strs) {
					n.Const = fmt.Sprintf("%q", strs[i])
				}
636
			}
Russ Cox's avatar
Russ Cox committed
637
		}
638
		conv.FinishType(pos)
639
	}
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
}

// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
func (p *Package) recordTypedefs(dtype dwarf.Type) {
	p.recordTypedefs1(dtype, map[dwarf.Type]bool{})
}
func (p *Package) recordTypedefs1(dtype dwarf.Type, visited map[dwarf.Type]bool) {
	if dtype == nil {
		return
	}
	if visited[dtype] {
		return
	}
	visited[dtype] = true
	switch dt := dtype.(type) {
	case *dwarf.TypedefType:
656 657 658 659
		if strings.HasPrefix(dt.Name, "__builtin") {
			// Don't look inside builtin types. There be dragons.
			return
		}
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
		if !p.typedefs[dt.Name] {
			p.typedefs[dt.Name] = true
			p.typedefList = append(p.typedefList, dt.Name)
			p.recordTypedefs1(dt.Type, visited)
		}
	case *dwarf.PtrType:
		p.recordTypedefs1(dt.Type, visited)
	case *dwarf.ArrayType:
		p.recordTypedefs1(dt.Type, visited)
	case *dwarf.QualType:
		p.recordTypedefs1(dt.Type, visited)
	case *dwarf.FuncType:
		p.recordTypedefs1(dt.ReturnType, visited)
		for _, a := range dt.ParamType {
			p.recordTypedefs1(a, visited)
		}
	case *dwarf.StructType:
		for _, f := range dt.Field {
			p.recordTypedefs1(f.Type, visited)
		}
	}
681 682
}

683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
// 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)
	}
}

704 705 706 707 708 709 710 711 712 713 714 715 716 717
// 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
}

718 719
// rewriteCalls rewrites all calls that pass pointers to check that
// they follow the rules for passing pointers between Go and C.
720 721 722
// This returns whether the package needs to import unsafe as _cgo_unsafe.
func (p *Package) rewriteCalls(f *File) bool {
	needsUnsafe := false
723 724
	for _, call := range f.Calls {
		// This is a call to C.xxx; set goname to "xxx".
725
		goname := call.Call.Fun.(*ast.SelectorExpr).Sel.Name
726 727 728 729 730 731 732 733
		if goname == "malloc" {
			continue
		}
		name := f.Name[goname]
		if name.Kind != "func" {
			// Probably a type conversion.
			continue
		}
734 735 736
		if p.rewriteCall(f, call, name) {
			needsUnsafe = true
		}
737
	}
738
	return needsUnsafe
739 740
}

741 742 743 744
// 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.
745 746
// This returns whether the package needs to import unsafe as _cgo_unsafe.
func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
747 748 749
	params := name.FuncType.Params
	args := call.Call.Args

750 751 752
	// 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.
753
	if len(args) < len(params) {
754
		return false
755 756
	}

757
	any := false
758 759
	for i, param := range params {
		if p.needsPointerCheck(f, param.Go, args[i]) {
760 761 762 763 764
			any = true
			break
		}
	}
	if !any {
765
		return false
766
	}
767

768 769
	// We need to rewrite this call.
	//
770 771 772 773 774 775 776 777
	// We are going to rewrite C.f(p) to
	//    func (_cgo0 ptype) {
	//            _cgoCheckPointer(_cgo0)
	//            C.f(_cgo0)
	//    }(p)
	// Using a function literal like this lets us do correct
	// argument type checking, and works correctly if the call is
	// deferred.
778 779 780
	var sb bytes.Buffer
	sb.WriteString("func(")

781
	needsUnsafe := false
782 783 784 785 786 787 788 789

	for i, param := range params {
		if i > 0 {
			sb.WriteString(", ")
		}

		fmt.Fprintf(&sb, "_cgo%d ", i)

790 791 792 793
		ptype := p.rewriteUnsafe(param.Go)
		if ptype != param.Go {
			needsUnsafe = true
		}
794 795
		sb.WriteString(gofmtLine(ptype))
	}
796

797
	sb.WriteString(")")
798

799 800
	result := false
	twoResults := false
801

802 803 804 805
	// Check whether this call expects two results.
	for _, ref := range f.Ref {
		if ref.Expr != &call.Call.Fun {
			continue
806
		}
807 808 809 810
		if ref.Context == ctxCall2 {
			sb.WriteString(" (")
			result = true
			twoResults = true
811
		}
812
		break
813 814
	}

815
	// Add the result type, if any.
816
	if name.FuncType.Result != nil {
817 818 819 820
		rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
		if rtype != name.FuncType.Result.Go {
			needsUnsafe = true
		}
821 822
		if !twoResults {
			sb.WriteString(" ")
823
		}
824 825
		sb.WriteString(gofmtLine(rtype))
		result = true
826
	}
827

828 829 830 831 832 833
	// 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")
834
		}
835
		sb.WriteString(", error)")
836
	}
837

838 839 840 841 842 843
	sb.WriteString(" { ")

	for i, param := range params {
		arg := args[i]
		if !p.needsPointerCheck(f, param.Go, arg) {
			continue
844
		}
845 846 847 848

		// Check for &a[i].
		if p.checkIndex(&sb, f, arg, i) {
			continue
849
		}
850 851 852 853 854 855 856

		// Check for &x.
		if p.checkAddr(&sb, arg, i) {
			continue
		}

		fmt.Fprintf(&sb, "_cgoCheckPointer(_cgo%d); ", i)
857
	}
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875

	if result {
		sb.WriteString("return ")
	}

	// Now we are ready to call the C function.
	// To work smoothly with rewriteRef we leave the call in place
	// and just insert our new arguments between the function
	// and the old arguments.
	f.Edit.Insert(f.offset(call.Call.Fun.Pos()), sb.String())

	sb.Reset()
	sb.WriteString("(")
	for i := range params {
		if i > 0 {
			sb.WriteString(", ")
		}
		fmt.Fprintf(&sb, "_cgo%d", i)
876
	}
877 878 879
	sb.WriteString("); }")

	f.Edit.Insert(f.offset(call.Call.Lparen), sb.String())
880

881
	return needsUnsafe
882 883 884 885 886
}

// needsPointerCheck returns whether the type t needs a pointer check.
// This is true if t is a pointer and if the value to which it points
// might contain a pointer.
887 888 889 890 891 892 893 894 895
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
	}

896 897 898
	return p.hasPointer(f, t, true)
}

899
// hasPointer is used by needsPointerCheck. If top is true it returns
900 901
// whether t is or contains a pointer that might point to a pointer.
// If top is false it returns whether t is or contains a pointer.
902
// f may be nil.
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
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
		}
924 925 926 927 928
		// Check whether this is a pointer to a C union (or class)
		// type that contains a pointer.
		if unionWithPointer[t.X] {
			return true
		}
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
		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
		}
961
		// We can't figure out the type. Conservative
962 963 964 965 966 967 968 969 970
		// 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
		}
971 972 973 974
		if f == nil {
			// Conservative approach: assume pointer.
			return true
		}
975 976 977 978
		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)
		}
979
		// We can't figure out the type. Conservative
980 981 982 983 984 985 986 987
		// approach is to assume it has a pointer.
		return true
	default:
		error_(t.Pos(), "could not understand type %s", gofmt(t))
		return true
	}
}

988 989 990 991 992
// checkIndex checks whether arg the form &a[i], possibly inside type
// conversions. If so, and if a has no side effects, it writes
// _cgoCheckPointer(_cgoNN, a) to sb and returns true. This tells
// _cgoCheckPointer to check the complete contents of the slice.
func (p *Package) checkIndex(sb *bytes.Buffer, f *File, arg ast.Expr, i int) bool {
993
	// Strip type conversions.
994
	x := arg
995 996 997 998 999 1000 1001 1002 1003
	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 {
1004
		return false
1005 1006
	}
	index, ok := u.X.(*ast.IndexExpr)
1007
	if !ok {
1008
		return false
1009
	}
1010 1011
	if p.hasSideEffects(f, index.X) {
		return false
1012
	}
1013 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

	fmt.Fprintf(sb, "_cgoCheckPointer(_cgo%d, %s); ", i, gofmtLine(index.X))

	return true
}

// checkAddr checks whether arg has the form &x, possibly inside type
// conversions. If so it writes _cgoCheckPointer(_cgoNN, true) to sb
// 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 *bytes.Buffer, arg ast.Expr, i int) bool {
	// 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
	}

	// Use "0 == 0" to do the right thing in the unlikely event
	// that "true" is shadowed.
	fmt.Fprintf(sb, "_cgoCheckPointer(_cgo%d, 0 == 0); ", i)

	return true
1044 1045 1046 1047 1048 1049 1050
}

// hasSideEffects returns whether the expression x has any side
// effects.  x is an expression, not a statement, so the only side
// effect is a function call.
func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
	found := false
1051 1052
	f.walk(x, ctxExpr,
		func(f *File, x interface{}, context astContext) {
1053
			if _, ok := x.(*ast.CallExpr); ok {
1054 1055 1056 1057 1058 1059
				found = true
			}
		})
	return found
}

1060 1061 1062 1063 1064 1065 1066 1067 1068
// isType returns whether the expression is definitely a type.
// 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
		}
1069 1070 1071 1072 1073 1074 1075
		if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
			return true
		}
		if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
			return true
		}
		return false
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
	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
		}
	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
}

1099 1100 1101
// 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 {
1102 1103
	switch t := t.(type) {
	case *ast.Ident:
1104 1105
		// We don't see a SelectorExpr for unsafe.Pointer;
		// this is created by code in this file.
1106 1107 1108
		if t.Name == "unsafe.Pointer" {
			return ast.NewIdent("_cgo_unsafe.Pointer")
		}
1109
	case *ast.ArrayType:
1110 1111 1112 1113 1114 1115
		t1 := p.rewriteUnsafe(t.Elt)
		if t1 != t.Elt {
			r := *t
			r.Elt = t1
			return &r
		}
1116
	case *ast.StructType:
1117 1118 1119
		changed := false
		fields := *t.Fields
		fields.List = nil
1120
		for _, f := range t.Fields.List {
1121 1122 1123 1124 1125 1126 1127 1128
			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
1129 1130
			}
		}
1131 1132 1133 1134 1135
		if changed {
			r := *t
			r.Fields = &fields
			return &r
		}
1136
	case *ast.StarExpr: // Pointer type.
1137 1138 1139 1140 1141 1142
		x1 := p.rewriteUnsafe(t.X)
		if x1 != t.X {
			r := *t
			r.X = x1
			return &r
		}
1143
	}
1144
	return t
1145 1146
}

Russ Cox's avatar
Russ Cox committed
1147 1148
// 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
1149
// the xxx. In *godefs mode, rewriteRef replaces the names
1150
// with full definitions instead of mangled names.
Russ Cox's avatar
Russ Cox committed
1151
func (p *Package) rewriteRef(f *File) {
1152 1153 1154 1155 1156
	// 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
1157
	for _, n := range f.Name {
1158 1159
		if n.Kind == "func" {
			functions[n.Go] = false
Russ Cox's avatar
Russ Cox committed
1160
		}
Russ Cox's avatar
Russ Cox committed
1161
	}
Russ Cox's avatar
Russ Cox committed
1162 1163 1164

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

1172 1173 1174 1175
		if r.Name.Kind == "func" {
			switch r.Context {
			case ctxCall, ctxCall2:
				functions[r.Name.Go] = true
Russ Cox's avatar
Russ Cox committed
1176 1177
			}
		}
1178

1179 1180
		expr := p.rewriteName(f, r)

1181
		if *godefs {
1182 1183 1184
			// 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
1185
					expr = t.Go
1186 1187 1188 1189 1190 1191
				}
				if id.Name == r.Name.Mangle && r.Name.Const != "" {
					expr = ast.NewIdent(r.Name.Const)
				}
			}
		}
1192 1193 1194 1195 1196

		// 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()
1197
		if x, ok := expr.(*ast.Ident); ok {
1198 1199 1200
			expr = &ast.Ident{NamePos: pos, Name: x.Name}
		}

1201 1202 1203
		// 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
1204
		*r.Expr = expr
1205 1206 1207 1208 1209 1210 1211

		// Record source-level edit for cgo output.
		repl := gofmt(expr)
		if r.Name.Kind != "type" {
			repl = "(" + repl + ")"
		}
		f.Edit.Replace(f.offset(old.Pos()), f.offset(old.End()), repl)
Russ Cox's avatar
Russ Cox committed
1212
	}
1213 1214 1215 1216 1217 1218 1219 1220

	// 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
1221 1222
}

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
// 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
}

1324 1325 1326 1327 1328
// 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
1329
	// Use $CC if set, since that's what the build uses.
1330
	if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
Russ Cox's avatar
Russ Cox committed
1331
		return ret
1332
	}
1333 1334
	// 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
1335 1336
		return ret
	}
1337
	return strings.Fields(defaultCC(goos, goarch))
1338 1339
}

Shenghou Ma's avatar
Shenghou Ma committed
1340
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1341
func (p *Package) gccMachine() []string {
1342
	switch goarch {
1343 1344 1345 1346
	case "amd64":
		return []string{"-m64"}
	case "386":
		return []string{"-m32"}
Shenghou Ma's avatar
Shenghou Ma committed
1347
	case "arm":
1348
		return []string{"-marm"} // not thumb
1349 1350 1351 1352
	case "s390":
		return []string{"-m31"}
	case "s390x":
		return []string{"-m64"}
1353 1354
	case "mips64", "mips64le":
		return []string{"-mabi=64"}
1355 1356
	case "mips", "mipsle":
		return []string{"-mabi=32"}
1357 1358
	}
	return nil
Russ Cox's avatar
Russ Cox committed
1359
}
1360

Russ Cox's avatar
Russ Cox committed
1361 1362 1363
func gccTmp() string {
	return *objDir + "_cgo_.o"
}
Russ Cox's avatar
Russ Cox committed
1364 1365 1366 1367

// gccCmd returns the gcc command line to use for compiling
// the input.
func (p *Package) gccCmd() []string {
1368
	c := append(p.gccBaseCmd(),
1369 1370 1371 1372 1373 1374
		"-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
1375
	)
1376
	if p.GccIsClang {
Russ Cox's avatar
Russ Cox committed
1377 1378
		c = append(c,
			"-ferror-limit=0",
1379 1380 1381 1382
			// 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
1383
			"-Wno-unneeded-internal-declaration",
1384 1385
			"-Wno-unused-function",
			"-Qunused-arguments",
1386 1387 1388 1389 1390
			// 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).
1391
			// See: https://golang.org/issue/6506.
1392
			"-fno-builtin",
Russ Cox's avatar
Russ Cox committed
1393 1394 1395
		)
	}

1396
	c = append(c, p.GccOptions...)
1397
	c = append(c, p.gccMachine()...)
1398 1399
	c = append(c, "-") //read input from standard input
	return c
Russ Cox's avatar
Russ Cox committed
1400 1401 1402
}

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

1407
	isDebugInts := func(s string) bool {
1408
		// Some systems use leading _ to denote non-assembly symbols.
1409 1410 1411 1412 1413
		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"
1414
	}
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
	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")
			}
1451
			strs[n] = data[:strlen]
1452 1453
		}
	}
1454

Russ Cox's avatar
Russ Cox committed
1455
	if f, err := macho.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1456
		defer f.Close()
1457 1458
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1459
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1460
		}
1461
		bo := f.ByteOrder
1462 1463 1464
		if f.Symtab != nil {
			for i := range f.Symtab.Syms {
				s := &f.Symtab.Syms[i]
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480
				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):
1481
					// Found it. Now find data section.
1482 1483 1484 1485
					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 {
1486 1487 1488 1489 1490
								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:]))
								}
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
				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
					}
1525
				}
1526
			}
1527 1528

			buildStrings()
1529
		}
1530
		return d, ints, floats, strs
1531 1532
	}

Russ Cox's avatar
Russ Cox committed
1533
	if f, err := elf.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1534
		defer f.Close()
1535 1536
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1537
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1538
		}
1539
		bo := f.ByteOrder
1540 1541 1542 1543
		symtab, err := f.Symbols()
		if err == nil {
			for i := range symtab {
				s := &symtab[i]
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
				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):
1560
					// Found it. Now find data section.
1561 1562 1563 1564
					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 {
1565 1566 1567 1568 1569
								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:]))
								}
1570 1571 1572
							}
						}
					}
1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603
				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
					}
1604 1605
				}
			}
1606 1607

			buildStrings()
1608
		}
1609
		return d, ints, floats, strs
1610
	}
1611

Russ Cox's avatar
Russ Cox committed
1612
	if f, err := pe.Open(gccTmp()); err == nil {
Dave Cheney's avatar
Dave Cheney committed
1613
		defer f.Close()
1614 1615
		d, err := f.DWARF()
		if err != nil {
Russ Cox's avatar
Russ Cox committed
1616
			fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1617
		}
1618
		bo := binary.LittleEndian
1619
		for _, s := range f.Symbols {
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
			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):
1635 1636 1637 1638
				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 {
1639 1640 1641 1642 1643
							data := sdat[s.Value:]
							floats = make([]float64, len(data)/8)
							for i := range floats {
								floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
							}
1644 1645 1646
						}
					}
				}
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675
			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
				}
1676 1677
			}
		}
1678 1679 1680 1681

		buildStrings()

		return d, ints, floats, strs
1682 1683
	}

Russ Cox's avatar
Russ Cox committed
1684
	fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
1685
	panic("not reached")
1686 1687
}

Russ Cox's avatar
Russ Cox committed
1688 1689 1690 1691 1692
// 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 {
1693
	base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
1694
	base = append(base, p.gccMachine()...)
1695
	stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
Russ Cox's avatar
Russ Cox committed
1696 1697 1698 1699
	return stdout
}

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

1706 1707 1708 1709 1710 1711 1712 1713
	// 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)
		}
	}

1714 1715 1716
	// Force -O0 optimization
	nargs = append(nargs, "-O0")

Russ Cox's avatar
Russ Cox committed
1717
	if *debugGcc {
1718
		fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
Russ Cox's avatar
Russ Cox committed
1719 1720 1721
		os.Stderr.Write(stdin)
		fmt.Fprint(os.Stderr, "EOF\n")
	}
1722
	stdout, stderr, _ := run(stdin, nargs)
Russ Cox's avatar
Russ Cox committed
1723 1724 1725
	if *debugGcc {
		os.Stderr.Write(stdout)
		os.Stderr.Write(stderr)
1726
	}
Russ Cox's avatar
Russ Cox committed
1727 1728
	return string(stderr)
}
1729

Russ Cox's avatar
Russ Cox committed
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746
// 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)
	}
1747
	if !ok {
Russ Cox's avatar
Russ Cox committed
1748 1749
		os.Stderr.Write(stderr)
		os.Exit(2)
1750
	}
Russ Cox's avatar
Russ Cox committed
1751
	return string(stdout), string(stderr)
1752 1753
}

Russ Cox's avatar
Russ Cox committed
1754 1755 1756 1757
// 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.
1758
	m map[dwarf.Type]*Type
Russ Cox's avatar
Russ Cox committed
1759

1760 1761
	// Map from types to incomplete pointers to those types.
	ptrs map[dwarf.Type][]*Type
1762
	// Keys of ptrs in insertion order (deterministic worklist)
1763
	// ptrKeys contains exactly the keys in ptrs.
1764
	ptrKeys []dwarf.Type
1765

1766 1767 1768
	// 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
1769
	// Predeclared types.
Devon H. O'Dell's avatar
Devon H. O'Dell committed
1770
	bool                                   ast.Expr
1771 1772 1773 1774
	byte                                   ast.Expr // denotes padding
	int8, int16, int32, int64              ast.Expr
	uint8, uint16, uint32, uint64, uintptr ast.Expr
	float32, float64                       ast.Expr
1775
	complex64, complex128                  ast.Expr
1776 1777
	void                                   ast.Expr
	string                                 ast.Expr
1778
	goVoid                                 ast.Expr // _Ctype_void, denotes C's void
1779
	goVoidPtr                              ast.Expr // unsafe.Pointer or *byte
Russ Cox's avatar
Russ Cox committed
1780

1781
	ptrSize int64
Russ Cox's avatar
Russ Cox committed
1782
	intSize int64
Russ Cox's avatar
Russ Cox committed
1783 1784
}

1785
var tagGen int
Russ Cox's avatar
Russ Cox committed
1786
var typedef = make(map[string]*Type)
1787
var goIdent = make(map[string]*ast.Ident)
1788

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

Russ Cox's avatar
Russ Cox committed
1793
func (c *typeConv) Init(ptrSize, intSize int64) {
1794
	c.ptrSize = ptrSize
Russ Cox's avatar
Russ Cox committed
1795
	c.intSize = intSize
1796
	c.m = make(map[dwarf.Type]*Type)
1797
	c.ptrs = make(map[dwarf.Type][]*Type)
1798
	c.getTypeIDs = make(map[string]bool)
Devon H. O'Dell's avatar
Devon H. O'Dell committed
1799
	c.bool = c.Ident("bool")
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811
	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")
1812 1813
	c.complex64 = c.Ident("complex64")
	c.complex128 = c.Ident("complex128")
1814 1815
	c.void = c.Ident("void")
	c.string = c.Ident("string")
1816
	c.goVoid = c.Ident("_Ctype_void")
1817 1818

	// Normally cgo translates void* to unsafe.Pointer,
1819 1820
	// but for historical reasons -godefs uses *byte instead.
	if *godefs {
1821 1822 1823 1824
		c.goVoidPtr = &ast.StarExpr{X: c.byte}
	} else {
		c.goVoidPtr = c.Ident("unsafe.Pointer")
	}
Russ Cox's avatar
Russ Cox committed
1825 1826 1827 1828 1829 1830
}

// 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 {
1831 1832
			dt = d.Type
			continue
Russ Cox's avatar
Russ Cox committed
1833 1834
		}
		if d, ok := dt.(*dwarf.TypedefType); ok {
1835 1836
			dt = d.Type
			continue
Russ Cox's avatar
Russ Cox committed
1837
		}
1838
		break
Russ Cox's avatar
Russ Cox committed
1839
	}
1840
	return dt
Russ Cox's avatar
Russ Cox committed
1841 1842
}

1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
// 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
1856
// Map from dwarf text names to aliases we use in package "C".
Russ Cox's avatar
Russ Cox committed
1857
var dwarfToName = map[string]string{
1858 1859 1860 1861
	"long int":               "long",
	"long unsigned int":      "ulong",
	"unsigned int":           "uint",
	"short unsigned int":     "ushort",
1862
	"unsigned short":         "ushort", // Used by Clang; issue 13129.
1863 1864
	"short int":              "short",
	"long long int":          "longlong",
Russ Cox's avatar
Russ Cox committed
1865
	"long long unsigned int": "ulonglong",
1866
	"signed char":            "schar",
1867
	"unsigned char":          "uchar",
Robert Griesemer's avatar
Robert Griesemer committed
1868
}
Russ Cox's avatar
Russ Cox committed
1869

1870 1871
const signedDelta = 64

1872
// String returns the current type representation. Format arguments
1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
// 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...)
}

1885
// Empty reports whether the result of String would be "".
1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897
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
}

1898
// FinishType completes any outstanding type mapping work.
1899
// In particular, it resolves incomplete pointer types.
1900 1901 1902
func (c *typeConv) FinishType(pos token.Pos) {
	// Completing one pointer type might produce more to complete.
	// Keep looping until they're all done.
1903 1904 1905
	for len(c.ptrKeys) > 0 {
		dtype := c.ptrKeys[0]
		c.ptrKeys = c.ptrKeys[1:]
1906 1907
		ptrs := c.ptrs[dtype]
		delete(c.ptrs, dtype)
1908 1909 1910

		// Note Type might invalidate c.ptrs[dtype].
		t := c.Type(dtype, pos)
1911
		for _, ptr := range ptrs {
1912 1913
			ptr.Go.(*ast.StarExpr).X = t.Go
			ptr.C.Set("%s*", t.C)
1914 1915 1916 1917
		}
	}
}

Russ Cox's avatar
Russ Cox committed
1918 1919
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
1920
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
Russ Cox's avatar
Russ Cox committed
1921 1922
	if t, ok := c.m[dtype]; ok {
		if t.Go == nil {
1923
			fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
Russ Cox's avatar
Russ Cox committed
1924
		}
1925
		return t
Russ Cox's avatar
Russ Cox committed
1926 1927
	}

1928
	t := new(Type)
1929
	t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
1930
	t.Align = -1
1931
	t.C = &TypeRepr{Repr: dtype.Common().Name}
1932
	c.m[dtype] = t
Russ Cox's avatar
Russ Cox committed
1933

Russ Cox's avatar
Russ Cox committed
1934 1935
	switch dt := dtype.(type) {
	default:
1936
		fatalf("%s: unexpected type: %s", lineno(pos), dtype)
Russ Cox's avatar
Russ Cox committed
1937 1938 1939

	case *dwarf.AddrType:
		if t.Size != c.ptrSize {
1940
			fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
1941
		}
1942 1943
		t.Go = c.uintptr
		t.Align = t.Size
Russ Cox's avatar
Russ Cox committed
1944 1945 1946 1947

	case *dwarf.ArrayType:
		if dt.StrideBitSize > 0 {
			// Cannot represent bit-sized elements in Go.
1948 1949
			t.Go = c.Opaque(t.Size)
			break
Russ Cox's avatar
Russ Cox committed
1950
		}
1951 1952 1953 1954 1955 1956
		count := dt.Count
		if count == -1 {
			// Indicates flexible array member, which Go doesn't support.
			// Translate to zero-length array instead.
			count = 0
		}
1957
		sub := c.Type(dt.Type, pos)
1958
		t.Align = sub.Align
1959
		t.Go = &ast.ArrayType{
1960
			Len: c.intExpr(count),
1961 1962
			Elt: sub.Go,
		}
1963 1964
		// Recalculate t.Size now that we know sub.Size.
		t.Size = count * sub.Size
1965
		t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
Russ Cox's avatar
Russ Cox committed
1966

Devon H. O'Dell's avatar
Devon H. O'Dell committed
1967 1968
	case *dwarf.BoolType:
		t.Go = c.bool
1969
		t.Align = 1
Devon H. O'Dell's avatar
Devon H. O'Dell committed
1970

Russ Cox's avatar
Russ Cox committed
1971 1972
	case *dwarf.CharType:
		if t.Size != 1 {
1973
			fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
1974
		}
1975 1976
		t.Go = c.int8
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
1977 1978

	case *dwarf.EnumType:
1979 1980 1981
		if t.Align = t.Size; t.Align >= c.ptrSize {
			t.Align = c.ptrSize
		}
1982
		t.C.Set("enum " + dt.EnumName)
1983 1984 1985 1986 1987 1988 1989 1990 1991
		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
1992
		default:
1993
			fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
1994
		case 1:
1995
			t.Go = c.uint8
Russ Cox's avatar
Russ Cox committed
1996
		case 2:
1997
			t.Go = c.uint16
Russ Cox's avatar
Russ Cox committed
1998
		case 4:
1999
			t.Go = c.uint32
Russ Cox's avatar
Russ Cox committed
2000
		case 8:
2001
			t.Go = c.uint64
2002 2003 2004 2005 2006 2007 2008 2009
		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
2010
		}
Russ Cox's avatar
Russ Cox committed
2011 2012 2013 2014

	case *dwarf.FloatType:
		switch t.Size {
		default:
2015
			fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2016
		case 4:
2017
			t.Go = c.float32
Russ Cox's avatar
Russ Cox committed
2018
		case 8:
2019
			t.Go = c.float64
Russ Cox's avatar
Russ Cox committed
2020 2021
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2022
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2023 2024
		}

2025 2026 2027
	case *dwarf.ComplexType:
		switch t.Size {
		default:
2028
			fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
2029 2030 2031 2032 2033
		case 8:
			t.Go = c.complex64
		case 16:
			t.Go = c.complex128
		}
2034
		if t.Align = t.Size / 2; t.Align >= c.ptrSize {
2035 2036 2037
			t.Align = c.ptrSize
		}

Russ Cox's avatar
Russ Cox committed
2038 2039 2040
	case *dwarf.FuncType:
		// No attempt at translation: would enable calls
		// directly between worlds, but we need to moderate those.
2041 2042
		t.Go = c.uintptr
		t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2043 2044 2045

	case *dwarf.IntType:
		if dt.BitSize > 0 {
2046
			fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
Russ Cox's avatar
Russ Cox committed
2047 2048 2049
		}
		switch t.Size {
		default:
2050
			fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2051
		case 1:
2052
			t.Go = c.int8
Russ Cox's avatar
Russ Cox committed
2053
		case 2:
2054
			t.Go = c.int16
Russ Cox's avatar
Russ Cox committed
2055
		case 4:
2056
			t.Go = c.int32
Russ Cox's avatar
Russ Cox committed
2057
		case 8:
2058
			t.Go = c.int64
2059 2060 2061 2062 2063
		case 16:
			t.Go = &ast.ArrayType{
				Len: c.intExpr(t.Size),
				Elt: c.uint8,
			}
Russ Cox's avatar
Russ Cox committed
2064 2065
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2066
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2067 2068 2069
		}

	case *dwarf.PtrType:
2070 2071 2072 2073 2074
		// 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
2075
		t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2076 2077

		if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
2078
			t.Go = c.goVoidPtr
2079
			t.C.Set("void*")
2080 2081 2082 2083 2084 2085 2086 2087 2088
			dq := dt.Type
			for {
				if d, ok := dq.(*dwarf.QualType); ok {
					t.C.Set(d.Qual + " " + t.C.String())
					dq = d.Type
				} else {
					break
				}
			}
2089
			break
Russ Cox's avatar
Russ Cox committed
2090 2091
		}

2092 2093 2094
		// Placeholder initialization; completed in FinishType.
		t.Go = &ast.StarExpr{}
		t.C.Set("<incomplete>*")
2095 2096 2097
		if _, ok := c.ptrs[dt.Type]; !ok {
			c.ptrKeys = append(c.ptrKeys, dt.Type)
		}
2098
		c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
Russ Cox's avatar
Russ Cox committed
2099 2100

	case *dwarf.QualType:
2101 2102 2103 2104
		t1 := c.Type(dt.Type, pos)
		t.Size = t1.Size
		t.Align = t1.Align
		t.Go = t1.Go
2105 2106 2107
		if unionWithPointer[t1.Go] {
			unionWithPointer[t.Go] = true
		}
2108 2109 2110
		t.EnumValues = nil
		t.Typedef = ""
		t.C.Set("%s "+dt.Qual, t1.C)
2111
		return t
Russ Cox's avatar
Russ Cox committed
2112 2113 2114 2115

	case *dwarf.StructType:
		// Convert to Go struct, being careful about alignment.
		// Have to give it a name to simulate C "struct foo" references.
2116
		tag := dt.StructName
2117 2118 2119
		if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
			break
		}
Russ Cox's avatar
Russ Cox committed
2120
		if tag == "" {
2121 2122
			tag = "__" + strconv.Itoa(tagGen)
			tagGen++
2123 2124
		} else if t.C.Empty() {
			t.C.Set(dt.Kind + " " + tag)
Russ Cox's avatar
Russ Cox committed
2125
		}
Russ Cox's avatar
Russ Cox committed
2126
		name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
2127
		t.Go = name // publish before recursive calls
2128
		goIdent[name.Name] = name
2129 2130 2131 2132 2133 2134 2135 2136 2137 2138
		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
2139
		switch dt.Kind {
2140
		case "class", "union":
2141
			t.Go = c.Opaque(t.Size)
2142 2143 2144
			if c.dwarfHasPointer(dt, pos) {
				unionWithPointer[t.Go] = true
			}
2145
			if t.C.Empty() {
2146
				t.C.Set("__typeof__(unsigned char[%d])", t.Size)
Russ Cox's avatar
Russ Cox committed
2147
			}
2148
			t.Align = 1 // TODO: should probably base this on field alignment.
Russ Cox's avatar
Russ Cox committed
2149
			typedef[name.Name] = t
Russ Cox's avatar
Russ Cox committed
2150
		case "struct":
2151
			g, csyntax, align := c.Struct(dt, pos)
2152 2153
			if t.C.Empty() {
				t.C.Set(csyntax)
Russ Cox's avatar
Russ Cox committed
2154
			}
2155
			t.Align = align
Russ Cox's avatar
Russ Cox committed
2156 2157 2158 2159 2160 2161
			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
2162 2163 2164 2165 2166 2167 2168 2169
		}

	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.
2170 2171 2172 2173 2174
			t.Go = c.string
			t.Size = c.ptrSize * 2
			t.Align = c.ptrSize
			break
		}
Russ Cox's avatar
Russ Cox committed
2175 2176 2177 2178 2179 2180 2181 2182
		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
		}
2183 2184
		name := c.Ident("_Ctype_" + dt.Name)
		goIdent[name.Name] = name
2185
		sub := c.Type(dt.Type, pos)
2186
		if c.badPointerTypedef(dt) {
2187 2188 2189 2190
			// Treat this typedef as a uintptr.
			s := *sub
			s.Go = c.uintptr
			sub = &s
2191 2192 2193 2194
			// Make sure we update any previously computed type.
			if oldType := typedef[name.Name]; oldType != nil {
				oldType.Go = sub.Go
			}
2195
		}
2196
		t.Go = name
2197 2198 2199
		if unionWithPointer[sub.Go] {
			unionWithPointer[t.Go] = true
		}
2200 2201
		t.Size = sub.Size
		t.Align = sub.Align
2202 2203
		oldType := typedef[name.Name]
		if oldType == nil {
Russ Cox's avatar
Russ Cox committed
2204 2205 2206
			tt := *t
			tt.Go = sub.Go
			typedef[name.Name] = &tt
Russ Cox's avatar
Russ Cox committed
2207
		}
2208 2209 2210 2211

		// 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.
2212 2213
		// In -godefs mode, do this for all typedefs.
		if isStructUnionClass(sub.Go) || *godefs {
2214
			t.Go = sub.Go
2215

2216 2217 2218 2219 2220
			if isStructUnionClass(sub.Go) {
				// Use the typedef name for C code.
				typedef[sub.Go.(*ast.Ident).Name].C = t.C
			}

2221 2222 2223 2224 2225 2226 2227 2228
			// 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
			}
2229
		}
Russ Cox's avatar
Russ Cox committed
2230 2231 2232

	case *dwarf.UcharType:
		if t.Size != 1 {
2233
			fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2234
		}
2235 2236
		t.Go = c.uint8
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
2237 2238 2239

	case *dwarf.UintType:
		if dt.BitSize > 0 {
2240
			fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
Russ Cox's avatar
Russ Cox committed
2241 2242 2243
		}
		switch t.Size {
		default:
2244
			fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
Russ Cox's avatar
Russ Cox committed
2245
		case 1:
2246
			t.Go = c.uint8
Russ Cox's avatar
Russ Cox committed
2247
		case 2:
2248
			t.Go = c.uint16
Russ Cox's avatar
Russ Cox committed
2249
		case 4:
2250
			t.Go = c.uint32
Russ Cox's avatar
Russ Cox committed
2251
		case 8:
2252
			t.Go = c.uint64
2253 2254 2255 2256 2257
		case 16:
			t.Go = &ast.ArrayType{
				Len: c.intExpr(t.Size),
				Elt: c.uint8,
			}
Russ Cox's avatar
Russ Cox committed
2258 2259
		}
		if t.Align = t.Size; t.Align >= c.ptrSize {
2260
			t.Align = c.ptrSize
Russ Cox's avatar
Russ Cox committed
2261 2262 2263
		}

	case *dwarf.VoidType:
2264
		t.Go = c.goVoid
2265
		t.C.Set("void")
2266
		t.Align = 1
Russ Cox's avatar
Russ Cox committed
2267 2268 2269
	}

	switch dtype.(type) {
2270
	case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
2271
		s := dtype.Common().Name
Russ Cox's avatar
Russ Cox committed
2272
		if s != "" {
Russ Cox's avatar
Russ Cox committed
2273
			if ss, ok := dwarfToName[s]; ok {
2274
				s = ss
Russ Cox's avatar
Russ Cox committed
2275
			}
2276
			s = strings.Replace(s, " ", "", -1)
Russ Cox's avatar
Russ Cox committed
2277
			name := c.Ident("_Ctype_" + s)
Russ Cox's avatar
Russ Cox committed
2278 2279
			tt := *t
			typedef[name.Name] = &tt
2280
			if !*godefs {
2281 2282
				t.Go = name
			}
Russ Cox's avatar
Russ Cox committed
2283 2284 2285
		}
	}

2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296
	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
2297
			}
2298 2299 2300 2301 2302 2303
			t.Go = c.Opaque(0)
		default:
			t.Go = c.Opaque(0)
		}
		if t.C.Empty() {
			t.C.Set("void")
2304 2305 2306
		}
	}

2307
	if t.C.Empty() {
2308
		fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
Russ Cox's avatar
Russ Cox committed
2309 2310
	}

2311
	return t
Russ Cox's avatar
Russ Cox committed
2312 2313
}

2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326
// 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
2327 2328
// FuncArg returns a Go type with the same memory layout as
// dtype when used as the type of a C function argument.
2329
func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
2330
	t := c.Type(unqual(dtype), pos)
Russ Cox's avatar
Russ Cox committed
2331 2332 2333 2334
	switch dt := dtype.(type) {
	case *dwarf.ArrayType:
		// Arrays are passed implicitly as pointers in C.
		// In Go, we must be explicit.
2335 2336
		tr := &TypeRepr{}
		tr.Set("%s*", t.C)
Russ Cox's avatar
Russ Cox committed
2337
		return &Type{
2338
			Size:  c.ptrSize,
Russ Cox's avatar
Russ Cox committed
2339
			Align: c.ptrSize,
2340
			Go:    &ast.StarExpr{X: t.Go},
2341
			C:     tr,
2342
		}
Russ Cox's avatar
Russ Cox committed
2343 2344
	case *dwarf.TypedefType:
		// C has much more relaxed rules than Go for
2345
		// implicit type conversions. When the parameter
Russ Cox's avatar
Russ Cox committed
2346 2347 2348
		// 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 {
2349 2350
			// Unless the typedef happens to point to void* since
			// Go has special rules around using unsafe.Pointer.
Russ Cox's avatar
Russ Cox committed
2351 2352
			if _, void := base(ptr.Type).(*dwarf.VoidType); void {
				break
2353
			}
2354 2355
			// ...or the typedef is one in which we expect bad pointers.
			// It will be a uintptr instead of *X.
2356
			if c.baseBadPointerTypedef(dt) {
2357 2358
				break
			}
Russ Cox's avatar
Russ Cox committed
2359 2360 2361 2362 2363 2364

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

2365 2366 2367 2368 2369 2370
			// 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
2371 2372
		}
	}
2373
	return t
Russ Cox's avatar
Russ Cox committed
2374 2375 2376 2377
}

// FuncType returns the Go type analogous to dtype.
// There is no guarantee about matching memory layout.
2378
func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
2379 2380
	p := make([]*Type, len(dtype.ParamType))
	gp := make([]*ast.Field, len(dtype.ParamType))
Russ Cox's avatar
Russ Cox committed
2381
	for i, f := range dtype.ParamType {
2382 2383
		// gcc's DWARF generator outputs a single DotDotDotType parameter for
		// function pointers that specify no parameters (e.g. void
2384
		// (*__cgo_0)()).  Treat this special case as void. This case is
2385 2386 2387
		// invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
		// legal).
		if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
2388 2389
			p, gp = nil, nil
			break
2390
		}
2391
		p[i] = c.FuncArg(f, pos)
2392
		gp[i] = &ast.Field{Type: p[i].Go}
Russ Cox's avatar
Russ Cox committed
2393
	}
2394 2395
	var r *Type
	var gr []*ast.Field
2396
	if _, ok := base(dtype.ReturnType).(*dwarf.VoidType); ok {
2397 2398
		gr = []*ast.Field{{Type: c.goVoid}}
	} else if dtype.ReturnType != nil {
2399
		r = c.Type(unqual(dtype.ReturnType), pos)
Russ Cox's avatar
Russ Cox committed
2400
		gr = []*ast.Field{{Type: r.Go}}
Russ Cox's avatar
Russ Cox committed
2401 2402 2403 2404 2405
	}
	return &FuncType{
		Params: p,
		Result: r,
		Go: &ast.FuncType{
2406
			Params:  &ast.FieldList{List: gp},
2407
			Results: &ast.FieldList{List: gr},
Robert Griesemer's avatar
Robert Griesemer committed
2408
		},
2409
	}
Russ Cox's avatar
Russ Cox committed
2410 2411 2412
}

// Identifier
Russ Cox's avatar
Russ Cox committed
2413 2414 2415
func (c *typeConv) Ident(s string) *ast.Ident {
	return ast.NewIdent(s)
}
Russ Cox's avatar
Russ Cox committed
2416 2417 2418 2419 2420

// 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
2421
		Elt: c.byte,
2422
	}
Russ Cox's avatar
Russ Cox committed
2423 2424 2425 2426 2427
}

// Expr for integer n.
func (c *typeConv) intExpr(n int64) ast.Expr {
	return &ast.BasicLit{
2428
		Kind:  token.INT,
Russ Cox's avatar
Russ Cox committed
2429
		Value: strconv.FormatInt(n, 10),
2430
	}
Russ Cox's avatar
Russ Cox committed
2431 2432 2433
}

// Add padding of given size to fld.
2434
func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
2435 2436 2437
	n := len(fld)
	fld = fld[0 : n+1]
	fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
2438 2439 2440
	sizes = sizes[0 : n+1]
	sizes[n] = size
	return fld, sizes
Russ Cox's avatar
Russ Cox committed
2441 2442
}

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

Russ Cox's avatar
Russ Cox committed
2448 2449
	var buf bytes.Buffer
	buf.WriteString("struct {")
2450
	fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
2451
	sizes := make([]int64, 0, 2*len(dt.Field)+1)
2452
	off := int64(0)
2453

Russ Cox's avatar
Russ Cox committed
2454
	// Rename struct fields that happen to be named Go keywords into
2455 2456
	// _{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
2457 2458 2459
	// 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).
2460 2461
	ident := make(map[string]string)
	used := make(map[string]bool)
2462
	for _, f := range dt.Field {
2463 2464
		ident[f.Name] = f.Name
		used[f.Name] = true
2465 2466
	}

2467
	if !*godefs {
2468
		for cid, goid := range ident {
2469
			if token.Lookup(goid).IsKeyword() {
2470
				// Avoid keyword
2471 2472
				goid = "_" + goid

2473 2474 2475 2476 2477 2478 2479 2480
				// Also avoid existing fields
				for _, exist := used[goid]; exist; _, exist = used[goid] {
					goid = "_" + goid
				}

				used[goid] = true
				ident[cid] = goid
			}
2481 2482 2483
		}
	}

2484
	anon := 0
Russ Cox's avatar
Russ Cox committed
2485 2486
	for _, f := range dt.Field {
		if f.ByteOffset > off {
2487
			fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
2488
			off = f.ByteOffset
Russ Cox's avatar
Russ Cox committed
2489
		}
2490 2491 2492 2493

		name := f.Name
		ft := f.Type

2494
		// In godefs mode, if this field is a C11
2495
		// anonymous union then treat the first field in the
2496
		// union as the field in the struct. This handles
2497 2498
		// cases like the glibc <sys/resource.h> file; see
		// issue 6677.
2499
		if *godefs {
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510
			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)
2511 2512
		tgo := t.Go
		size := t.Size
2513
		talign := t.Align
2514
		if f.BitSize > 0 {
2515 2516 2517
			switch f.BitSize {
			case 8, 16, 32, 64:
			default:
2518 2519 2520 2521 2522 2523 2524 2525 2526 2527
				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))
2528
			talign = size
2529 2530
		}

2531
		if talign > 0 && f.ByteOffset%talign != 0 {
2532 2533 2534 2535 2536 2537 2538
			// 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
		}
2539 2540
		n := len(fld)
		fld = fld[0 : n+1]
2541 2542 2543 2544 2545 2546
		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}
2547 2548
		sizes = sizes[0 : n+1]
		sizes[n] = size
2549
		off += size
2550
		buf.WriteString(t.C.String())
Russ Cox's avatar
Russ Cox committed
2551
		buf.WriteString(" ")
2552
		buf.WriteString(name)
Russ Cox's avatar
Russ Cox committed
2553
		buf.WriteString("; ")
2554 2555
		if talign > align {
			align = talign
Russ Cox's avatar
Russ Cox committed
2556 2557 2558
		}
	}
	if off < dt.ByteSize {
2559
		fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
2560
		off = dt.ByteSize
Russ Cox's avatar
Russ Cox committed
2561
	}
2562 2563 2564 2565 2566 2567

	// 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,
2568
	// which means that it cannot be referenced from Go.
2569 2570 2571 2572 2573 2574
	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
2575
	if off != dt.ByteSize {
Russ Cox's avatar
Russ Cox committed
2576
		fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
Russ Cox's avatar
Russ Cox committed
2577
	}
Russ Cox's avatar
Russ Cox committed
2578 2579
	buf.WriteString("}")
	csyntax = buf.String()
2580

2581
	if *godefs {
2582
		godefsFields(fld)
2583
	}
2584
	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
2585
	return
Russ Cox's avatar
Russ Cox committed
2586
}
2587

2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
// dwarfHasPointer returns whether the DWARF type dt contains a pointer.
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)
	}
}

2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645
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 {
2646 2647
			if n.Name != prefix {
				n.Name = strings.TrimPrefix(n.Name, prefix)
2648 2649 2650 2651 2652 2653
			}
			if n.Name == "_" {
				// Use exported name instead.
				n.Name = "Pad_cgo_" + strconv.Itoa(npad)
				npad++
			}
2654
			n.Name = upper(n.Name)
2655 2656 2657 2658 2659
		}
	}
}

// fieldPrefix returns the prefix that should be removed from all the
2660
// field names when generating the C or Go code. For generated
2661 2662 2663 2664 2665 2666 2667 2668 2669
// 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
2670
			// looking for. It is common in C headers to have fields
2671 2672 2673
			// 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.
2674
			// The check for "orig_" here handles orig_eax in the
2675 2676 2677 2678 2679
			// x86 ptrace register sets, which otherwise have all fields
			// with reg_ prefixes.
			if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
				continue
			}
2680
			i := strings.Index(n.Name, "_")
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
			if i < 0 {
				continue
			}
			if prefix == "" {
				prefix = n.Name[:i+1]
			} else if prefix != n.Name[:i+1] {
				return ""
			}
		}
	}
	return prefix
}
2693 2694 2695 2696 2697

// 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.
2698 2699
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
	if c.badCFType(dt) {
2700 2701
		return true
	}
2702
	if c.badJNI(dt) {
2703 2704 2705 2706 2707
		return true
	}
	return false
}

2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720
// 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)
}

2721
func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
2722
	// The real bad types are CFNumberRef and CFDateRef.
2723 2724
	// Sometimes non-pointers are stored in these types.
	// CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
2725 2726 2727
	// 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.
2728
	// See comment below for details about the bad pointers.
2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
	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
2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783
}

// 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,
};
*/
2784

2785
func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808
	// 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
			}
		}

2809 2810 2811 2812 2813 2814 2815 2816 2817
		// 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;
2818
		if ptr, ok := w.Type.(*dwarf.PtrType); ok {
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833
			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
						}
					}
2834 2835 2836 2837 2838 2839 2840 2841
				}
			}
		}
	}
	return false
}

// jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which
2842
// they are mapped. The base "jobject" maps to the empty string.
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859
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",
}