aboutsummaryrefslogtreecommitdiffstats
path: root/sys/align.go
blob: 9d7bb1f06d1f7c0f8dc60d5c693a3759a56b3d20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package sys

func initAlign() {
	var rec func(t Type) Type
	rec = func(t Type) Type {
		switch t1 := t.(type) {
		case PtrType:
			t1.Type = rec(t1.Type)
			t = t1
		case ArrayType:
			t1.Type = rec(t1.Type)
			t = t1
		case StructType:
			for i, f := range t1.Fields {
				t1.Fields[i] = rec(f)
			}
			t = addAlignment(t1)
		case UnionType:
			opts := make(map[string]bool)
			for i, opt := range t1.Options {
				if opts[opt.Name()] {
					panic("duplicate option in union")
				}
				opts[opt.Name()] = true
				t1.Options[i] = rec(opt)
			}
		}
		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)
		}
	}
}

func addAlignment(t StructType) Type {
	if t.packed {
		t.padded = true
		return t
	}
	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)
		if at, ok := f.(ArrayType); ok && at.Len == 0 {
			varLen = true
		}
		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,
		IsPad:      true,
	}
}