aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorAlbert van der Linde <alinde@google.com>2020-07-14 07:44:00 +0000
committerDmitry Vyukov <dvyukov@google.com>2020-07-14 12:20:37 +0200
commit230553f68fcaa90508b724edd0dfc806669c1f22 (patch)
treecbc2024c41d78351ae75d219c70b63ad1c286a11 /pkg/compiler
parentce4c95b3a67eee4693923ed820d14aa3d2655f45 (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.go54
-rw-r--r--pkg/compiler/types.go45
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
}