aboutsummaryrefslogtreecommitdiffstats
path: root/sys/decl.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-12-11 15:42:14 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-12-17 14:38:46 +0100
commit9980a72713f95bdef6bbd649fd0525bfe1da64d5 (patch)
tree2f28c2926f72cf4bb1926a58e20a42c44d6a7f36 /sys/decl.go
parent48d0a3662ef7971ad56214c73623a30cee996415 (diff)
sys: automatically add padding to structs
Diffstat (limited to 'sys/decl.go')
-rw-r--r--sys/decl.go188
1 files changed, 188 insertions, 0 deletions
diff --git a/sys/decl.go b/sys/decl.go
index b86ff2fad..9405a7e03 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -6,6 +6,8 @@
package sys
+const ptrSize = 8
+
type Call struct {
ID int
CallID int
@@ -19,6 +21,8 @@ type Type interface {
Name() string
Optional() bool
Default() uintptr
+ Size() uintptr
+ Align() uintptr
}
type TypeCommon struct {
@@ -173,6 +177,10 @@ func (t ResourceType) Size() uintptr {
}
}
+func (t ResourceType) Align() uintptr {
+ return t.Size()
+}
+
func (t ResourceType) SubKinds() []ResourceSubkind {
switch t.Kind {
case ResFD:
@@ -195,6 +203,14 @@ type FileoffType struct {
File string
}
+func (t FileoffType) Size() uintptr {
+ return t.TypeSize
+}
+
+func (t FileoffType) Align() uintptr {
+ return t.Size()
+}
+
type BufferKind int
const (
@@ -211,34 +227,89 @@ type BufferType struct {
Kind BufferKind
}
+func (t BufferType) Size() uintptr {
+ switch t.Kind {
+ case BufferAlgType:
+ return 14
+ case BufferAlgName:
+ return 64
+ default:
+ panic("buffer size is not statically known")
+ }
+}
+
+func (t BufferType) Align() uintptr {
+ return 1
+}
+
type VmaType struct {
TypeCommon
}
+func (t VmaType) Size() uintptr {
+ return ptrSize
+}
+
+func (t VmaType) Align() uintptr {
+ return t.Size()
+}
+
type LenType struct {
TypeCommon
TypeSize uintptr
Buf string
}
+func (t LenType) Size() uintptr {
+ return t.TypeSize
+}
+
+func (t LenType) Align() uintptr {
+ return t.Size()
+}
+
type FlagsType struct {
TypeCommon
TypeSize uintptr
Vals []uintptr
}
+func (t FlagsType) Size() uintptr {
+ return t.TypeSize
+}
+
+func (t FlagsType) Align() uintptr {
+ return t.Size()
+}
+
type ConstType struct {
TypeCommon
TypeSize uintptr
Val uintptr
}
+func (t ConstType) Size() uintptr {
+ return t.TypeSize
+}
+
+func (t ConstType) Align() uintptr {
+ return t.Size()
+}
+
type StrConstType struct {
TypeCommon
TypeSize uintptr
Val string
}
+func (t StrConstType) Size() uintptr {
+ return ptrSize
+}
+
+func (t StrConstType) Align() uintptr {
+ return t.Size()
+}
+
type IntKind int
const (
@@ -253,24 +324,78 @@ type IntType struct {
Kind IntKind
}
+func (t IntType) Size() uintptr {
+ return t.TypeSize
+}
+
+func (t IntType) Align() uintptr {
+ return t.Size()
+}
+
type FilenameType struct {
TypeCommon
}
+func (t FilenameType) Size() uintptr {
+ panic("filename size is not statically known")
+}
+
+func (t FilenameType) Align() uintptr {
+ return 1
+}
+
type ArrayType struct {
TypeCommon
Type Type
}
+func (t ArrayType) Size() uintptr {
+ return 0 // for trailing embed arrays
+}
+
+func (t ArrayType) Align() uintptr {
+ return t.Type.Align()
+}
+
type PtrType struct {
TypeCommon
Type Type
Dir Dir
}
+func (t PtrType) Size() uintptr {
+ return ptrSize
+}
+
+func (t PtrType) Align() uintptr {
+ return t.Size()
+}
+
type StructType struct {
TypeCommon
Fields []Type
+ padded bool
+}
+
+func (t StructType) Size() uintptr {
+ if !t.padded {
+ panic("struct is not padded yet")
+ }
+ var size uintptr
+ for _, f := range t.Fields {
+ size += f.Size()
+ }
+ return size
+}
+
+func (t StructType) Align() uintptr {
+ var align uintptr
+ for _, f := range t.Fields {
+ if a1 := f.Align(); align < a1 {
+ align = a1
+ }
+ }
+ return align
}
type Dir int
@@ -288,6 +413,30 @@ var (
)
func init() {
+ var rec func(t Type) Type
+ rec = func(t Type) Type {
+ switch t1 := t.(type) {
+ case PtrType:
+ rec(t1.Type)
+ case ArrayType:
+ rec(t1.Type)
+ case StructType:
+ for i, f := range t1.Fields {
+ t1.Fields[i] = rec(f)
+ }
+ t = addAlignment(t1)
+ }
+ return t
+ }
+ for _, c := range Calls {
+ for i, t := range c.Args {
+ c.Args[i] = rec(t)
+ }
+ if c.Ret != nil {
+ c.Ret = rec(c.Ret)
+ }
+ }
+
for _, c := range Calls {
if CallMap[c.Name] != nil {
println(c.Name)
@@ -303,3 +452,42 @@ func init() {
}
CallCount = len(CallID)
}
+
+func addAlignment(t StructType) Type {
+ var fields []Type
+ var off, align uintptr
+ varLen := false
+ for i, f := range t.Fields {
+ a := f.Align()
+ if align < a {
+ align = a
+ }
+ if off%a != 0 {
+ pad := a - off%a
+ off += pad
+ fields = append(fields, makePad(pad))
+ }
+ off += f.Size()
+ fields = append(fields, f)
+ _, varLen := f.(ArrayType)
+ if varLen && i != len(t.Fields)-1 {
+ panic("embed array in middle of a struct")
+ }
+ }
+ if align != 0 && off%align != 0 && !varLen {
+ pad := align - off%align
+ off += pad
+ fields = append(fields, makePad(pad))
+ }
+ t.Fields = fields
+ t.padded = true
+ return t
+}
+
+func makePad(sz uintptr) Type {
+ return ConstType{
+ TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false},
+ TypeSize: sz,
+ Val: 0,
+ }
+}