Skip to content

Commit

Permalink
parser: Different way of storing unions
Browse files Browse the repository at this point in the history
  • Loading branch information
mefistotelis committed Mar 13, 2022
1 parent 787a5be commit 0f2999f
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 31 deletions.
13 changes: 7 additions & 6 deletions cmd/sym_dump/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ func pruneDuplicates(ps []*csym.Parser, skipAddrDiff, skipLineDiff bool, opts *s

// Sort types by tag.
natsort.Strings(dst.EnumTags)
natsort.Strings(dst.UnionTags)
less := func(i, j int) bool {
ti := dst.Typedefs[i].(*c.VarDecl)
tj := dst.Typedefs[j].(*c.VarDecl)
Expand Down Expand Up @@ -272,8 +271,9 @@ func addUniqueStructs(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int

// addUniqueUnions adds unique unions to destination parser.
func addUniqueUnions(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int, isPresent *map[string]bool, opts *sym.Options) {
for _, tag := range p.UnionTags {
t := p.Unions[tag]
for tag, unions := range p.UnionTags {
for i := 0; i < len(unions); i++ {
t := unions[i]
fake := strings.Contains(t.Tag, "fake")
if fake {
t.Tag = placeholder
Expand All @@ -286,16 +286,17 @@ func addUniqueUnions(dst *csym.Parser, p *csym.Parser, pnum int, fakeCount *int,
}
if !(*isPresent)[s] {
if !fake {
if _, ok := dst.Unions[tag]; ok {
if _, ok := dst.UnionTags[tag]; ok {
tag = fmt.Sprintf("%s_dup_%d", tag, pnum)
t.Tag = tag
}
}
dst.Unions[tag] = t
dst.UnionTags = append(dst.UnionTags, tag)
dst.UnionTags[tag] = append(dst.UnionTags[tag], t)
dst.Unions = append(dst.Unions, t)
}
(*isPresent)[s] = true
}
}
}

// addUniqueEnums adds unique Enums to destination parser.
Expand Down
3 changes: 1 addition & 2 deletions cmd/sym_dump/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ func dumpTypes(p *csym.Parser, outputDir string) error {
}
}
// Print unions.
for _, tag := range p.UnionTags {
t := p.Unions[tag]
for _, t := range p.Unions {
if _, err := fmt.Fprintf(f, "%s;\n\n", t.Def()); err != nil {
return errors.WithStack(err)
}
Expand Down
8 changes: 4 additions & 4 deletions csym/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ type Parser struct {
// Struct maps from struct tag to struct types.
StructTags map[string][]*c.StructType
// unions maps from union tag to union type.
Unions map[string]*c.UnionType
UnionTags map[string][]*c.UnionType
// enums maps from enum tag to enum type.
Enums map[string]*c.EnumType
// types maps from type name to underlying type definition.
Types map[string]c.Type
// Structs in order of occurrence in SYM file.
Structs []*c.StructType
// Union tags in order of occurrence in SYM file.
UnionTags []string
// Unions in order of occurrence in SYM file.
Unions []*c.UnionType
// Enum tags in order of occurrence in SYM file.
EnumTags []string
// Type definitions in order of occurrence in SYM file.
Expand Down Expand Up @@ -52,7 +52,7 @@ func NewParser(opts *sym.Options) *Parser {
}
return &Parser{
StructTags: make(map[string][]*c.StructType),
Unions: make(map[string]*c.UnionType),
UnionTags: make(map[string][]*c.UnionType),
Enums: make(map[string]*c.EnumType),
Types: make(map[string]c.Type),
enumMembers: make(map[string]bool),
Expand Down
51 changes: 32 additions & 19 deletions csym/parse_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func (p *Parser) emptyUnion(tag string, size uint32) *c.UnionType {
Tag: tag,
Size: size,
}
p.Unions[tag] = t
p.UnionTags = append(p.UnionTags, tag)
p.UnionTags[tag] = append(p.UnionTags[tag], t)
p.Unions = append(p.Unions, t)
return t
}

Expand Down Expand Up @@ -93,7 +93,6 @@ func (p *Parser) initTaggedTypes(syms []*sym.Symbol) {
// referrenced before defined.
p.emptyStruct("__vtbl_ptr_type", 0)
var (
unionTags = make(map[string]bool)
enumTags = make(map[string]bool)
)
for _, s := range syms {
Expand All @@ -104,7 +103,6 @@ func (p *Parser) initTaggedTypes(syms []*sym.Symbol) {
case sym.ClassSTRTAG:
p.emptyStruct(tag, body.Size)
case sym.ClassUNTAG:
tag = uniqueTag(tag, unionTags)
p.emptyUnion(tag, body.Size)
case sym.ClassENTAG:
tag = uniqueTag(tag, enumTags)
Expand Down Expand Up @@ -323,7 +321,7 @@ func (p *Parser) findStruct(tag string, size uint32, matchSize bool) *c.StructTy

// findEmptyStruct returns the struct with the given tag and size.
// It selects the struct which has no fields defined yet, and
// asserts the type exists.
// asserts that the type exists.
func findEmptyStruct(p *Parser, tag string, size uint32) *c.StructType {
var t *c.StructType = nil
structs, ok := p.StructTags[tag]
Expand All @@ -343,30 +341,45 @@ func findEmptyStruct(p *Parser, tag string, size uint32) *c.StructType {

// findUnion returns the union with the given tag and size.
func (p *Parser) findUnion(tag string, size uint32, matchSize bool) *c.UnionType {
t, ok := p.Unions[tag]
// Ignore size - we currently support only one type with specific tag
if !ok {
var t *c.UnionType = nil
nameExists := false
unions, ok := p.UnionTags[tag]
if ok {
nameExists = len(unions) > 0
for i := 0; i < len(unions); i++ {
tt := unions[i]
if matchSize && tt.Size != size { continue }
t = tt
}
}
if t == nil {
t = p.emptyUnion(tag, size)
if nameExists {
t.Tag = UniqueUnionTag(p.UnionTags, t)
}
log.Printf("unable to locate union %q, created empty", tag)
}
return t
}

// findEmptyUnion returns the union with the given tag and size.
// It selects the union which has no fields defined yet, and
// asserts the type exists.
// asserts that the type exists.
func findEmptyUnion(p *Parser, tag string, size uint32) *c.UnionType {
newTag := tag
for i := 0; ; i++ {
t, ok := p.Unions[newTag]
if !ok {
panic(fmt.Errorf("unable to locate union %q", tag))
}
if t.Size == size && len(t.Fields) == 0 {
return t
var t *c.UnionType = nil
unions, ok := p.UnionTags[tag]
if ok {
for i := 0; i < len(unions); i++ {
tt := unions[i]
if tt.Size != size { continue }
if len(tt.Fields) != 0 { continue }
t = tt
}
newTag = fmt.Sprintf(duplicateTagFormat, tag, i)
}
if t == nil {
panic(fmt.Errorf("unable to locate union %q size %d", tag, size))
}
return t
}

// findEnum returns the enumeration with the given tag.
Expand All @@ -382,7 +395,7 @@ func (p *Parser) findEnum(tag string) *c.EnumType {

// findEmptyEnum returns the enumeration with the given tag.
// It selects the enum which has no members defined yet, and
// asserts the type exists.
// asserts that the type exists.
func findEmptyEnum(p *Parser, tag string) *c.EnumType {
newTag := tag
for i := 0; ; i++ {
Expand Down

0 comments on commit 0f2999f

Please sign in to comment.