diff options
| author | Albert van der Linde <alinde@google.com> | 2020-07-14 07:44:00 +0000 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-07-14 12:20:37 +0200 |
| commit | 230553f68fcaa90508b724edd0dfc806669c1f22 (patch) | |
| tree | cbc2024c41d78351ae75d219c70b63ad1c286a11 /pkg/compiler | |
| parent | ce4c95b3a67eee4693923ed820d14aa3d2655f45 (diff) | |
prog/types.go: add Type.Alignment() and TypeCommon.TypeAlign
Type.Alignment() can be used to obtain byte alignment for
correctly allocating aligned memory for the Type.
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/gen.go | 54 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 45 |
2 files changed, 46 insertions, 53 deletions
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go index a86190863..d4834e40e 100644 --- a/pkg/compiler/gen.go +++ b/pkg/compiler/gen.go @@ -296,7 +296,7 @@ func (comp *compiler) layoutStructFields(t *prog.StructType, varlen, packed bool f := field.Type fieldAlign := uint64(1) if !packed { - fieldAlign = comp.typeAlign(f) + fieldAlign = f.Alignment() if structAlign < fieldAlign { structAlign = fieldAlign } @@ -424,58 +424,6 @@ func setBitfieldUnitOffset(t prog.Type, v uint64) { *p = v } -func (comp *compiler) typeAlign(t0 prog.Type) uint64 { - switch t0.Format() { - case prog.FormatNative, prog.FormatBigEndian: - case prog.FormatStrDec, prog.FormatStrHex, prog.FormatStrOct: - return 1 - default: - panic("unknown binary format") - } - if prog.IsPad(t0) { - return 1 - } - switch t := t0.(type) { - case *prog.ConstType, *prog.IntType, *prog.LenType, *prog.FlagsType, *prog.ProcType, - *prog.CsumType, *prog.PtrType, *prog.VmaType, *prog.ResourceType: - align := t0.UnitSize() - if align == 8 && comp.target.Int64Alignment != 0 { - align = comp.target.Int64Alignment - } - return align - case *prog.BufferType: - return 1 - case *prog.ArrayType: - return comp.typeAlign(t.Elem) - case *prog.StructType: - n := comp.structs[t.TypeName] - attrs := comp.parseAttrs(structAttrs, n, n.Attrs) - if align := attrs[attrAlign]; align != 0 { - return align // overrided by user attribute - } - if attrs[attrPacked] != 0 { - return 1 - } - align := uint64(0) - for _, f := range t.Fields { - if a := comp.typeAlign(f.Type); align < a { - align = a - } - } - return align - case *prog.UnionType: - align := uint64(0) - for _, f := range t.Fields { - if a := comp.typeAlign(f.Type); align < a { - align = a - } - } - return align - default: - panic(fmt.Sprintf("unknown type: %#v", t)) - } -} - func genPad(size uint64) prog.Field { return prog.Field{ Type: &prog.ConstType{ diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 6cf32e39f..122c4a9d4 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -140,6 +140,7 @@ var typeInt = &typeDesc{ bitLen = t.Colon[0].Value } base.TypeSize = size + base.TypeAlign = getIntAlignment(comp, base) return &prog.IntType{ IntTypeCommon: genIntCommon(base.TypeCommon, bitLen, be), Kind: kind, @@ -150,6 +151,14 @@ var typeInt = &typeDesc{ }, } +func getIntAlignment(comp *compiler, base prog.IntTypeCommon) uint64 { + align := base.UnitSize() + if align == 8 && comp.target.Int64Alignment != 0 { + align = comp.target.Int64Alignment + } + return align +} + var typePtr = &typeDesc{ Names: []string{"ptr", "ptr64"}, CanBeArgRet: canBeArg, @@ -160,6 +169,7 @@ var typePtr = &typeDesc{ if t.Ident == "ptr64" { base.TypeSize = 8 } + base.TypeAlign = getIntAlignment(comp, base) return &prog.PtrType{ TypeCommon: base.TypeCommon, Elem: comp.genType(args[1], 0), @@ -176,6 +186,7 @@ var typeVoid = &typeDesc{ }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { base.TypeSize = 0 // the only type with static size 0 + base.TypeAlign = 1 return &prog.BufferType{ TypeCommon: base.TypeCommon, Kind: prog.BufferBlobRange, @@ -230,6 +241,7 @@ var typeArray = &typeDesc{ base.TypeSize = begin * elemType.Size() } } + base.TypeAlign = 1 return &prog.BufferType{ TypeCommon: base.TypeCommon, Kind: bufKind, @@ -238,6 +250,7 @@ var typeArray = &typeDesc{ } } // TypeSize is assigned later in layoutArray. + base.TypeAlign = elemType.Alignment() return &prog.ArrayType{ TypeCommon: base.TypeCommon, Elem: elemType, @@ -273,6 +286,7 @@ var typeLen = &typeDesc{ for _, col := range args[0].Colon { path = append(path, col.Ident) } + base.TypeAlign = getIntAlignment(comp, base) return &prog.LenType{ IntTypeCommon: base, Path: path, @@ -298,6 +312,7 @@ var typeConst = &typeDesc{ args[0].Value = v & (uint64(1)<<bitSize - 1) }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { + base.TypeAlign = getIntAlignment(comp, base) return &prog.ConstType{ IntTypeCommon: base, Val: args[0].Value, @@ -364,6 +379,7 @@ var typeFlags = &typeDesc{ sort.Slice(values, func(i, j int) bool { return values[i] < values[j] }) + base.TypeAlign = getIntAlignment(comp, base) return &prog.FlagsType{ IntTypeCommon: base, Vals: values, @@ -416,6 +432,7 @@ var typeVMA = &typeDesc{ if t.Ident == "vma64" { base.TypeSize = 8 } + base.TypeAlign = getIntAlignment(comp, base) return &prog.VmaType{ TypeCommon: base.TypeCommon, RangeBegin: begin, @@ -447,6 +464,7 @@ var typeCsum = &typeDesc{ if len(args) > 2 { proto = args[2].Value } + base.TypeAlign = getIntAlignment(comp, base) return &prog.CsumType{ IntTypeCommon: base, Buf: args[0].Ident, @@ -501,6 +519,7 @@ var typeProc = &typeDesc{ } }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { + base.TypeAlign = getIntAlignment(comp, base) return &prog.ProcType{ IntTypeCommon: base, ValuesStart: args[0].Value, @@ -518,6 +537,7 @@ var typeText = &typeDesc{ }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { base.TypeSize = 0 + base.TypeAlign = 1 return &prog.BufferType{ TypeCommon: base.TypeCommon, Kind: prog.BufferText, @@ -586,6 +606,7 @@ var typeString = &typeDesc{ return comp.stringSize(t, args) == 0 }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { + base.TypeAlign = 1 if len(args) > 0 && args[0].Ident == "filename" { base.TypeName = "filename" base.TypeSize = 0 @@ -723,18 +744,23 @@ var typeFmt = &typeDesc{ case *prog.ResourceType: t.ArgFormat = format t.TypeSize = size + t.TypeAlign = 1 case *prog.IntType: t.ArgFormat = format t.TypeSize = size + t.TypeAlign = 1 case *prog.LenType: t.ArgFormat = format t.TypeSize = size + t.TypeAlign = 1 case *prog.FlagsType: t.ArgFormat = format t.TypeSize = size + t.TypeAlign = 1 case *prog.ProcType: t.ArgFormat = format t.TypeSize = size + t.TypeAlign = 1 default: panic(fmt.Sprintf("unexpected type: %#v", typ)) } @@ -769,6 +795,7 @@ func init() { } baseProgType := comp.genType(baseType, 0) base.TypeSize = baseProgType.Size() + base.TypeAlign = getIntAlignment(comp, base) return &prog.ResourceType{ TypeCommon: base.TypeCommon, ArgFormat: baseProgType.Format(), @@ -836,8 +863,26 @@ func init() { fields := comp.genFieldArray(s.Fields, make([]uint64, len(s.Fields))) if s.IsUnion { typ.(*prog.UnionType).Fields = fields + for _, f := range fields { + if a := f.Type.Alignment(); typ.(*prog.UnionType).TypeAlign < a { + typ.(*prog.UnionType).TypeAlign = a + } + } } else { typ.(*prog.StructType).Fields = fields + attrs := comp.parseAttrs(structAttrs, s, s.Attrs) + if align := attrs[attrAlign]; align != 0 { + typ.(*prog.StructType).TypeAlign = align + } else if attrs[attrPacked] != 0 { + typ.(*prog.StructType).TypeAlign = 1 + } else { + for _, f := range fields { + a := f.Type.Alignment() + if typ.(*prog.StructType).TypeAlign < a { + typ.(*prog.StructType).TypeAlign = a + } + } + } } return typ } |
