]> Cypherpunks repositories - gostls13.git/commitdiff
This patch enables cgo utility to correctly convert enums in the C source
authorMoriyoshi Koizumi <mozo@mozo.jp>
Wed, 16 Dec 2009 05:24:17 +0000 (21:24 -0800)
committerRuss Cox <rsc@golang.org>
Wed, 16 Dec 2009 05:24:17 +0000 (21:24 -0800)
into consts in the resulting Go source.  Previously known as issue 161047,
which I deleted accidentally.  Fixes issue 207.

R=rsc
https://golang.org/cl/166059

AUTHORS
CONTRIBUTORS
src/cmd/cgo/ast.go
src/cmd/cgo/gcc.go
src/cmd/cgo/main.go
src/cmd/cgo/out.go

diff --git a/AUTHORS b/AUTHORS
index 421683155b79d17f38cf5d62acc04e8f2f17d486..7b17b2dd9ce83755a892e26ed314c0b7509e36af 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,7 @@ Kei Son <hey.calmdown@gmail.com>
 Kevin Ballard <kevin@sb.org>
 Michael Elkins <michael.elkins@gmail.com>
 Michael Hoisie <hoisie@gmail.com>
+Moriyoshi Koizumi <mozo@mozo.jp>
 Môshe van der Sterre <moshevds@gmail.com>
 Peter Froehlich <peter.hans.froehlich@gmail.com>
 Roger Peppe <rogpeppe@gmail.com>
index 24950031e456e7f3fc411dbc1cb9fca460eaa0d3..71dd22e1801130929727edca49d4b3e9c2254514 100644 (file)
@@ -69,6 +69,7 @@ Larry Hosken <lahosken@golang.org>
 Maxim Ushakov <ushakov@google.com>
 Michael Elkins <michael.elkins@gmail.com>
 Michael Hoisie <hoisie@gmail.com>
+Moriyoshi Koizumi <mozo@mozo.jp>
 Môshe van der Sterre <moshevds@gmail.com>
 Nigel Tao <nigeltao@golang.org>
 Peter Froehlich <peter.hans.froehlich@gmail.com>
index b309c33d46ec932145df3a42cd6c681027d1f060..301516c43a880e2a33df1c0508c741ad93986685 100644 (file)
@@ -35,16 +35,18 @@ type Prog struct {
        Typedef     map[string]ast.Expr
        Vardef      map[string]*Type
        Funcdef     map[string]*FuncType
+       Enumdef     map[string]int64
        PtrSize     int64
        GccOptions  []string
 }
 
 // A Type collects information about a type in both the C and Go worlds.
 type Type struct {
-       Size  int64
-       Align int64
-       C     string
-       Go    ast.Expr
+       Size       int64
+       Align      int64
+       C          string
+       Go         ast.Expr
+       EnumValues map[string]int64
 }
 
 // A FuncType collects information about a function type in both the C and Go worlds.
index c42cb73003aa0867b67325dfc5c2145a7a4853cf..07bfa8ab65681e16b2ff220bbbf7a3d0b132251b 100644 (file)
@@ -120,6 +120,7 @@ func (p *Prog) loadDebugInfo() {
 
        // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
        types := make([]dwarf.Type, len(names))
+       enums := make([]dwarf.Offset, len(names))
        r := d.Reader()
        for {
                e, err := r.Next()
@@ -129,32 +130,56 @@ func (p *Prog) loadDebugInfo() {
                if e == nil {
                        break
                }
-               if e.Tag != dwarf.TagVariable {
-                       goto Continue
-               }
-               name, _ := e.Val(dwarf.AttrName).(string)
-               typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
-               if name == "" || typOff == 0 {
-                       fatal("malformed DWARF TagVariable entry")
-               }
-               if !strings.HasPrefix(name, "__cgo__") {
-                       goto Continue
-               }
-               typ, err := d.Type(typOff)
-               if err != nil {
-                       fatal("loading DWARF type: %s", err)
-               }
-               t, ok := typ.(*dwarf.PtrType)
-               if !ok || t == nil {
-                       fatal("internal error: %s has non-pointer type", name)
-               }
-               i, err := strconv.Atoi(name[7:])
-               if err != nil {
-                       fatal("malformed __cgo__ name: %s", name)
+               switch e.Tag {
+               case dwarf.TagEnumerationType:
+                       offset := e.Offset
+                       for {
+                               e, err := r.Next()
+                               if err != nil {
+                                       fatal("reading DWARF entry: %s", err)
+                               }
+                               if e.Tag == 0 {
+                                       break
+                               }
+                               if e.Tag == dwarf.TagEnumerator {
+                                       entryName := e.Val(dwarf.AttrName).(string)
+                                       i, ok := m[entryName]
+                                       if ok {
+                                               enums[i] = offset
+                                       }
+                               }
+                       }
+               case dwarf.TagVariable:
+                       name, _ := e.Val(dwarf.AttrName).(string)
+                       typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
+                       if name == "" || typOff == 0 {
+                               fatal("malformed DWARF TagVariable entry")
+                       }
+                       if !strings.HasPrefix(name, "__cgo__") {
+                               break
+                       }
+                       typ, err := d.Type(typOff)
+                       if err != nil {
+                               fatal("loading DWARF type: %s", err)
+                       }
+                       t, ok := typ.(*dwarf.PtrType)
+                       if !ok || t == nil {
+                               fatal("internal error: %s has non-pointer type", name)
+                       }
+                       i, err := strconv.Atoi(name[7:])
+                       if err != nil {
+                               fatal("malformed __cgo__ name: %s", name)
+                       }
+                       if enums[i] != 0 {
+                               t, err := d.Type(enums[i])
+                               if err != nil {
+                                       fatal("loading DWARF type: %s", err)
+                               }
+                               types[i] = t
+                       } else {
+                               types[i] = t.Type
+                       }
                }
-               types[i] = t.Type
-
-       Continue:
                if e.Tag != dwarf.TagCompileUnit {
                        r.SkipChildren()
                }
@@ -315,6 +340,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
        t.Size = dtype.Size()
        t.Align = -1
        t.C = dtype.Common().Name
+       t.EnumValues = nil
        c.m[dtype] = t
        if t.Size < 0 {
                // Unsized types are [0]byte
@@ -376,6 +402,10 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                        t.Align = c.ptrSize
                }
                t.C = "enum " + dt.EnumName
+               t.EnumValues = make(map[string]int64)
+               for _, ev := range dt.Val {
+                       t.EnumValues[ev.Name] = ev.Val
+               }
 
        case *dwarf.FloatType:
                switch t.Size {
index 373df3ba25c9315bab1e7a9a4608ea2365b3a92e..5aa17397bda7d66df98bfaaf1a4c3a53fc54b272 100644 (file)
@@ -71,6 +71,7 @@ func main() {
        p.loadDebugInfo()
        p.Vardef = make(map[string]*Type)
        p.Funcdef = make(map[string]*FuncType)
+       p.Enumdef = make(map[string]int64)
 
        for _, cref := range p.Crefs {
                switch cref.Context {
@@ -86,6 +87,14 @@ func main() {
                        if cref.TypeName {
                                error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name)
                        }
+                       // If the expression refers to an enumerated value, then
+                       // place the identifier for the value and add it to Enumdef so
+                       // it will be declared as a constant in the later stage.
+                       if cref.Type.EnumValues != nil {
+                               *cref.Expr = &ast.Ident{Value: cref.Name}
+                               p.Enumdef[cref.Name] = cref.Type.EnumValues[cref.Name]
+                               break
+                       }
                        // Reference to C variable.
                        // We declare a pointer and arrange to have it filled in.
                        *cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}}
index 9c85bc5985da1fa79ae61be316330dbe0cacf9a0..2b42edbe099b59406e42acb41b2b0af20296a398 100644 (file)
@@ -69,6 +69,11 @@ func (p *Prog) writeOutput(srcfile string) {
        }
        fmt.Fprintf(fc, "\n")
 
+       for name, value := range p.Enumdef {
+               fmt.Fprintf(fgo2, "const %s = %d\n", name, value)
+       }
+       fmt.Fprintf(fgo2, "\n")
+
        for name, def := range p.Funcdef {
                // Go func declaration.
                d := &ast.FuncDecl{