summaryrefslogtreecommitdiffstats
path: root/llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go
diff options
context:
space:
mode:
Diffstat (limited to 'llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go')
-rw-r--r--llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go101
1 files changed, 59 insertions, 42 deletions
diff --git a/llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go b/llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go
index abdd369d713..e0b89ec14cb 100644
--- a/llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go
+++ b/llgo/third_party/gofrontend/libgo/go/cmd/cgo/gcc.go
@@ -154,20 +154,6 @@ func splitQuoted(s string) (r []string, err error) {
return args, err
}
-var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
-
-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
-}
-
// 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.
@@ -213,6 +199,10 @@ func (p *Package) loadDefines(f *File) {
val = strings.TrimSpace(line[tabIndex:])
}
+ if key == "__clang__" {
+ p.GccIsClang = true
+ }
+
if n := f.Name[key]; n != nil {
if *debugDefine {
fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
@@ -500,6 +490,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
name, _ := e.Val(dwarf.AttrName).(string)
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
if name == "" || typOff == 0 {
+ if e.Val(dwarf.AttrSpecification) != nil {
+ // Since we are reading all the DWARF,
+ // assume we will see the variable elsewhere.
+ break
+ }
fatalf("malformed DWARF TagVariable entry")
}
if !strings.HasPrefix(name, "__cgo__") {
@@ -582,7 +577,7 @@ func (p *Package) mangleName(n *Name) {
// 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
-// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
+// the xxx. In *godefs mode, rewriteRef replaces the names
// with full definitions instead of mangled names.
func (p *Package) rewriteRef(f *File) {
// Keep a list of all the functions, to remove the ones
@@ -673,6 +668,13 @@ func (p *Package) rewriteRef(f *File) {
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
}
+ case "selector":
+ if r.Name.Kind == "var" {
+ expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
+ } else {
+ error_(r.Pos(), "only C variables allowed in selector expression", fixGo(r.Name.Go))
+ }
+
case "type":
if r.Name.Kind != "type" {
error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
@@ -688,7 +690,7 @@ func (p *Package) rewriteRef(f *File) {
error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
}
}
- if *godefs || *cdefs {
+ if *godefs {
// Substitute definition for mangled type name.
if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil {
@@ -746,6 +748,10 @@ func (p *Package) gccMachine() []string {
return []string{"-m32"}
case "arm":
return []string{"-marm"} // not thumb
+ case "s390":
+ return []string{"-m31"}
+ case "s390x":
+ return []string{"-m64"}
}
return nil
}
@@ -765,7 +771,7 @@ func (p *Package) gccCmd() []string {
"-c", // do not link
"-xc", // input language is C
)
- if strings.Contains(c[0], "clang") {
+ if p.GccIsClang {
c = append(c,
"-ferror-limit=0",
// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
@@ -780,7 +786,7 @@ func (p *Package) gccCmd() []string {
// 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.
+ // See: https://golang.org/issue/6506.
"-fno-builtin",
)
}
@@ -992,8 +998,8 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.goVoid = c.Ident("_Ctype_void")
// Normally cgo translates void* to unsafe.Pointer,
- // but for historical reasons -cdefs and -godefs use *byte instead.
- if *cdefs || *godefs {
+ // but for historical reasons -godefs uses *byte instead.
+ if *godefs {
c.goVoidPtr = &ast.StarExpr{X: c.byte}
} else {
c.goVoidPtr = c.Ident("unsafe.Pointer")
@@ -1045,7 +1051,7 @@ func (tr *TypeRepr) String() string {
return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
}
-// Empty returns true if the result of String would be "".
+// Empty reports whether the result of String would be "".
func (tr *TypeRepr) Empty() bool {
return len(tr.Repr) == 0
}
@@ -1334,8 +1340,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// 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 {
+ // In -godefs mode, do this for all typedefs.
+ if isStructUnionClass(sub.Go) || *godefs {
t.Go = sub.Go
if isStructUnionClass(sub.Go) {
@@ -1397,7 +1403,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
name := c.Ident("_Ctype_" + s)
tt := *t
typedef[name.Name] = &tt
- if !*godefs && !*cdefs {
+ if !*godefs {
t.Go = name
}
}
@@ -1543,14 +1549,16 @@ func (c *typeConv) intExpr(n int64) ast.Expr {
}
// Add padding of given size to fld.
-func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
+func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
n := len(fld)
fld = fld[0 : n+1]
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
- return fld
+ sizes = sizes[0 : n+1]
+ sizes[n] = size
+ return fld, sizes
}
-// Struct conversion: return Go and (6g) C syntax for type.
+// Struct conversion: return Go and (gc) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
// Minimum alignment for a struct is 1 byte.
align = 1
@@ -1558,6 +1566,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
var buf bytes.Buffer
buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
+ sizes := make([]int64, 0, 2*len(dt.Field)+1)
off := int64(0)
// Rename struct fields that happen to be named Go keywords into
@@ -1573,7 +1582,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
used[f.Name] = true
}
- if !*godefs && !*cdefs {
+ if !*godefs {
for cid, goid := range ident {
if token.Lookup(goid).IsKeyword() {
// Avoid keyword
@@ -1593,19 +1602,19 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
anon := 0
for _, f := range dt.Field {
if f.ByteOffset > off {
- fld = c.pad(fld, f.ByteOffset-off)
+ fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
off = f.ByteOffset
}
name := f.Name
ft := f.Type
- // In godefs or cdefs mode, if this field is a C11
+ // In godefs mode, if this field is a C11
// anonymous union then treat the first field in the
// union as the field in the struct. This handles
// cases like the glibc <sys/resource.h> file; see
// issue 6677.
- if *godefs || *cdefs {
+ if *godefs {
if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
name = st.Field[0].Name
ident[name] = name
@@ -1635,14 +1644,12 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
talign = size
}
- if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs {
+ 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.
- // Exception: In -cdefs mode, we use #pragma pack, so misaligned
- // fields should still work.
continue
}
n := len(fld)
@@ -1653,6 +1660,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
ident[name] = name
}
fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
+ sizes = sizes[0 : n+1]
+ sizes[n] = size
off += size
buf.WriteString(t.C.String())
buf.WriteString(" ")
@@ -1663,16 +1672,29 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
}
}
if off < dt.ByteSize {
- fld = c.pad(fld, dt.ByteSize-off)
+ fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
off = dt.ByteSize
}
+
+ // If the last field in a non-zero-sized struct is zero-sized
+ // the compiler is going to pad it by one (see issue 9401).
+ // We can't permit that, because then the size of the Go
+ // struct will not be the same as the size of the C struct.
+ // Our only option in such a case is to remove the field,
+ // which means that it can not be referenced from Go.
+ for off > 0 && sizes[len(sizes)-1] == 0 {
+ n := len(sizes)
+ fld = fld[0 : n-1]
+ sizes = sizes[0 : n-1]
+ }
+
if off != dt.ByteSize {
fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
}
buf.WriteString("}")
csyntax = buf.String()
- if *godefs || *cdefs {
+ if *godefs {
godefsFields(fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
@@ -1707,9 +1729,7 @@ func godefsFields(fld []*ast.Field) {
n.Name = "Pad_cgo_" + strconv.Itoa(npad)
npad++
}
- if !*cdefs {
- n.Name = upper(n.Name)
- }
+ n.Name = upper(n.Name)
}
}
}
@@ -1721,9 +1741,6 @@ func godefsFields(fld []*ast.Field) {
// 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 {
OpenPOWER on IntegriCloud