1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:54:42 -07:00

This patch enables cgo utility to correctly convert enums in the C source

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
This commit is contained in:
Moriyoshi Koizumi 2009-12-15 21:24:17 -08:00 committed by Russ Cox
parent 52114724b7
commit a8fbf5dc2c
6 changed files with 77 additions and 29 deletions

View File

@ -35,6 +35,7 @@ Kei Son <hey.calmdown@gmail.com>
Kevin Ballard <kevin@sb.org> Kevin Ballard <kevin@sb.org>
Michael Elkins <michael.elkins@gmail.com> Michael Elkins <michael.elkins@gmail.com>
Michael Hoisie <hoisie@gmail.com> Michael Hoisie <hoisie@gmail.com>
Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com> Môshe van der Sterre <moshevds@gmail.com>
Peter Froehlich <peter.hans.froehlich@gmail.com> Peter Froehlich <peter.hans.froehlich@gmail.com>
Roger Peppe <rogpeppe@gmail.com> Roger Peppe <rogpeppe@gmail.com>

View File

@ -69,6 +69,7 @@ Larry Hosken <lahosken@golang.org>
Maxim Ushakov <ushakov@google.com> Maxim Ushakov <ushakov@google.com>
Michael Elkins <michael.elkins@gmail.com> Michael Elkins <michael.elkins@gmail.com>
Michael Hoisie <hoisie@gmail.com> Michael Hoisie <hoisie@gmail.com>
Moriyoshi Koizumi <mozo@mozo.jp>
Môshe van der Sterre <moshevds@gmail.com> Môshe van der Sterre <moshevds@gmail.com>
Nigel Tao <nigeltao@golang.org> Nigel Tao <nigeltao@golang.org>
Peter Froehlich <peter.hans.froehlich@gmail.com> Peter Froehlich <peter.hans.froehlich@gmail.com>

View File

@ -35,6 +35,7 @@ type Prog struct {
Typedef map[string]ast.Expr Typedef map[string]ast.Expr
Vardef map[string]*Type Vardef map[string]*Type
Funcdef map[string]*FuncType Funcdef map[string]*FuncType
Enumdef map[string]int64
PtrSize int64 PtrSize int64
GccOptions []string GccOptions []string
} }
@ -45,6 +46,7 @@ type Type struct {
Align int64 Align int64
C string C string
Go ast.Expr Go ast.Expr
EnumValues map[string]int64
} }
// A FuncType collects information about a function type in both the C and Go worlds. // A FuncType collects information about a function type in both the C and Go worlds.

View File

@ -120,6 +120,7 @@ func (p *Prog) loadDebugInfo() {
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i. // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
types := make([]dwarf.Type, len(names)) types := make([]dwarf.Type, len(names))
enums := make([]dwarf.Offset, len(names))
r := d.Reader() r := d.Reader()
for { for {
e, err := r.Next() e, err := r.Next()
@ -129,16 +130,33 @@ func (p *Prog) loadDebugInfo() {
if e == nil { if e == nil {
break break
} }
if e.Tag != dwarf.TagVariable { switch e.Tag {
goto Continue 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) name, _ := e.Val(dwarf.AttrName).(string)
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
if name == "" || typOff == 0 { if name == "" || typOff == 0 {
fatal("malformed DWARF TagVariable entry") fatal("malformed DWARF TagVariable entry")
} }
if !strings.HasPrefix(name, "__cgo__") { if !strings.HasPrefix(name, "__cgo__") {
goto Continue break
} }
typ, err := d.Type(typOff) typ, err := d.Type(typOff)
if err != nil { if err != nil {
@ -152,9 +170,16 @@ func (p *Prog) loadDebugInfo() {
if err != nil { if err != nil {
fatal("malformed __cgo__ name: %s", name) 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 { if e.Tag != dwarf.TagCompileUnit {
r.SkipChildren() r.SkipChildren()
} }
@ -315,6 +340,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Size = dtype.Size() t.Size = dtype.Size()
t.Align = -1 t.Align = -1
t.C = dtype.Common().Name t.C = dtype.Common().Name
t.EnumValues = nil
c.m[dtype] = t c.m[dtype] = t
if t.Size < 0 { if t.Size < 0 {
// Unsized types are [0]byte // Unsized types are [0]byte
@ -376,6 +402,10 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Align = c.ptrSize t.Align = c.ptrSize
} }
t.C = "enum " + dt.EnumName 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: case *dwarf.FloatType:
switch t.Size { switch t.Size {

View File

@ -71,6 +71,7 @@ func main() {
p.loadDebugInfo() p.loadDebugInfo()
p.Vardef = make(map[string]*Type) p.Vardef = make(map[string]*Type)
p.Funcdef = make(map[string]*FuncType) p.Funcdef = make(map[string]*FuncType)
p.Enumdef = make(map[string]int64)
for _, cref := range p.Crefs { for _, cref := range p.Crefs {
switch cref.Context { switch cref.Context {
@ -86,6 +87,14 @@ func main() {
if cref.TypeName { if cref.TypeName {
error((*cref.Expr).Pos(), "type C.%s used as expression", cref.Name) 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. // Reference to C variable.
// We declare a pointer and arrange to have it filled in. // We declare a pointer and arrange to have it filled in.
*cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}} *cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}}

View File

@ -69,6 +69,11 @@ func (p *Prog) writeOutput(srcfile string) {
} }
fmt.Fprintf(fc, "\n") 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 { for name, def := range p.Funcdef {
// Go func declaration. // Go func declaration.
d := &ast.FuncDecl{ d := &ast.FuncDecl{