From 230553f68fcaa90508b724edd0dfc806669c1f22 Mon Sep 17 00:00:00 2001 From: Albert van der Linde Date: Tue, 14 Jul 2020 07:44:00 +0000 Subject: 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. --- pkg/compiler/gen.go | 54 +-------------------------------------------------- pkg/compiler/types.go | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 53 deletions(-) (limited to 'pkg/compiler') 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)< 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 } -- cgit mrf-deployment