cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// Annotate Ref in Prog with C types by parsing gcc debug output.
|
2009-09-24 11:43:19 -07:00
|
|
|
// Conversion of debug output to Go types.
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2009-12-15 15:33:31 -08:00
|
|
|
"bytes"
|
|
|
|
|
"debug/dwarf"
|
|
|
|
|
"debug/elf"
|
|
|
|
|
"debug/macho"
|
2010-11-01 17:52:26 -04:00
|
|
|
"debug/pe"
|
2011-06-13 14:43:54 -04:00
|
|
|
"encoding/binary"
|
2011-11-01 22:06:05 -04:00
|
|
|
"errors"
|
2010-07-14 17:17:53 -07:00
|
|
|
"flag"
|
2009-12-15 15:33:31 -08:00
|
|
|
"fmt"
|
|
|
|
|
"go/ast"
|
2010-01-11 13:05:26 -08:00
|
|
|
"go/parser"
|
2009-12-15 15:33:31 -08:00
|
|
|
"go/token"
|
|
|
|
|
"os"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
2011-02-01 08:44:18 -05:00
|
|
|
"unicode"
|
2011-11-10 19:08:04 -05:00
|
|
|
"unicode/utf8"
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
)
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
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{
|
2011-01-19 14:30:57 -05:00
|
|
|
"schar": "signed char",
|
|
|
|
|
"uchar": "unsigned char",
|
|
|
|
|
"ushort": "unsigned short",
|
|
|
|
|
"uint": "unsigned int",
|
|
|
|
|
"ulong": "unsigned long",
|
|
|
|
|
"longlong": "long long",
|
|
|
|
|
"ulonglong": "unsigned long long",
|
|
|
|
|
"complexfloat": "float complex",
|
|
|
|
|
"complexdouble": "double complex",
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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_"):]
|
|
|
|
|
}
|
2011-11-10 19:08:04 -05:00
|
|
|
if strings.HasPrefix(s, "sizeof_") {
|
|
|
|
|
return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
|
|
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-10 21:41:54 -07:00
|
|
|
// 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() {
|
2011-06-28 09:43:14 +10:00
|
|
|
linesIn := strings.Split(f.Preamble, "\n")
|
2011-02-01 08:44:18 -05:00
|
|
|
linesOut := make([]string, 0, len(linesIn))
|
|
|
|
|
for _, line := range linesIn {
|
|
|
|
|
l := strings.TrimSpace(line)
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
|
2011-02-01 08:44:18 -05:00
|
|
|
linesOut = append(linesOut, line)
|
2013-09-03 21:15:15 -07:00
|
|
|
} else {
|
|
|
|
|
linesOut = append(linesOut, "")
|
2011-02-01 08:44:18 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f.Preamble = strings.Join(linesOut, "\n")
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-26 22:19:23 -03:00
|
|
|
// addToFlag appends args to flag. All flags are later written out onto the
|
|
|
|
|
// _cgo_flags file for the build system to use.
|
|
|
|
|
func (p *Package) addToFlag(flag string, args []string) {
|
2013-03-06 16:57:14 -05:00
|
|
|
p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
|
2011-05-26 22:19:23 -03:00
|
|
|
if flag == "CFLAGS" {
|
|
|
|
|
// We'll also need these when preprocessing for dwarf information.
|
|
|
|
|
p.GccOptions = append(p.GccOptions, args...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 08:44:18 -05:00
|
|
|
// 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
|
|
|
|
|
// last element. The backslash is used for escaping.
|
|
|
|
|
//
|
|
|
|
|
// For example, the following string:
|
|
|
|
|
//
|
|
|
|
|
// `a b:"c d" 'e''f' "g\""`
|
|
|
|
|
//
|
|
|
|
|
// Would be parsed as:
|
|
|
|
|
//
|
|
|
|
|
// []string{"a", "b:c d", "ef", `g"`}
|
|
|
|
|
//
|
2011-11-01 22:06:05 -04:00
|
|
|
func splitQuoted(s string) (r []string, err error) {
|
2011-02-01 08:44:18 -05:00
|
|
|
var args []string
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
arg := make([]rune, len(s))
|
2011-02-01 08:44:18 -05:00
|
|
|
escaped := false
|
|
|
|
|
quoted := false
|
2011-12-08 22:08:03 -05:00
|
|
|
quote := '\x00'
|
2011-02-01 08:44:18 -05:00
|
|
|
i := 0
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
for _, r := range s {
|
2011-02-01 08:44:18 -05:00
|
|
|
switch {
|
|
|
|
|
case escaped:
|
|
|
|
|
escaped = false
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
case r == '\\':
|
2011-02-01 08:44:18 -05:00
|
|
|
escaped = true
|
|
|
|
|
continue
|
|
|
|
|
case quote != 0:
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
if r == quote {
|
2011-02-01 08:44:18 -05:00
|
|
|
quote = 0
|
|
|
|
|
continue
|
|
|
|
|
}
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
case r == '"' || r == '\'':
|
2011-02-01 08:44:18 -05:00
|
|
|
quoted = true
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
quote = r
|
2011-02-01 08:44:18 -05:00
|
|
|
continue
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
case unicode.IsSpace(r):
|
2011-02-01 08:44:18 -05:00
|
|
|
if quoted || i > 0 {
|
|
|
|
|
quoted = false
|
|
|
|
|
args = append(args, string(arg[:i]))
|
|
|
|
|
i = 0
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
cgo, goyacc, go/build, html, http, path, path/filepath, testing/quick, test: use rune
Nothing terribly interesting here.
R=golang-dev, bradfitz, gri, r
CC=golang-dev
https://golang.org/cl/5300043
2011-10-25 22:20:02 -07:00
|
|
|
arg[i] = r
|
2011-02-01 08:44:18 -05:00
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
if quoted || i > 0 {
|
|
|
|
|
args = append(args, string(arg[:i]))
|
|
|
|
|
}
|
|
|
|
|
if quote != 0 {
|
2011-11-01 22:06:05 -04:00
|
|
|
err = errors.New("unclosed quote")
|
2011-02-01 08:44:18 -05:00
|
|
|
} else if escaped {
|
2011-11-01 22:06:05 -04:00
|
|
|
err = errors.New("unfinished escaping")
|
2011-02-01 08:44:18 -05:00
|
|
|
}
|
|
|
|
|
return args, err
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-04 15:07:28 +11:00
|
|
|
var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
|
2011-05-26 22:19:23 -03:00
|
|
|
|
|
|
|
|
func safeName(s string) bool {
|
|
|
|
|
if s == "" {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
|
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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)
|
|
|
|
|
needType := p.guessKinds(f)
|
|
|
|
|
if len(needType) > 0 {
|
|
|
|
|
p.loadDWARF(f, needType)
|
|
|
|
|
}
|
|
|
|
|
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) {
|
2010-01-11 13:05:26 -08:00
|
|
|
var b bytes.Buffer
|
2010-07-14 17:17:53 -07:00
|
|
|
b.WriteString(f.Preamble)
|
2013-10-15 15:00:48 -04:00
|
|
|
b.WriteString(builtinProlog)
|
2010-07-14 17:17:53 -07:00
|
|
|
stdout := p.gccDefines(b.Bytes())
|
2010-01-11 13:05:26 -08:00
|
|
|
|
2011-06-28 09:43:14 +10:00
|
|
|
for _, line := range strings.Split(stdout, "\n") {
|
2010-01-11 13:05:26 -08:00
|
|
|
if len(line) < 9 || line[0:7] != "#define" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line = strings.TrimSpace(line[8:])
|
|
|
|
|
|
|
|
|
|
var key, val string
|
|
|
|
|
spaceIndex := strings.Index(line, " ")
|
|
|
|
|
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:])
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
if n := f.Name[key]; n != nil {
|
|
|
|
|
if *debugDefine {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
|
2010-01-11 13:05:26 -08:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
n.Define = val
|
2010-01-11 13:05:26 -08:00
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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 {
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
// Determine kinds for names we already know about,
|
|
|
|
|
// like #defines or 'struct foo', before bothering with gcc.
|
|
|
|
|
var names, needType []*Name
|
2010-07-14 17:17:53 -07:00
|
|
|
for _, n := range f.Name {
|
|
|
|
|
// If we've already found this name as a #define
|
|
|
|
|
// and we can translate it as a constant value, do so.
|
|
|
|
|
if n.Define != "" {
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
isConst := false
|
2010-07-14 17:17:53 -07:00
|
|
|
if _, err := strconv.Atoi(n.Define); err == nil {
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
isConst = true
|
2010-07-14 17:17:53 -07:00
|
|
|
} else if n.Define[0] == '"' || n.Define[0] == '\'' {
|
2012-01-12 16:04:48 -08:00
|
|
|
if _, err := parser.ParseExpr(n.Define); err == nil {
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
isConst = true
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
if isConst {
|
2010-07-14 17:17:53 -07:00
|
|
|
n.Kind = "const"
|
2011-11-10 19:08:04 -05:00
|
|
|
// Turn decimal into hex, just for consistency
|
|
|
|
|
// with enum-derived constants. Otherwise
|
|
|
|
|
// in the cgo -godefs output half the constants
|
|
|
|
|
// are in hex and half are in whatever the #define used.
|
2011-12-05 15:48:46 -05:00
|
|
|
i, err := strconv.ParseInt(n.Define, 0, 64)
|
2011-11-10 19:08:04 -05:00
|
|
|
if err == nil {
|
|
|
|
|
n.Const = fmt.Sprintf("%#x", i)
|
|
|
|
|
} else {
|
|
|
|
|
n.Const = n.Define
|
|
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if isName(n.Define) {
|
|
|
|
|
n.C = n.Define
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
needType = append(needType, n)
|
|
|
|
|
|
|
|
|
|
// If this is a struct, union, or enum type name, no need to guess the kind.
|
2010-07-14 17:17:53 -07:00
|
|
|
if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
|
|
|
|
|
n.Kind = "type"
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
// Otherwise, we'll need to find out from gcc.
|
|
|
|
|
names = append(names, n)
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
// Bypass gcc if there's nothing left to find out.
|
|
|
|
|
if len(names) == 0 {
|
2010-07-14 17:17:53 -07:00
|
|
|
return needType
|
|
|
|
|
}
|
|
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
// 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"
|
2013-10-22 18:33:23 -04:00
|
|
|
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
// #line xxx "not-type"
|
|
|
|
|
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
|
|
|
|
|
// #line xxx "not-const"
|
|
|
|
|
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
|
|
|
|
|
//
|
|
|
|
|
// 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.
|
|
|
|
|
// If we see an error at not-const:xxx, the corresponding name is not an integer constant.
|
|
|
|
|
// If we see no errors, we assume the name is an expression but not a constant
|
|
|
|
|
// (so a variable or a function).
|
|
|
|
|
//
|
|
|
|
|
// The specific input forms are chosen so that they are valid C syntax regardless of
|
|
|
|
|
// whether name denotes a type or an expression.
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
var b bytes.Buffer
|
|
|
|
|
b.WriteString(f.Preamble)
|
2013-10-15 15:00:48 -04:00
|
|
|
b.WriteString(builtinProlog)
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
|
|
|
|
|
for i, n := range names {
|
|
|
|
|
fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
|
2013-10-22 18:33:23 -04:00
|
|
|
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
"#line %d \"not-type\"\n"+
|
|
|
|
|
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
|
|
|
|
|
"#line %d \"not-const\"\n"+
|
|
|
|
|
"void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
|
|
|
|
|
i+1, i+1, n.C,
|
|
|
|
|
i+1, i+1, n.C,
|
|
|
|
|
i+1, i+1, n.C)
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
|
|
|
|
|
"int __cgo__1 = __cgo__2;\n")
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
stderr := p.gccErrors(b.Bytes())
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
if stderr == "" {
|
2013-09-11 09:56:51 -04:00
|
|
|
fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
completed := false
|
|
|
|
|
sniff := make([]int, len(names))
|
|
|
|
|
const (
|
|
|
|
|
notType = 1 << iota
|
|
|
|
|
notConst
|
|
|
|
|
)
|
2011-06-28 09:43:14 +10:00
|
|
|
for _, line := range strings.Split(stderr, "\n") {
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
if !strings.Contains(line, ": error:") {
|
|
|
|
|
// we only care about errors.
|
|
|
|
|
// we tried to turn off warnings on the command line, but one never knows.
|
2009-11-09 12:07:39 -08:00
|
|
|
continue
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
|
|
|
|
|
c1 := strings.Index(line, ":")
|
|
|
|
|
if c1 < 0 {
|
2009-11-09 12:07:39 -08:00
|
|
|
continue
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
c2 := strings.Index(line[c1+1:], ":")
|
|
|
|
|
if c2 < 0 {
|
2010-07-14 17:17:53 -07:00
|
|
|
continue
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
c2 += c1 + 1
|
|
|
|
|
|
|
|
|
|
filename := line[:c1]
|
|
|
|
|
i, _ := strconv.Atoi(line[c1+1 : c2])
|
|
|
|
|
i--
|
|
|
|
|
if i < 0 || i >= len(names) {
|
2010-07-14 17:17:53 -07:00
|
|
|
continue
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
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":
|
|
|
|
|
error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
|
|
|
|
|
case "not-type":
|
|
|
|
|
sniff[i] |= notType
|
|
|
|
|
case "not-const":
|
|
|
|
|
sniff[i] |= notConst
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
|
|
|
|
|
if !completed {
|
|
|
|
|
fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i, n := range names {
|
|
|
|
|
switch sniff[i] {
|
|
|
|
|
case 0:
|
|
|
|
|
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
|
|
|
|
|
case notType:
|
|
|
|
|
n.Kind = "const"
|
|
|
|
|
case notConst:
|
|
|
|
|
n.Kind = "type"
|
|
|
|
|
case notConst | notType:
|
|
|
|
|
n.Kind = "not-type"
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-11-11 16:58:27 -08:00
|
|
|
if nerrors > 0 {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("unresolved names")
|
2009-11-11 16:58:27 -08:00
|
|
|
}
|
cmd/cgo: stop using compiler error message text to analyze C names
The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program
name;
and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.
The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:
// error if and only if name is undeclared
void f1(void) { typeof(name) *x; }
// error if and only if name is not a type
void f2(void) { name *x; }
// error if and only if name is not an integer constant
void f3(void) { enum { x = (name)*1 }; }
I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.
Fixes #6596.
Fixes #6612.
R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
2013-10-18 15:56:25 -04:00
|
|
|
|
|
|
|
|
needType = append(needType, names...)
|
2010-07-14 17:17:53 -07:00
|
|
|
return needType
|
|
|
|
|
}
|
2009-11-11 16:58:27 -08:00
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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) {
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
// Extract the types from the DWARF section of an object
|
|
|
|
|
// from a well-formed C program. Gcc only generates DWARF info
|
|
|
|
|
// 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
|
2013-10-22 18:33:23 -04:00
|
|
|
// __typeof__(names[i]) *__cgo__i;
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
// for each entry in names and then dereference the type we
|
|
|
|
|
// learn for __cgo__i.
|
2010-07-14 17:17:53 -07:00
|
|
|
var b bytes.Buffer
|
|
|
|
|
b.WriteString(f.Preamble)
|
2013-10-15 15:00:48 -04:00
|
|
|
b.WriteString(builtinProlog)
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
for i, n := range names {
|
2013-10-22 18:33:23 -04:00
|
|
|
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
|
2010-07-14 17:17:53 -07:00
|
|
|
if n.Kind == "const" {
|
|
|
|
|
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
|
|
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2011-06-13 14:43:54 -04:00
|
|
|
|
|
|
|
|
// Apple's LLVM-based gcc does not include the enumeration
|
|
|
|
|
// names and values in its DWARF debug output. In case we're
|
|
|
|
|
// using such a gcc, create a data block initialized with the values.
|
|
|
|
|
// We can read them out of the object file.
|
|
|
|
|
fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
|
|
|
|
|
for _, n := range names {
|
|
|
|
|
if n.Kind == "const" {
|
|
|
|
|
fmt.Fprintf(&b, "\t%s,\n", n.C)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Fprintf(&b, "\t0,\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-07-30 18:44:48 -04:00
|
|
|
// for the last entry, we can not use 0, otherwise
|
|
|
|
|
// 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")
|
2011-06-13 14:43:54 -04:00
|
|
|
fmt.Fprintf(&b, "};\n")
|
|
|
|
|
|
|
|
|
|
d, bo, debugData := p.gccDebug(b.Bytes())
|
|
|
|
|
enumVal := make([]int64, len(debugData)/8)
|
|
|
|
|
for i := range enumVal {
|
|
|
|
|
enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
|
|
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
|
2009-11-02 12:02:16 -08:00
|
|
|
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
|
2009-12-15 15:33:31 -08:00
|
|
|
types := make([]dwarf.Type, len(names))
|
2009-12-15 21:24:17 -08:00
|
|
|
enums := make([]dwarf.Offset, len(names))
|
2010-07-14 17:17:53 -07:00
|
|
|
nameToIndex := make(map[*Name]int)
|
|
|
|
|
for i, n := range names {
|
|
|
|
|
nameToIndex[n] = i
|
|
|
|
|
}
|
2012-02-06 20:38:54 +01:00
|
|
|
nameToRef := make(map[*Name]*Ref)
|
|
|
|
|
for _, ref := range f.Ref {
|
|
|
|
|
nameToRef[ref.Name] = ref
|
|
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
r := d.Reader()
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
for {
|
2009-12-15 15:33:31 -08:00
|
|
|
e, err := r.Next()
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
if err != nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("reading DWARF entry: %s", err)
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
if e == nil {
|
2009-11-09 12:07:39 -08:00
|
|
|
break
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2009-12-15 21:24:17 -08:00
|
|
|
switch e.Tag {
|
|
|
|
|
case dwarf.TagEnumerationType:
|
|
|
|
|
offset := e.Offset
|
|
|
|
|
for {
|
|
|
|
|
e, err := r.Next()
|
|
|
|
|
if err != nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("reading DWARF entry: %s", err)
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
if e.Tag == 0 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if e.Tag == dwarf.TagEnumerator {
|
|
|
|
|
entryName := e.Val(dwarf.AttrName).(string)
|
2010-07-14 17:17:53 -07:00
|
|
|
if strings.HasPrefix(entryName, "__cgo_enum__") {
|
|
|
|
|
n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
|
|
|
|
|
if 0 <= n && n < len(names) {
|
|
|
|
|
enums[n] = offset
|
|
|
|
|
}
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case dwarf.TagVariable:
|
|
|
|
|
name, _ := e.Val(dwarf.AttrName).(string)
|
|
|
|
|
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
|
|
|
|
|
if name == "" || typOff == 0 {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("malformed DWARF TagVariable entry")
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
if !strings.HasPrefix(name, "__cgo__") {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
typ, err := d.Type(typOff)
|
|
|
|
|
if err != nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("loading DWARF type: %s", err)
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
t, ok := typ.(*dwarf.PtrType)
|
|
|
|
|
if !ok || t == nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("internal error: %s has non-pointer type", name)
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
i, err := strconv.Atoi(name[7:])
|
|
|
|
|
if err != nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("malformed __cgo__ name: %s", name)
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
if enums[i] != 0 {
|
|
|
|
|
t, err := d.Type(enums[i])
|
|
|
|
|
if err != nil {
|
2011-04-13 16:57:44 -07:00
|
|
|
fatalf("loading DWARF type: %s", err)
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
|
|
|
|
types[i] = t
|
|
|
|
|
} else {
|
|
|
|
|
types[i] = t.Type
|
|
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
if e.Tag != dwarf.TagCompileUnit {
|
2009-11-09 12:07:39 -08:00
|
|
|
r.SkipChildren()
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// Record types and typedef information.
|
2009-12-15 15:33:31 -08:00
|
|
|
var conv typeConv
|
2012-09-24 14:58:57 -04:00
|
|
|
conv.Init(p.PtrSize, p.IntSize)
|
2010-07-14 17:17:53 -07:00
|
|
|
for i, n := range names {
|
2011-11-09 16:01:55 -05:00
|
|
|
if types[i] == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2012-02-06 20:38:54 +01:00
|
|
|
pos := token.NoPos
|
|
|
|
|
if ref, ok := nameToRef[n]; ok {
|
|
|
|
|
pos = ref.Pos()
|
|
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
f, fok := types[i].(*dwarf.FuncType)
|
2010-07-14 17:17:53 -07:00
|
|
|
if n.Kind != "type" && fok {
|
|
|
|
|
n.Kind = "func"
|
2013-10-15 21:35:52 -04:00
|
|
|
n.FuncType = conv.FuncType(f, pos)
|
2009-09-24 11:43:19 -07:00
|
|
|
} else {
|
2012-02-06 20:38:54 +01:00
|
|
|
n.Type = conv.Type(types[i], pos)
|
2012-09-20 13:20:33 +10:00
|
|
|
if enums[i] != 0 && n.Type.EnumValues != nil {
|
2011-01-11 10:15:49 -05:00
|
|
|
k := fmt.Sprintf("__cgo_enum__%d", i)
|
2010-07-14 17:17:53 -07:00
|
|
|
n.Kind = "const"
|
2011-11-10 19:08:04 -05:00
|
|
|
n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
|
2011-01-11 10:15:49 -05:00
|
|
|
// Remove injected enum to ensure the value will deep-compare
|
|
|
|
|
// equally in future loads of the same constant.
|
2011-10-18 09:56:34 -04:00
|
|
|
delete(n.Type.EnumValues, k)
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
2012-09-20 13:20:33 +10:00
|
|
|
// Prefer debug data over DWARF debug output, if we have it.
|
|
|
|
|
if n.Kind == "const" && i < len(enumVal) {
|
|
|
|
|
n.Const = fmt.Sprintf("%#x", enumVal[i])
|
|
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2011-06-13 14:43:54 -04:00
|
|
|
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-13 12:42:21 -04:00
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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
|
2011-11-10 19:08:04 -05:00
|
|
|
// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
|
|
|
|
|
// with full definitions instead of mangled names.
|
2010-07-14 17:17:53 -07:00
|
|
|
func (p *Package) rewriteRef(f *File) {
|
2013-08-13 12:42:21 -04:00
|
|
|
// 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)
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// Assign mangled names.
|
|
|
|
|
for _, n := range f.Name {
|
|
|
|
|
if n.Kind == "not-type" {
|
|
|
|
|
n.Kind = "var"
|
|
|
|
|
}
|
|
|
|
|
if n.Mangle == "" {
|
2013-08-13 12:42:21 -04:00
|
|
|
p.mangleName(n)
|
|
|
|
|
}
|
|
|
|
|
if n.Kind == "func" {
|
|
|
|
|
functions[n.Go] = false
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
2009-10-03 10:37:12 -07:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
|
|
|
|
|
// Now that we have all the name types filled in,
|
|
|
|
|
// scan through the Refs to identify the ones that
|
|
|
|
|
// are trying to do a ,err call. Also check that
|
|
|
|
|
// functions are only used in calls.
|
|
|
|
|
for _, r := range f.Ref {
|
2011-06-13 14:43:54 -04:00
|
|
|
if r.Name.Kind == "const" && r.Name.Const == "" {
|
2013-09-11 09:56:51 -04:00
|
|
|
error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
|
2011-06-13 14:43:54 -04:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
|
|
|
|
|
switch r.Context {
|
|
|
|
|
case "call", "call2":
|
|
|
|
|
if r.Name.Kind != "func" {
|
|
|
|
|
if r.Name.Kind == "type" {
|
|
|
|
|
r.Context = "type"
|
|
|
|
|
expr = r.Name.Type.Go
|
|
|
|
|
break
|
|
|
|
|
}
|
2013-09-11 09:56:51 -04:00
|
|
|
error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
|
2010-07-14 17:17:53 -07:00
|
|
|
break
|
|
|
|
|
}
|
2013-08-13 12:42:21 -04:00
|
|
|
functions[r.Name.Go] = true
|
2010-07-14 17:17:53 -07:00
|
|
|
if r.Context == "call2" {
|
2013-09-11 09:56:51 -04:00
|
|
|
if r.Name.Go == "_CMalloc" {
|
|
|
|
|
error_(r.Pos(), "no two-result form for C.malloc")
|
|
|
|
|
break
|
|
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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
|
|
|
|
|
}
|
2010-08-04 17:15:04 -07:00
|
|
|
expr = ast.NewIdent(n.Mangle)
|
2010-07-14 17:17:53 -07:00
|
|
|
r.Name = n
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
case "expr":
|
|
|
|
|
if r.Name.Kind == "func" {
|
2013-08-13 12:42:21 -04:00
|
|
|
// 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
|
|
|
|
|
expr = ast.NewIdent(name.Mangle)
|
|
|
|
|
} else if r.Name.Kind == "type" {
|
2010-07-14 17:17:53 -07:00
|
|
|
// Okay - might be new(T)
|
|
|
|
|
expr = r.Name.Type.Go
|
2013-08-13 12:42:21 -04:00
|
|
|
} else if r.Name.Kind == "var" {
|
2013-10-18 16:52:44 -04:00
|
|
|
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "type":
|
|
|
|
|
if r.Name.Kind != "type" {
|
2013-09-11 09:56:51 -04:00
|
|
|
error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
|
2011-11-09 16:01:55 -05:00
|
|
|
} 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.
|
2013-09-11 09:56:51 -04:00
|
|
|
error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
|
2010-09-16 13:38:23 -04:00
|
|
|
} else {
|
|
|
|
|
expr = r.Name.Type.Go
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
if r.Name.Kind == "func" {
|
2013-09-11 09:56:51 -04:00
|
|
|
error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-10 19:08:04 -05:00
|
|
|
if *godefs || *cdefs {
|
|
|
|
|
// Substitute definition for mangled type name.
|
|
|
|
|
if id, ok := expr.(*ast.Ident); ok {
|
|
|
|
|
if t := typedef[id.Name]; t != nil {
|
2012-02-19 13:32:55 -05:00
|
|
|
expr = t.Go
|
2011-11-10 19:08:04 -05:00
|
|
|
}
|
|
|
|
|
if id.Name == r.Name.Mangle && r.Name.Const != "" {
|
|
|
|
|
expr = ast.NewIdent(r.Name.Const)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-18 16:52:44 -04:00
|
|
|
|
|
|
|
|
// 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()
|
|
|
|
|
switch x := expr.(type) {
|
|
|
|
|
case *ast.Ident:
|
|
|
|
|
expr = &ast.Ident{NamePos: pos, Name: x.Name}
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
*r.Expr = expr
|
2009-10-03 10:37:12 -07:00
|
|
|
}
|
2013-08-13 12:42:21 -04:00
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-03 10:37:12 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-02 14:58:27 -04:00
|
|
|
// 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 {
|
2013-02-15 13:37:43 -08:00
|
|
|
// Use $CC if set, since that's what the build uses.
|
2013-08-02 14:58:27 -04:00
|
|
|
if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
|
2013-02-15 13:37:43 -08:00
|
|
|
return ret
|
2010-07-16 11:01:04 -07:00
|
|
|
}
|
2013-08-02 14:58:27 -04:00
|
|
|
// Try $GCC if set, since that's what we used to use.
|
|
|
|
|
if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
|
2013-02-15 13:37:43 -08:00
|
|
|
return ret
|
|
|
|
|
}
|
2013-08-02 14:58:27 -04:00
|
|
|
return strings.Fields(defaultCC)
|
2010-07-16 11:01:04 -07:00
|
|
|
}
|
|
|
|
|
|
2012-05-04 18:26:16 +08:00
|
|
|
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
|
2011-06-07 16:59:35 +10:00
|
|
|
func (p *Package) gccMachine() []string {
|
2011-09-19 11:50:59 -04:00
|
|
|
switch goarch {
|
2011-06-07 16:59:35 +10:00
|
|
|
case "amd64":
|
|
|
|
|
return []string{"-m64"}
|
|
|
|
|
case "386":
|
|
|
|
|
return []string{"-m32"}
|
2012-05-04 18:26:16 +08:00
|
|
|
case "arm":
|
|
|
|
|
return []string{"-marm"} // not thumb
|
2011-06-07 16:59:35 +10:00
|
|
|
}
|
|
|
|
|
return nil
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
|
2011-12-14 22:42:42 -05:00
|
|
|
func gccTmp() string {
|
|
|
|
|
return *objDir + "_cgo_.o"
|
|
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
|
|
|
|
|
// gccCmd returns the gcc command line to use for compiling
|
|
|
|
|
// the input.
|
|
|
|
|
func (p *Package) gccCmd() []string {
|
2013-08-02 14:58:27 -04:00
|
|
|
c := append(p.gccBaseCmd(),
|
2013-10-28 22:21:26 -04:00
|
|
|
"-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
|
2013-08-02 14:58:27 -04:00
|
|
|
)
|
|
|
|
|
if strings.Contains(c[0], "clang") {
|
2013-02-15 13:37:43 -08:00
|
|
|
c = append(c,
|
|
|
|
|
"-ferror-limit=0",
|
2013-02-23 20:24:38 +08:00
|
|
|
// 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",
|
2013-02-15 13:37:43 -08:00
|
|
|
"-Wno-unneeded-internal-declaration",
|
2013-02-23 20:24:38 +08:00
|
|
|
"-Wno-unused-function",
|
|
|
|
|
"-Qunused-arguments",
|
2013-10-15 21:35:52 -04:00
|
|
|
// 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).
|
|
|
|
|
// See: http://golang.org/issue/6506.
|
|
|
|
|
"-fno-builtin",
|
2013-02-15 13:37:43 -08:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-06 13:35:51 -07:00
|
|
|
c = append(c, p.GccOptions...)
|
2011-06-07 16:59:35 +10:00
|
|
|
c = append(c, p.gccMachine()...)
|
2011-05-06 13:35:51 -07:00
|
|
|
c = append(c, "-") //read input from standard input
|
|
|
|
|
return c
|
2010-07-14 17:17:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
2011-06-13 14:43:54 -04:00
|
|
|
// returns the corresponding DWARF data and, if present, debug data block.
|
|
|
|
|
func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
|
2011-05-06 13:35:51 -07:00
|
|
|
runGcc(stdin, p.gccCmd())
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
|
2013-10-30 10:24:42 -04:00
|
|
|
isDebugData := func(s string) bool {
|
|
|
|
|
// Some systems use leading _ to denote non-assembly symbols.
|
|
|
|
|
return s == "__cgodebug_data" || s == "___cgodebug_data"
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 22:42:42 -05:00
|
|
|
if f, err := macho.Open(gccTmp()); err == nil {
|
2013-06-18 23:20:17 +10:00
|
|
|
defer f.Close()
|
2011-06-13 14:43:54 -04:00
|
|
|
d, err := f.DWARF()
|
|
|
|
|
if err != nil {
|
2011-12-14 22:42:42 -05:00
|
|
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
2011-06-13 14:43:54 -04:00
|
|
|
}
|
|
|
|
|
var data []byte
|
|
|
|
|
if f.Symtab != nil {
|
|
|
|
|
for i := range f.Symtab.Syms {
|
|
|
|
|
s := &f.Symtab.Syms[i]
|
2013-10-30 10:24:42 -04:00
|
|
|
if isDebugData(s.Name) {
|
2011-06-13 14:43:54 -04:00
|
|
|
// 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:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-11-01 17:52:26 -04:00
|
|
|
}
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2011-06-13 14:43:54 -04:00
|
|
|
return d, f.ByteOrder, data
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
|
2011-12-14 22:42:42 -05:00
|
|
|
if f, err := elf.Open(gccTmp()); err == nil {
|
2013-06-18 23:20:17 +10:00
|
|
|
defer f.Close()
|
2011-06-13 14:43:54 -04:00
|
|
|
d, err := f.DWARF()
|
|
|
|
|
if err != nil {
|
2011-12-14 22:42:42 -05:00
|
|
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
2011-06-13 14:43:54 -04:00
|
|
|
}
|
2012-09-07 13:32:40 +10:00
|
|
|
var data []byte
|
|
|
|
|
symtab, err := f.Symbols()
|
|
|
|
|
if err == nil {
|
|
|
|
|
for i := range symtab {
|
|
|
|
|
s := &symtab[i]
|
2013-10-30 10:24:42 -04:00
|
|
|
if isDebugData(s.Name) {
|
2012-09-07 13:32:40 +10:00
|
|
|
// 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:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return d, f.ByteOrder, data
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
2011-06-13 14:43:54 -04:00
|
|
|
|
2011-12-14 22:42:42 -05:00
|
|
|
if f, err := pe.Open(gccTmp()); err == nil {
|
2013-06-18 23:20:17 +10:00
|
|
|
defer f.Close()
|
2011-06-13 14:43:54 -04:00
|
|
|
d, err := f.DWARF()
|
|
|
|
|
if err != nil {
|
2011-12-14 22:42:42 -05:00
|
|
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
2011-06-13 14:43:54 -04:00
|
|
|
}
|
2012-09-22 17:57:54 +10:00
|
|
|
var data []byte
|
|
|
|
|
for _, s := range f.Symbols {
|
2013-10-30 10:24:42 -04:00
|
|
|
if isDebugData(s.Name) {
|
2012-09-22 17:57:54 +10:00
|
|
|
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:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return d, binary.LittleEndian, data
|
2011-06-13 14:43:54 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-14 22:42:42 -05:00
|
|
|
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
|
2011-06-13 14:43:54 -04:00
|
|
|
panic("not reached")
|
cgo: can look up C identifier kind (type or value) and type
gmp.go:197:4: type mpz_t C type mpz_t
gmp.go:205:2: call mpz_init C value func(mpz_ptr) void
gmp.go:206:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:221:2: call mpz_init C value func(mpz_ptr) void
gmp.go:227:7: call size_t C type size_t
gmp.go:228:2: call mpz_export C value func(*void, *size_t, int, size_t, int, size_t, mpz_srcptr) *void
gmp.go:235:13: call mpz_sizeinbase C value func(mpz_srcptr, int) size_t
gmp.go:241:2: call mpz_set C value func(mpz_ptr, mpz_srcptr) void
gmp.go:252:3: call mpz_import C value func(mpz_ptr, size_t, int, size_t, int, size_t, *const void) void
gmp.go:261:2: call mpz_set_si C value func(mpz_ptr, long int) void
gmp.go:273:5: call mpz_set_str C value func(mpz_ptr, *const char, int) int
gmp.go:282:9: call mpz_get_str C value func(*char, int, mpz_srcptr) *char
gmp.go:287:3: call mpz_clear C value func(mpz_ptr) void
gmp.go:302:2: call mpz_add C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:311:2: call mpz_sub C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:320:2: call mpz_mul C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:329:2: call mpz_tdiv_q C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:339:2: call mpz_tdiv_r C value func(mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:348:2: call mpz_mul_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:356:2: call mpz_div_2exp C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:367:3: call mpz_pow_ui C value func(mpz_ptr, mpz_srcptr, long unsigned int) void
gmp.go:369:3: call mpz_powm C value func(mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr) void
gmp.go:378:2: call mpz_neg C value func(mpz_ptr, mpz_srcptr) void
gmp.go:386:2: call mpz_abs C value func(mpz_ptr, mpz_srcptr) void
gmp.go:404:9: call mpz_cmp C value func(mpz_srcptr, mpz_srcptr) int
gmp.go:413:2: call mpz_tdiv_qr C value func(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
gmp.go:426:2: call mpz_gcdext C value func(mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr) void
R=r
DELTA=938 (628 added, 308 deleted, 2 changed)
OCL=34733
CL=34791
2009-09-18 11:52:00 -07:00
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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 {
|
2013-08-02 14:58:27 -04:00
|
|
|
base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
|
2011-06-07 16:59:35 +10:00
|
|
|
base = append(base, p.gccMachine()...)
|
2011-05-06 13:35:51 -07:00
|
|
|
stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
|
2010-07-14 17:17:53 -07:00
|
|
|
return stdout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gccErrors runs gcc over the C program stdin and returns
|
|
|
|
|
// the errors that gcc prints. That is, this function expects
|
|
|
|
|
// gcc to fail.
|
|
|
|
|
func (p *Package) gccErrors(stdin []byte) string {
|
|
|
|
|
// TODO(rsc): require failure
|
2011-05-06 13:35:51 -07:00
|
|
|
args := p.gccCmd()
|
2013-05-08 06:28:33 -07:00
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
if *debugGcc {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
|
|
|
|
|
os.Stderr.Write(stdin)
|
|
|
|
|
fmt.Fprint(os.Stderr, "EOF\n")
|
|
|
|
|
}
|
|
|
|
|
stdout, stderr, _ := run(stdin, args)
|
|
|
|
|
if *debugGcc {
|
|
|
|
|
os.Stderr.Write(stdout)
|
|
|
|
|
os.Stderr.Write(stderr)
|
2010-01-11 13:05:26 -08:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
return string(stderr)
|
|
|
|
|
}
|
2010-01-11 13:05:26 -08:00
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// 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)
|
|
|
|
|
}
|
2010-01-11 13:05:26 -08:00
|
|
|
if !ok {
|
2010-07-14 17:17:53 -07:00
|
|
|
os.Stderr.Write(stderr)
|
|
|
|
|
os.Exit(2)
|
2010-01-11 13:05:26 -08:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
return string(stdout), string(stderr)
|
2010-01-11 13:05:26 -08:00
|
|
|
}
|
|
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
// 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.
|
2009-12-15 15:33:31 -08:00
|
|
|
m map[dwarf.Type]*Type
|
|
|
|
|
typedef map[string]ast.Expr
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
// Predeclared types.
|
2010-01-13 10:25:28 -08:00
|
|
|
bool ast.Expr
|
2009-12-15 15:33:31 -08:00
|
|
|
byte ast.Expr // denotes padding
|
|
|
|
|
int8, int16, int32, int64 ast.Expr
|
|
|
|
|
uint8, uint16, uint32, uint64, uintptr ast.Expr
|
|
|
|
|
float32, float64 ast.Expr
|
2011-01-19 14:30:57 -05:00
|
|
|
complex64, complex128 ast.Expr
|
2009-12-15 15:33:31 -08:00
|
|
|
void ast.Expr
|
|
|
|
|
unsafePointer ast.Expr
|
|
|
|
|
string ast.Expr
|
2012-12-18 00:26:08 +08:00
|
|
|
goVoid ast.Expr // _Ctype_void, denotes C's void
|
2009-09-24 11:43:19 -07:00
|
|
|
|
2009-12-15 15:33:31 -08:00
|
|
|
ptrSize int64
|
2012-09-24 14:58:57 -04:00
|
|
|
intSize int64
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2010-12-13 13:20:04 -05:00
|
|
|
var tagGen int
|
2012-02-19 13:32:55 -05:00
|
|
|
var typedef = make(map[string]*Type)
|
2011-11-10 19:08:04 -05:00
|
|
|
var goIdent = make(map[string]*ast.Ident)
|
2010-12-13 13:20:04 -05:00
|
|
|
|
2012-09-24 14:58:57 -04:00
|
|
|
func (c *typeConv) Init(ptrSize, intSize int64) {
|
2009-12-15 15:33:31 -08:00
|
|
|
c.ptrSize = ptrSize
|
2012-09-24 14:58:57 -04:00
|
|
|
c.intSize = intSize
|
2009-12-15 15:33:31 -08:00
|
|
|
c.m = make(map[dwarf.Type]*Type)
|
2010-01-13 10:25:28 -08:00
|
|
|
c.bool = c.Ident("bool")
|
2009-12-15 15:33:31 -08:00
|
|
|
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")
|
2011-01-19 14:30:57 -05:00
|
|
|
c.complex64 = c.Ident("complex64")
|
|
|
|
|
c.complex128 = c.Ident("complex128")
|
2009-12-15 15:33:31 -08:00
|
|
|
c.unsafePointer = c.Ident("unsafe.Pointer")
|
|
|
|
|
c.void = c.Ident("void")
|
|
|
|
|
c.string = c.Ident("string")
|
2012-12-18 00:26:08 +08:00
|
|
|
c.goVoid = c.Ident("_Ctype_void")
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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 {
|
2009-12-15 15:33:31 -08:00
|
|
|
dt = d.Type
|
|
|
|
|
continue
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
if d, ok := dt.(*dwarf.TypedefType); ok {
|
2009-12-15 15:33:31 -08:00
|
|
|
dt = d.Type
|
|
|
|
|
continue
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
break
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
return dt
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Map from dwarf text names to aliases we use in package "C".
|
2010-07-14 17:17:53 -07:00
|
|
|
var dwarfToName = map[string]string{
|
2010-03-02 13:46:51 -08:00
|
|
|
"long int": "long",
|
|
|
|
|
"long unsigned int": "ulong",
|
|
|
|
|
"unsigned int": "uint",
|
|
|
|
|
"short unsigned int": "ushort",
|
|
|
|
|
"short int": "short",
|
|
|
|
|
"long long int": "longlong",
|
2009-09-24 11:43:19 -07:00
|
|
|
"long long unsigned int": "ulonglong",
|
2010-03-02 13:46:51 -08:00
|
|
|
"signed char": "schar",
|
2011-01-19 14:30:57 -05:00
|
|
|
"float complex": "complexfloat",
|
|
|
|
|
"double complex": "complexdouble",
|
2009-11-05 15:33:26 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
|
2011-02-08 23:50:14 -05:00
|
|
|
const signedDelta = 64
|
|
|
|
|
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
// String returns the current type representation. Format arguments
|
|
|
|
|
// 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...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Empty returns true if the result of String would be "".
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
// Type returns a *Type with the same memory layout as
|
|
|
|
|
// dtype when used as the type of a variable or a struct field.
|
2012-02-06 20:38:54 +01:00
|
|
|
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
2009-09-24 11:43:19 -07:00
|
|
|
if t, ok := c.m[dtype]; ok {
|
|
|
|
|
if t.Go == nil {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
return t
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2013-02-23 20:24:38 +08:00
|
|
|
// clang won't generate DW_AT_byte_size for pointer types,
|
|
|
|
|
// so we have to fix it here.
|
|
|
|
|
if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
|
|
|
|
|
dt.ByteSize = c.ptrSize
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-15 15:33:31 -08:00
|
|
|
t := new(Type)
|
2013-11-07 15:24:51 -05:00
|
|
|
t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Align = -1
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
t.C = &TypeRepr{Repr: dtype.Common().Name}
|
2009-12-15 15:33:31 -08:00
|
|
|
c.m[dtype] = t
|
2010-07-14 17:17:53 -07:00
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
switch dt := dtype.(type) {
|
|
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected type: %s", lineno(pos), dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.AddrType:
|
|
|
|
|
if t.Size != c.ptrSize {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.uintptr
|
|
|
|
|
t.Align = t.Size
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.ArrayType:
|
|
|
|
|
if dt.StrideBitSize > 0 {
|
|
|
|
|
// Cannot represent bit-sized elements in Go.
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.Opaque(t.Size)
|
|
|
|
|
break
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
gt := &ast.ArrayType{
|
|
|
|
|
Len: c.intExpr(dt.Count),
|
2009-12-15 15:33:31 -08:00
|
|
|
}
|
|
|
|
|
t.Go = gt // publish before recursive call
|
2012-02-06 20:38:54 +01:00
|
|
|
sub := c.Type(dt.Type, pos)
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Align = sub.Align
|
|
|
|
|
gt.Elt = sub.Go
|
2013-10-22 18:33:23 -04:00
|
|
|
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
|
2009-09-24 11:43:19 -07:00
|
|
|
|
2010-01-13 10:25:28 -08:00
|
|
|
case *dwarf.BoolType:
|
|
|
|
|
t.Go = c.bool
|
2012-11-21 13:04:38 -08:00
|
|
|
t.Align = 1
|
2010-01-13 10:25:28 -08:00
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
case *dwarf.CharType:
|
|
|
|
|
if t.Size != 1 {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.int8
|
|
|
|
|
t.Align = 1
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.EnumType:
|
2011-02-08 23:50:14 -05:00
|
|
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
|
|
|
|
t.Align = c.ptrSize
|
|
|
|
|
}
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
t.C.Set("enum " + dt.EnumName)
|
2011-02-08 23:50:14 -05:00
|
|
|
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) {
|
2009-09-24 11:43:19 -07:00
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
case 1:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint8
|
2009-09-24 11:43:19 -07:00
|
|
|
case 2:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint16
|
2009-09-24 11:43:19 -07:00
|
|
|
case 4:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint32
|
2009-09-24 11:43:19 -07:00
|
|
|
case 8:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint64
|
2011-02-08 23:50:14 -05:00
|
|
|
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
|
2009-12-15 21:24:17 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.FloatType:
|
|
|
|
|
switch t.Size {
|
|
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
case 4:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.float32
|
2009-09-24 11:43:19 -07:00
|
|
|
case 8:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.float64
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Align = c.ptrSize
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-19 14:30:57 -05:00
|
|
|
case *dwarf.ComplexType:
|
|
|
|
|
switch t.Size {
|
|
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
|
2011-01-19 14:30:57 -05:00
|
|
|
case 8:
|
|
|
|
|
t.Go = c.complex64
|
|
|
|
|
case 16:
|
|
|
|
|
t.Go = c.complex128
|
|
|
|
|
}
|
|
|
|
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
|
|
|
|
t.Align = c.ptrSize
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
case *dwarf.FuncType:
|
|
|
|
|
// No attempt at translation: would enable calls
|
|
|
|
|
// directly between worlds, but we need to moderate those.
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.uintptr
|
|
|
|
|
t.Align = c.ptrSize
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.IntType:
|
|
|
|
|
if dt.BitSize > 0 {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
switch t.Size {
|
|
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
case 1:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.int8
|
2009-09-24 11:43:19 -07:00
|
|
|
case 2:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.int16
|
2009-09-24 11:43:19 -07:00
|
|
|
case 4:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.int32
|
2009-09-24 11:43:19 -07:00
|
|
|
case 8:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.int64
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Align = c.ptrSize
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case *dwarf.PtrType:
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Align = c.ptrSize
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
// Translate void* as unsafe.Pointer
|
|
|
|
|
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.unsafePointer
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
t.C.Set("void*")
|
2009-12-15 15:33:31 -08:00
|
|
|
break
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2009-12-15 15:33:31 -08:00
|
|
|
gt := &ast.StarExpr{}
|
|
|
|
|
t.Go = gt // publish before recursive call
|
2012-02-06 20:38:54 +01:00
|
|
|
sub := c.Type(dt.Type, pos)
|
2009-12-15 15:33:31 -08:00
|
|
|
gt.X = sub.Go
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
t.C.Set("%s*", sub.C)
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.QualType:
|
|
|
|
|
// Ignore qualifier.
|
2012-02-06 20:38:54 +01:00
|
|
|
t = c.Type(dt.Type, pos)
|
2009-12-15 15:33:31 -08:00
|
|
|
c.m[dtype] = t
|
|
|
|
|
return t
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.StructType:
|
|
|
|
|
// Convert to Go struct, being careful about alignment.
|
|
|
|
|
// Have to give it a name to simulate C "struct foo" references.
|
2009-12-15 15:33:31 -08:00
|
|
|
tag := dt.StructName
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
|
|
|
|
|
break
|
|
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
if tag == "" {
|
2010-12-13 13:20:04 -05:00
|
|
|
tag = "__" + strconv.Itoa(tagGen)
|
|
|
|
|
tagGen++
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
} else if t.C.Empty() {
|
|
|
|
|
t.C.Set(dt.Kind + " " + tag)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = name // publish before recursive calls
|
2011-11-10 19:08:04 -05:00
|
|
|
goIdent[name.Name] = name
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
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
|
|
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
switch dt.Kind {
|
2012-09-22 07:25:41 +10:00
|
|
|
case "class", "union":
|
2012-02-22 17:10:25 -02:00
|
|
|
t.Go = c.Opaque(t.Size)
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
if t.C.Empty() {
|
2013-10-22 18:33:23 -04:00
|
|
|
t.C.Set("__typeof__(unsigned char[%d])", t.Size)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2012-09-22 07:25:41 +10:00
|
|
|
t.Align = 1 // TODO: should probably base this on field alignment.
|
2012-02-19 13:32:55 -05:00
|
|
|
typedef[name.Name] = t
|
2009-09-24 11:43:19 -07:00
|
|
|
case "struct":
|
2012-02-06 20:38:54 +01:00
|
|
|
g, csyntax, align := c.Struct(dt, pos)
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
if t.C.Empty() {
|
|
|
|
|
t.C.Set(csyntax)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Align = align
|
2012-02-19 13:32:55 -05:00
|
|
|
tt := *t
|
|
|
|
|
if tag != "" {
|
|
|
|
|
tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
|
|
|
|
|
}
|
|
|
|
|
tt.Go = g
|
|
|
|
|
typedef[name.Name] = &tt
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.string
|
|
|
|
|
t.Size = c.ptrSize * 2
|
|
|
|
|
t.Align = c.ptrSize
|
|
|
|
|
break
|
|
|
|
|
}
|
2011-07-28 12:39:50 -04:00
|
|
|
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
|
|
|
|
|
}
|
2011-11-10 19:08:04 -05:00
|
|
|
name := c.Ident("_Ctype_" + dt.Name)
|
|
|
|
|
goIdent[name.Name] = name
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = name // publish before recursive call
|
2012-02-06 20:38:54 +01:00
|
|
|
sub := c.Type(dt.Type, pos)
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Size = sub.Size
|
|
|
|
|
t.Align = sub.Align
|
2014-06-02 12:55:43 -07:00
|
|
|
oldType := typedef[name.Name]
|
|
|
|
|
if oldType == nil {
|
2012-02-19 13:32:55 -05:00
|
|
|
tt := *t
|
|
|
|
|
tt.Go = sub.Go
|
|
|
|
|
typedef[name.Name] = &tt
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
// In -godefs and -cdefs mode, do this for all typedefs.
|
|
|
|
|
if isStructUnionClass(sub.Go) || *godefs || *cdefs {
|
2011-11-10 19:08:04 -05:00
|
|
|
t.Go = sub.Go
|
2014-06-02 12:55:43 -07:00
|
|
|
|
2014-06-05 10:42:03 -07:00
|
|
|
if isStructUnionClass(sub.Go) {
|
|
|
|
|
// Use the typedef name for C code.
|
|
|
|
|
typedef[sub.Go.(*ast.Ident).Name].C = t.C
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-02 12:55:43 -07:00
|
|
|
// 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
|
|
|
|
|
}
|
2011-11-10 19:08:04 -05:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.UcharType:
|
|
|
|
|
if t.Size != 1 {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
t.Go = c.uint8
|
|
|
|
|
t.Align = 1
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
case *dwarf.UintType:
|
|
|
|
|
if dt.BitSize > 0 {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
switch t.Size {
|
|
|
|
|
default:
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
case 1:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint8
|
2009-09-24 11:43:19 -07:00
|
|
|
case 2:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint16
|
2009-09-24 11:43:19 -07:00
|
|
|
case 4:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint32
|
2009-09-24 11:43:19 -07:00
|
|
|
case 8:
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Go = c.uint64
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
if t.Align = t.Size; t.Align >= c.ptrSize {
|
2009-11-09 12:07:39 -08:00
|
|
|
t.Align = c.ptrSize
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case *dwarf.VoidType:
|
2012-12-18 00:26:08 +08:00
|
|
|
t.Go = c.goVoid
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
t.C.Set("void")
|
2012-12-18 00:26:08 +08:00
|
|
|
t.Align = 1
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch dtype.(type) {
|
2010-01-13 10:25:28 -08:00
|
|
|
case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
|
2009-12-15 15:33:31 -08:00
|
|
|
s := dtype.Common().Name
|
2009-09-24 11:43:19 -07:00
|
|
|
if s != "" {
|
2010-07-14 17:17:53 -07:00
|
|
|
if ss, ok := dwarfToName[s]; ok {
|
2009-11-09 12:07:39 -08:00
|
|
|
s = ss
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2011-06-28 09:43:14 +10:00
|
|
|
s = strings.Join(strings.Split(s, " "), "") // strip spaces
|
2010-07-14 17:17:53 -07:00
|
|
|
name := c.Ident("_Ctype_" + s)
|
2012-02-19 13:32:55 -05:00
|
|
|
tt := *t
|
|
|
|
|
typedef[name.Name] = &tt
|
2011-11-10 19:08:04 -05:00
|
|
|
if !*godefs && !*cdefs {
|
|
|
|
|
t.Go = name
|
|
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 15:24:51 -05:00
|
|
|
if t.Size <= 0 {
|
|
|
|
|
// Clang does not record the size of a pointer in its DWARF entry,
|
|
|
|
|
// so if dtype is an array, the call to dtype.Size at the top of the function
|
|
|
|
|
// computed the size as the array length * 0 = 0.
|
|
|
|
|
// The type switch called Type (this function) recursively on the pointer
|
|
|
|
|
// entry, and the code near the top of the function updated the size to
|
|
|
|
|
// be correct, so calling dtype.Size again will produce the correct value.
|
|
|
|
|
t.Size = dtype.Size()
|
|
|
|
|
if t.Size < 0 {
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
// 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.
|
2013-11-07 15:24:51 -05:00
|
|
|
t.Size = 0
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
switch dt := dtype.(type) {
|
|
|
|
|
case *dwarf.TypedefType:
|
|
|
|
|
// ok
|
|
|
|
|
case *dwarf.StructType:
|
|
|
|
|
if dt.StructName != "" {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
t.Go = c.Opaque(0)
|
|
|
|
|
default:
|
2014-03-27 20:23:16 +00:00
|
|
|
t.Go = c.Opaque(0)
|
|
|
|
|
}
|
2013-11-07 15:24:51 -05:00
|
|
|
if t.C.Empty() {
|
|
|
|
|
t.C.Set("void")
|
|
|
|
|
}
|
|
|
|
|
return t
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
if t.C.Empty() {
|
2012-02-06 20:38:54 +01:00
|
|
|
fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2009-12-15 15:33:31 -08:00
|
|
|
return t
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
cmd/cgo: given typedef struct S T, make C.T and C.struct_S interchangeable
For incomplete struct S, C.T and C.struct_S were interchangeable in Go 1.2
and earlier, because all incomplete types were interchangeable
(even C.struct_S1 and C.struct_S2).
CL 76450043, which fixed issue 7409, made different incomplete types
different from Go's point of view, so that they were no longer completely
interchangeable.
However, imprecision about C.T and C.struct_S - really the same
underlying C type - is the one behavior enabled by the bug that
is most likely to be depended on by existing cgo code.
Explicitly allow it, to keep that code working.
Fixes #7786.
LGTM=iant, r
R=golang-codereviews, iant, r
CC=golang-codereviews
https://golang.org/cl/98580046
2014-05-28 14:04:31 -04:00
|
|
|
// 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_")
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-24 11:43:19 -07:00
|
|
|
// FuncArg returns a Go type with the same memory layout as
|
|
|
|
|
// dtype when used as the type of a C function argument.
|
2012-02-06 20:38:54 +01:00
|
|
|
func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
|
|
|
|
t := c.Type(dtype, pos)
|
2009-09-24 11:43:19 -07:00
|
|
|
switch dt := dtype.(type) {
|
|
|
|
|
case *dwarf.ArrayType:
|
|
|
|
|
// Arrays are passed implicitly as pointers in C.
|
|
|
|
|
// In Go, we must be explicit.
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
tr := &TypeRepr{}
|
|
|
|
|
tr.Set("%s*", t.C)
|
2009-09-24 11:43:19 -07:00
|
|
|
return &Type{
|
2010-03-02 13:46:51 -08:00
|
|
|
Size: c.ptrSize,
|
2009-09-24 11:43:19 -07:00
|
|
|
Align: c.ptrSize,
|
2010-03-02 13:46:51 -08:00
|
|
|
Go: &ast.StarExpr{X: t.Go},
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
C: tr,
|
2009-11-09 12:07:39 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
case *dwarf.TypedefType:
|
|
|
|
|
// C has much more relaxed rules than Go for
|
|
|
|
|
// implicit type conversions. When the parameter
|
|
|
|
|
// 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 {
|
2009-11-17 23:42:21 -08:00
|
|
|
// Unless the typedef happens to point to void* since
|
|
|
|
|
// Go has special rules around using unsafe.Pointer.
|
2012-02-19 13:32:55 -05:00
|
|
|
if _, void := base(ptr.Type).(*dwarf.VoidType); void {
|
|
|
|
|
break
|
2009-11-17 23:42:21 -08:00
|
|
|
}
|
2012-02-19 13:32:55 -05:00
|
|
|
|
|
|
|
|
t = c.Type(ptr, pos)
|
|
|
|
|
if t == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remember the C spelling, in case the struct
|
|
|
|
|
// has __attribute__((unavailable)) on it. See issue 2888.
|
|
|
|
|
t.Typedef = dt.Name
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
return t
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FuncType returns the Go type analogous to dtype.
|
|
|
|
|
// There is no guarantee about matching memory layout.
|
2013-10-15 21:35:52 -04:00
|
|
|
func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
|
2009-12-15 15:33:31 -08:00
|
|
|
p := make([]*Type, len(dtype.ParamType))
|
|
|
|
|
gp := make([]*ast.Field, len(dtype.ParamType))
|
2009-09-24 11:43:19 -07:00
|
|
|
for i, f := range dtype.ParamType {
|
2009-11-23 22:02:12 -08:00
|
|
|
// gcc's DWARF generator outputs a single DotDotDotType parameter for
|
|
|
|
|
// function pointers that specify no parameters (e.g. void
|
|
|
|
|
// (*__cgo_0)()). Treat this special case as void. This case is
|
|
|
|
|
// invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
|
|
|
|
|
// legal).
|
|
|
|
|
if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
|
2009-12-15 15:33:31 -08:00
|
|
|
p, gp = nil, nil
|
|
|
|
|
break
|
2009-11-23 22:02:12 -08:00
|
|
|
}
|
2012-02-06 20:38:54 +01:00
|
|
|
p[i] = c.FuncArg(f, pos)
|
2009-12-15 15:33:31 -08:00
|
|
|
gp[i] = &ast.Field{Type: p[i].Go}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
var r *Type
|
|
|
|
|
var gr []*ast.Field
|
2012-12-18 00:26:08 +08:00
|
|
|
if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
|
|
|
|
|
gr = []*ast.Field{{Type: c.goVoid}}
|
|
|
|
|
} else if dtype.ReturnType != nil {
|
2012-02-06 20:38:54 +01:00
|
|
|
r = c.Type(dtype.ReturnType, pos)
|
2011-12-02 14:14:25 -05:00
|
|
|
gr = []*ast.Field{{Type: r.Go}}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
return &FuncType{
|
|
|
|
|
Params: p,
|
|
|
|
|
Result: r,
|
|
|
|
|
Go: &ast.FuncType{
|
2010-03-02 13:46:51 -08:00
|
|
|
Params: &ast.FieldList{List: gp},
|
2010-02-24 16:17:11 -08:00
|
|
|
Results: &ast.FieldList{List: gr},
|
2009-11-05 15:33:26 -08:00
|
|
|
},
|
2009-12-15 15:33:31 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Identifier
|
2010-07-14 17:17:53 -07:00
|
|
|
func (c *typeConv) Ident(s string) *ast.Ident {
|
|
|
|
|
return ast.NewIdent(s)
|
|
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
|
|
|
|
|
// Opaque type of n bytes.
|
|
|
|
|
func (c *typeConv) Opaque(n int64) ast.Expr {
|
|
|
|
|
return &ast.ArrayType{
|
|
|
|
|
Len: c.intExpr(n),
|
2009-11-05 15:33:26 -08:00
|
|
|
Elt: c.byte,
|
2009-11-09 12:07:39 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Expr for integer n.
|
|
|
|
|
func (c *typeConv) intExpr(n int64) ast.Expr {
|
|
|
|
|
return &ast.BasicLit{
|
2010-03-02 13:46:51 -08:00
|
|
|
Kind: token.INT,
|
2011-12-05 15:48:46 -05:00
|
|
|
Value: strconv.FormatInt(n, 10),
|
2009-11-09 12:07:39 -08:00
|
|
|
}
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add padding of given size to fld.
|
|
|
|
|
func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
|
2009-12-15 15:33:31 -08:00
|
|
|
n := len(fld)
|
|
|
|
|
fld = fld[0 : n+1]
|
|
|
|
|
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
|
|
|
|
|
return fld
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// Struct conversion: return Go and (6g) C syntax for type.
|
2012-02-06 20:38:54 +01:00
|
|
|
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
|
2010-07-14 17:17:53 -07:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
buf.WriteString("struct {")
|
2009-12-15 15:33:31 -08:00
|
|
|
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
|
|
|
|
|
off := int64(0)
|
2009-11-18 09:59:10 -08:00
|
|
|
|
2010-07-14 17:17:53 -07:00
|
|
|
// Rename struct fields that happen to be named Go keywords into
|
2009-11-18 09:59:10 -08:00
|
|
|
// _{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
|
|
|
|
|
// 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).
|
2009-12-15 15:33:31 -08:00
|
|
|
ident := make(map[string]string)
|
|
|
|
|
used := make(map[string]bool)
|
2009-11-18 09:59:10 -08:00
|
|
|
for _, f := range dt.Field {
|
2009-12-15 15:33:31 -08:00
|
|
|
ident[f.Name] = f.Name
|
|
|
|
|
used[f.Name] = true
|
2009-11-18 09:59:10 -08:00
|
|
|
}
|
|
|
|
|
|
2011-11-10 19:08:04 -05:00
|
|
|
if !*godefs && !*cdefs {
|
|
|
|
|
for cid, goid := range ident {
|
2012-01-11 14:20:32 -08:00
|
|
|
if token.Lookup(goid).IsKeyword() {
|
2011-11-10 19:08:04 -05:00
|
|
|
// Avoid keyword
|
2009-11-18 09:59:10 -08:00
|
|
|
goid = "_" + goid
|
|
|
|
|
|
2011-11-10 19:08:04 -05:00
|
|
|
// Also avoid existing fields
|
|
|
|
|
for _, exist := used[goid]; exist; _, exist = used[goid] {
|
|
|
|
|
goid = "_" + goid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
used[goid] = true
|
|
|
|
|
ident[cid] = goid
|
|
|
|
|
}
|
2009-11-18 09:59:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-10 19:08:04 -05:00
|
|
|
anon := 0
|
2009-09-24 11:43:19 -07:00
|
|
|
for _, f := range dt.Field {
|
|
|
|
|
if f.ByteOffset > off {
|
2009-12-15 15:33:31 -08:00
|
|
|
fld = c.pad(fld, f.ByteOffset-off)
|
|
|
|
|
off = f.ByteOffset
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2012-02-06 20:38:54 +01:00
|
|
|
t := c.Type(f.Type, pos)
|
2011-11-10 19:08:04 -05:00
|
|
|
tgo := t.Go
|
|
|
|
|
size := t.Size
|
2014-05-12 23:48:20 -04:00
|
|
|
talign := t.Align
|
2011-11-10 19:08:04 -05:00
|
|
|
if f.BitSize > 0 {
|
|
|
|
|
if f.BitSize%8 != 0 {
|
|
|
|
|
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))
|
2014-05-12 23:48:20 -04:00
|
|
|
talign = size
|
2011-11-10 19:08:04 -05:00
|
|
|
}
|
|
|
|
|
|
2014-05-12 23:48:20 -04:00
|
|
|
if talign > 0 && f.ByteOffset%talign != 0 {
|
|
|
|
|
// 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
|
|
|
|
|
}
|
2009-12-15 15:33:31 -08:00
|
|
|
n := len(fld)
|
|
|
|
|
fld = fld[0 : n+1]
|
2011-11-10 19:08:04 -05:00
|
|
|
name := f.Name
|
|
|
|
|
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}
|
|
|
|
|
off += size
|
cgo: fix dwarf type parsing
The recursive algorithm used to parse types in cgo
has a bug related to building the C type representation.
As an example, when the recursion starts at a type *T,
the C type representation won't be known until type T
itself is parsed. But then, it is possible that type T
references the type **T internally. The latter
representation is built based on the one of *T, which
started the recursion, so it won't attempt to parse it
again, and will instead use the current representation
value for *T, which is still empty at this point.
This problem was fixed by introducing a simple TypeRepr
type which builds the string representation lazily,
analogous to how the Go type information is built within
the same algorithm. This way, even if a type
representation is still unknown at some level in the
recursion, representations dependant on it can still
be created correctly.
R=rsc
CC=golang-dev
https://golang.org/cl/4244052
2011-03-06 18:05:57 -05:00
|
|
|
buf.WriteString(t.C.String())
|
2010-07-14 17:17:53 -07:00
|
|
|
buf.WriteString(" ")
|
2011-11-10 19:08:04 -05:00
|
|
|
buf.WriteString(name)
|
2010-07-14 17:17:53 -07:00
|
|
|
buf.WriteString("; ")
|
2014-05-12 23:48:20 -04:00
|
|
|
if talign > align {
|
|
|
|
|
align = talign
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if off < dt.ByteSize {
|
2009-12-15 15:33:31 -08:00
|
|
|
fld = c.pad(fld, dt.ByteSize-off)
|
|
|
|
|
off = dt.ByteSize
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
|
|
|
|
if off != dt.ByteSize {
|
2012-02-19 13:32:55 -05:00
|
|
|
fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2010-07-14 17:17:53 -07:00
|
|
|
buf.WriteString("}")
|
|
|
|
|
csyntax = buf.String()
|
2011-11-10 19:08:04 -05:00
|
|
|
|
|
|
|
|
if *godefs || *cdefs {
|
|
|
|
|
godefsFields(fld)
|
|
|
|
|
}
|
2010-02-24 16:17:11 -08:00
|
|
|
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
|
2009-12-15 15:33:31 -08:00
|
|
|
return
|
2009-09-24 11:43:19 -07:00
|
|
|
}
|
2011-11-10 19:08:04 -05:00
|
|
|
|
|
|
|
|
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 {
|
2013-02-01 08:41:25 -08:00
|
|
|
if n.Name != prefix {
|
|
|
|
|
n.Name = strings.TrimPrefix(n.Name, prefix)
|
2011-11-10 19:08:04 -05:00
|
|
|
}
|
|
|
|
|
if n.Name == "_" {
|
|
|
|
|
// Use exported name instead.
|
|
|
|
|
n.Name = "Pad_cgo_" + strconv.Itoa(npad)
|
|
|
|
|
npad++
|
|
|
|
|
}
|
|
|
|
|
if !*cdefs {
|
|
|
|
|
n.Name = upper(n.Name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p := &f.Type
|
|
|
|
|
t := *p
|
|
|
|
|
if star, ok := t.(*ast.StarExpr); ok {
|
|
|
|
|
star = &ast.StarExpr{X: star.X}
|
|
|
|
|
*p = star
|
|
|
|
|
p = &star.X
|
|
|
|
|
t = *p
|
|
|
|
|
}
|
|
|
|
|
if id, ok := t.(*ast.Ident); ok {
|
|
|
|
|
if id.Name == "unsafe.Pointer" {
|
|
|
|
|
*p = ast.NewIdent("*byte")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fieldPrefix returns the prefix that should be removed from all the
|
2012-10-30 13:38:01 -07:00
|
|
|
// field names when generating the C or Go code. For generated
|
2011-11-10 19:08:04 -05:00
|
|
|
// 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 {
|
|
|
|
|
if *cdefs {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
prefix := ""
|
|
|
|
|
for _, f := range fld {
|
|
|
|
|
for _, n := range f.Names {
|
|
|
|
|
// Ignore field names that don't have the prefix we're
|
|
|
|
|
// looking for. It is common in C headers to have fields
|
|
|
|
|
// 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.
|
2012-10-30 13:38:01 -07:00
|
|
|
// The check for "orig_" here handles orig_eax in the
|
2011-11-10 19:08:04 -05:00
|
|
|
// x86 ptrace register sets, which otherwise have all fields
|
|
|
|
|
// with reg_ prefixes.
|
|
|
|
|
if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
i := strings.Index(n.Name, "_")
|
|
|
|
|
if i < 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if prefix == "" {
|
|
|
|
|
prefix = n.Name[:i+1]
|
|
|
|
|
} else if prefix != n.Name[:i+1] {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return prefix
|
|
|
|
|
}
|