mirror of
https://github.com/golang/go
synced 2024-11-22 05:34:39 -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:
parent
52114724b7
commit
a8fbf5dc2c
1
AUTHORS
1
AUTHORS
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -35,16 +35,18 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Type collects information about a type in both the C and Go worlds.
|
// A Type collects information about a type in both the C and Go worlds.
|
||||||
type Type struct {
|
type Type struct {
|
||||||
Size int64
|
Size int64
|
||||||
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.
|
||||||
|
@ -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,32 +130,56 @@ 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)
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
}
|
|
||||||
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 {
|
||||||
|
@ -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}}
|
||||||
|
@ -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{
|
||||||
|
Loading…
Reference in New Issue
Block a user