Skip to content
This repository has been archived by the owner on May 18, 2024. It is now read-only.

Commit

Permalink
union: support embedded field
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed Apr 3, 2022
1 parent 2aabf7d commit a03115e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
37 changes: 30 additions & 7 deletions cl/codebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,35 +42,58 @@ func newUnionBuilder() *unionBuilder {
return &unionBuilder{}
}

func unionEmbeddedField(ctx *blockCtx, fields []*gox.UnionField, t *types.Named, off int) []*gox.UnionField {
o := t.Underlying().(*types.Struct)
for i, n := 0, o.NumFields(); i < n; i++ {
fld := o.Field(i)
fldType := fld.Type()
if fld.Embedded() {
fields = unionEmbeddedField(ctx, fields, fldType.(*types.Named), off)
} else {
fields = append(fields, &gox.UnionField{
Name: fld.Name(),
Off: off,
Type: fldType,
})
}
off += ctx.sizeof(fldType)
}
return fields
}

func (p *unionBuilder) Type(ctx *blockCtx, t *types.Named) *types.Struct {
var fldLargest *gox.UnionField
var lenLargest int
for _, fld := range p.fields {
var fields = p.fields
var lenLargest, n = 0, len(fields)
for i := 0; i < n; i++ {
fld := fields[i]
if len := ctx.sizeof(fld.Type); len > lenLargest {
fldLargest, lenLargest = fld, len
}
if fld.Name == "" { // embedded
fields = unionEmbeddedField(ctx, fields, fld.Type.(*types.Named), 0)
}
}
flds := make([]*types.Var, 0, 1)
if fldLargest != nil {
pkg := ctx.pkg
pkg.SetVFields(t, gox.NewUnionFields(p.fields))
pkg.SetVFields(t, gox.NewUnionFields(fields))
fld := types.NewField(fldLargest.Pos, pkg.Types, fldLargest.Name, fldLargest.Type, false)
flds = append(flds, fld)
}
return types.NewStruct(flds, nil)
}

func (p *unionBuilder) Field(ctx *blockCtx, pos token.Pos, typ types.Type, name string, embedded bool) {
if embedded {
name = ""
}
fld := &gox.UnionField{
Name: name,
Off: 0, // TODO
Type: typ,
Pos: pos,
}
p.fields = append(p.fields, fld)
if name == "" {
log.Fatalln("unionBuilder.Field TODO: embedded")
}
}

// -----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions cl/type_and_var.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func toUnionType(ctx *blockCtx, t *types.Named, unio *ast.Node, ns string) types
}
break
}
case ast.IndirectFieldDecl:
default:
log.Fatalln("toUnionType: unknown field kind =", decl.Kind)
}
Expand Down
19 changes: 18 additions & 1 deletion testdata/union/union.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
#include <stdio.h>

typedef union {
long a;
int a;
unsigned short b;
struct bar {
unsigned short low, high;
} c;
struct {
unsigned short low;
struct {
unsigned short high;
};
};
} foo;

int main() {
Expand All @@ -16,5 +22,16 @@ int main() {
printf(
"foo.a = %d, foo.b = %d, foo.c.low = %d, foo.c.high = %d\n",
foo.a, foo.b, foo.c.low, foo.c.high);
printf(
"foo.low = %d, foo.high = %d\n",
foo.low, foo.high);
foo.low = 5;
foo.high = 6;
printf(
"foo.a = %d, foo.b = %d, foo.c.low = %d, foo.c.high = %d\n",
foo.a, foo.b, foo.c.low, foo.c.high);
printf(
"foo.low = %d, foo.high = %d\n",
foo.low, foo.high);
return 0;
}

0 comments on commit a03115e

Please sign in to comment.