forked from golang/go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiletype.go
167 lines (138 loc) · 5.81 KB
/
compiletype.go
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package abi
// These functions are the build-time version of the Go type data structures.
// Their contents must be kept in sync with their definitions.
// Because the host and target type sizes can differ, the compiler and
// linker cannot use the host information that they might get from
// either unsafe.Sizeof and Alignof, nor runtime, reflect, or reflectlite.
// CommonSize returns sizeof(Type) for a compilation target with a given ptrSize
func CommonSize(ptrSize int) int { return 4*ptrSize + 8 + 8 }
// StructFieldSize returns sizeof(StructField) for a compilation target with a given ptrSize
func StructFieldSize(ptrSize int) int { return 3 * ptrSize }
// UncommonSize returns sizeof(UncommonType). This currently does not depend on ptrSize.
// This exported function is in an internal package, so it may change to depend on ptrSize in the future.
func UncommonSize() uint64 { return 4 + 2 + 2 + 4 + 4 }
// IMethodSize returns sizeof(IMethod) for a compilation target with a given ptrSize
func IMethodSize(ptrSize int) int { return 4 + 4 }
// KindOff returns the offset of Type.Kind_ for a compilation target with a given ptrSize
func KindOff(ptrSize int) int { return 2*ptrSize + 7 }
// SizeOff returns the offset of Type.Size_ for a compilation target with a given ptrSize
func SizeOff(ptrSize int) int { return 0 }
// PtrBytes returns the offset of Type.PtrBytes for a compilation target with a given ptrSize
func PtrBytesOff(ptrSize int) int { return ptrSize }
// TFlagOff returns the offset of Type.TFlag for a compilation target with a given ptrSize
func TFlagOff(ptrSize int) int { return 2*ptrSize + 4 }
// Offset is for computing offsets of type data structures at compile/link time;
// the target platform may not be the host platform. Its state includes the
// current offset, necessary alignment for the sequence of types, and the size
// of pointers and alignment of slices, interfaces, and strings (this is for tearing-
// resistant access to these types, if/when that is supported).
type Offset struct {
off uint64 // the current offset
align uint8 // the required alignmentof the container
ptrSize uint8 // the size of a pointer in bytes
sliceAlign uint8 // the alignment of slices (and interfaces and strings)
}
// NewOffset returns a new Offset with offset 0 and alignment 1.
func NewOffset(ptrSize uint8, twoWordAlignSlices bool) Offset {
if twoWordAlignSlices {
return Offset{off: 0, align: 1, ptrSize: ptrSize, sliceAlign: 2 * ptrSize}
}
return Offset{off: 0, align: 1, ptrSize: ptrSize, sliceAlign: ptrSize}
}
func assertIsAPowerOfTwo(x uint8) {
if x == 0 {
panic("Zero is not a power of two")
}
if x&-x == x {
return
}
panic("Not a power of two")
}
// InitializedOffset returns a new Offset with specified offset, alignment, pointer size, and slice alignment.
func InitializedOffset(off int, align uint8, ptrSize uint8, twoWordAlignSlices bool) Offset {
assertIsAPowerOfTwo(align)
o0 := NewOffset(ptrSize, twoWordAlignSlices)
o0.off = uint64(off)
o0.align = align
return o0
}
func (o Offset) align_(a uint8) Offset {
o.off = (o.off + uint64(a) - 1) & ^(uint64(a) - 1)
if o.align < a {
o.align = a
}
return o
}
// Align returns the offset obtained by aligning offset to a multiple of a.
// a must be a power of two.
func (o Offset) Align(a uint8) Offset {
assertIsAPowerOfTwo(a)
return o.align_(a)
}
// plus returns the offset obtained by appending a power-of-2-sized-and-aligned object to o.
func (o Offset) plus(x uint64) Offset {
o = o.align_(uint8(x))
o.off += x
return o
}
// D8 returns the offset obtained by appending an 8-bit field to o.
func (o Offset) D8() Offset {
return o.plus(1)
}
// D16 returns the offset obtained by appending a 16-bit field to o.
func (o Offset) D16() Offset {
return o.plus(2)
}
// D32 returns the offset obtained by appending a 32-bit field to o.
func (o Offset) D32() Offset {
return o.plus(4)
}
// D64 returns the offset obtained by appending a 64-bit field to o.
func (o Offset) D64() Offset {
return o.plus(8)
}
// D64 returns the offset obtained by appending a pointer field to o.
func (o Offset) P() Offset {
if o.ptrSize == 0 {
panic("This offset has no defined pointer size")
}
return o.plus(uint64(o.ptrSize))
}
// Slice returns the offset obtained by appending a slice field to o.
func (o Offset) Slice() Offset {
o = o.align_(o.sliceAlign)
o.off += 3 * uint64(o.ptrSize)
// There's been discussion of whether slices should be 2-word aligned to allow
// use of aligned 2-word load/store to prevent tearing, this is future proofing.
// In general, for purposes of struct layout (and very likely default C layout
// compatibility) the "size" of a Go type is rounded up to its alignment.
return o.Align(o.sliceAlign)
}
// String returns the offset obtained by appending a string field to o.
func (o Offset) String() Offset {
o = o.align_(o.sliceAlign)
o.off += 2 * uint64(o.ptrSize)
return o // We "know" it needs no further alignment
}
// Interface returns the offset obtained by appending an interface field to o.
func (o Offset) Interface() Offset {
o = o.align_(o.sliceAlign)
o.off += 2 * uint64(o.ptrSize)
return o // We "know" it needs no further alignment
}
// Offset returns the struct-aligned offset (size) of o.
// This is at least as large as the current internal offset; it may be larger.
func (o Offset) Offset() uint64 {
return o.Align(o.align).off
}
func (o Offset) PlusUncommon() Offset {
o.off += UncommonSize()
return o
}
// CommonOffset returns the Offset to the data after the common portion of type data structures.
func CommonOffset(ptrSize int, twoWordAlignSlices bool) Offset {
return InitializedOffset(CommonSize(ptrSize), uint8(ptrSize), uint8(ptrSize), twoWordAlignSlices)
}