2
2
3
3
This document describes Go’s internal application binary interface
4
4
(ABI), known as ABIInternal.
5
+ Go's ABI defines the layout of data in memory and the conventions for
6
+ calling between Go functions.
5
7
This ABI is * unstable* and will change between Go versions.
6
8
If you’re writing assembly code, please instead refer to Go’s
7
9
[ assembly documentation] ( /doc/asm.html ) , which describes Go’s stable
@@ -20,7 +22,89 @@ specifics.
20
22
architectures instead of the platform ABI, see the [ register-based Go
21
23
calling convention proposal] ( https://golang.org/design/40724-register-calling ) .
22
24
23
- ## Argument and result passing
25
+ ## Memory layout
26
+
27
+ Go's built-in types have the following sizes and alignments.
28
+ Many, though not all, of these sizes are guaranteed by the [ language
29
+ specification] ( /doc/go_spec.html#Size_and_alignment_guarantees ) .
30
+ Those that aren't guaranteed may change in future versions of Go (for
31
+ example, we've considered changing the alignment of int64 on 32-bit).
32
+
33
+ | Type | 64-bit | | 32-bit | |
34
+ | --- | --- | --- | --- | --- |
35
+ | | Size | Align | Size | Align |
36
+ | bool, uint8, int8 | 1 | 1 | 1 | 1 |
37
+ | uint16, int16 | 2 | 2 | 2 | 2 |
38
+ | uint32, int32 | 4 | 4 | 4 | 4 |
39
+ | uint64, int64 | 8 | 8 | 8 | 4 |
40
+ | int, uint | 8 | 8 | 4 | 4 |
41
+ | float32 | 4 | 4 | 4 | 4 |
42
+ | float64 | 8 | 8 | 8 | 4 |
43
+ | complex64 | 8 | 4 | 8 | 4 |
44
+ | complex128 | 16 | 8 | 16 | 4 |
45
+ | uintptr, * T, unsafe.Pointer | 8 | 8 | 4 | 4 |
46
+
47
+ The types ` byte ` and ` rune ` are aliases for ` uint8 ` and ` int32 ` ,
48
+ respectively, and hence have the same size and alignment as these
49
+ types.
50
+
51
+ The layout of ` map ` , ` chan ` , and ` func ` types is equivalent to * T.
52
+
53
+ To describe the layout of the remaining composite types, we first
54
+ define the layout of a * sequence* S of N fields with types
55
+ t<sub >1</sub >, t<sub >2</sub >, ..., t<sub >N</sub >.
56
+ We define the byte offset at which each field begins relative to a
57
+ base address of 0, as well as the size and alignment of the sequence
58
+ as follows:
59
+
60
+ ```
61
+ offset(S, i) = 0 if i = 1
62
+ = align(offset(S, i-1) + sizeof(t_(i-1)), alignof(t_i))
63
+ alignof(S) = 1 if N = 0
64
+ = max(alignof(t_i) | 1 <= i <= N)
65
+ sizeof(S) = 0 if N = 0
66
+ = align(offset(S, N) + sizeof(t_N), alignof(S))
67
+ ```
68
+
69
+ Where sizeof(T) and alignof(T) are the size and alignment of type T,
70
+ respectively, and align(x, y) rounds x up to a multiple of y.
71
+
72
+ The ` interface{} ` type is a sequence of 1. a pointer to the runtime type
73
+ description for the interface's dynamic type and 2. an ` unsafe.Pointer `
74
+ data field.
75
+ Any other interface type (besides the empty interface) is a sequence
76
+ of 1. a pointer to the runtime "itab" that gives the method pointers and
77
+ the type of the data field and 2. an ` unsafe.Pointer ` data field.
78
+ An interface can be "direct" or "indirect" depending on the dynamic
79
+ type: a direct interface stores the value directly in the data field,
80
+ and an indirect interface stores a pointer to the value in the data
81
+ field.
82
+ An interface can only be direct if the value consists of a single
83
+ pointer word.
84
+
85
+ An array type ` [N]T ` is a sequence of N fields of type T.
86
+
87
+ The slice type ` []T ` is a sequence of a ` *[cap]T ` pointer to the slice
88
+ backing store, an ` int ` giving the ` len ` of the slice, and an ` int `
89
+ giving the ` cap ` of the slice.
90
+
91
+ The ` string ` type is a sequence of a ` *[len]byte ` pointer to the
92
+ string backing store, and an ` int ` giving the ` len ` of the string.
93
+
94
+ A struct type ` struct { f1 t1; ...; fM tM } ` is laid out as the
95
+ sequence t1, ..., tM, tP, where tP is either:
96
+
97
+ - Type ` byte ` if sizeof(tM) = 0 and any of sizeof(t* i* ) ≠ 0.
98
+ - Empty (size 0 and align 1) otherwise.
99
+
100
+ The padding byte prevents creating a past-the-end pointer by taking
101
+ the address of the final, empty fN field.
102
+
103
+ Note that user-written assembly code should generally not depend on Go
104
+ type layout and should instead use the constants defined in
105
+ [ ` go_asm.h ` ] ( /doc/asm.html#data-offsets ) .
106
+
107
+ ## Function call argument and result passing
24
108
25
109
Function calls pass arguments and results using a combination of the
26
110
stack and machine registers.
@@ -45,42 +129,48 @@ reserves spill space on the stack for all register-based arguments
45
129
(but does not populate this space).
46
130
47
131
The receiver, arguments, and results of function or method F are
48
- assigned to registers using the following algorithm:
132
+ assigned to registers or the stack using the following algorithm:
49
133
50
- 1 . Start with the full integer and floating-point register sequences
51
- and an empty stack frame.
134
+ 1 . Let NI and NFP be the length of integer and floating-point register
135
+ sequences defined by the architecture.
136
+ Let I and FP be 0; these are the indexes of the next integer and
137
+ floating-pointer register.
138
+ Let S, the type sequence defining the stack frame, be empty.
52
139
1 . If F is a method, assign F’s receiver.
53
140
1 . For each argument A of F, assign A.
54
- 1 . Align the stack frame offset to the architecture’s pointer size.
55
- 1 . Reset to the full integer and floating-point register sequences
56
- (but do not reset the stack frame) .
141
+ 1 . Add a pointer-alignment field to S. This has size 0 and the same
142
+ alignment as ` uintptr ` .
143
+ 1 . Reset I and FP to 0 .
57
144
1 . For each result R of F, assign R.
58
- 1 . Align the stack frame offset to the architecture’s pointer size .
145
+ 1 . Add a pointer-alignment field to S .
59
146
1 . For each register-assigned receiver and argument of F, let T be its
60
- type and stack-assign an empty value of type T.
61
- This is the argument's (or receiver's) spill space.
62
- 1 . Align the stack frame offset to the architecture’s pointer size.
147
+ type and add T to the stack sequence S.
148
+ This is the argument's (or receiver's) spill space and will be
149
+ uninitialized at the call.
150
+ 1 . Add a pointer-alignment field to S.
63
151
64
- Assigning a receiver, argument, or result V works as follows:
152
+ Assigning a receiver, argument, or result V of underlying type T works
153
+ as follows:
65
154
66
- 1 . Register-assign V.
67
- 1 . If step 1 failed, undo all register and stack assignments it
68
- performed and stack-assign V.
155
+ 1 . Remember I and FP.
156
+ 1 . Try to register-assign V.
157
+ 1 . If step 2 failed, reset I and FP to the values from step 1, add T
158
+ to the stack sequence S, and assign V to this field in S.
69
159
70
160
Register-assignment of a value V of underlying type T works as follows:
71
161
72
162
1 . If T is a boolean or integral type that fits in an integer
73
- register, assign V to the next available integer register .
163
+ register, assign V to register I and increment I .
74
164
1 . If T is an integral type that fits in two integer registers, assign
75
- the least significant and most significant halves of V to the next
76
- two available integer registers , respectively.
165
+ the least significant and most significant halves of V to registers
166
+ I and I+1 , respectively, and increment I by 2
77
167
1 . If T is a floating-point type and can be represented without loss
78
- of precision in a floating-point register, assign V to the next
79
- available floating-point register .
168
+ of precision in a floating-point register, assign V to register FP
169
+ and increment FP .
80
170
1 . If T is a complex type, recursively register-assign its real and
81
171
imaginary parts.
82
172
1 . If T is a pointer type, map type, channel type, or function type,
83
- assign V to the next available integer register .
173
+ assign V to register I and increment I .
84
174
1 . If T is a string type, interface type, or slice type, recursively
85
175
register-assign V’s components (2 for strings and interfaces, 3 for
86
176
slices).
@@ -89,22 +179,17 @@ Register-assignment of a value V of underlying type T works as follows:
89
179
1 . If T is an array type of length 1, recursively register-assign its
90
180
one element.
91
181
1 . If T is an array type of length > 1, fail.
92
- 1 . If there is no available integer or floating-point register
93
- available above, fail.
94
- 1 . If any recursive assignment above fails, this register-assign fails.
95
-
96
- Stack-assignment of a value V of underlying type T works as follows:
97
-
98
- 1 . Align the current stack frame offset to T’s alignment.
99
- 1 . Append V to the stack frame.
100
-
101
- (Note that any non-zero-sized struct type that ends in a zero-sized
102
- field is implicitly padded with 1 byte to prevent past-the-end
103
- pointers.
104
- This applies to all structs, not just those passed as arguments.)
105
-
106
- The following diagram shows what the resulting argument frame looks
107
- like on the stack:
182
+ 1 . If I > NI or FP > NFP, fail.
183
+ 1 . If any recursive assignment above fails, fail.
184
+
185
+ The above algorithm produces an assignment of each receiver, argument,
186
+ and result to registers or to a field in the stack sequence.
187
+ The final stack sequence looks like: stack-assigned receiver,
188
+ stack-assigned arguments, pointer-alignment, stack-assigned results,
189
+ pointer-alignment, spill space for each register-assigned argument,
190
+ pointer-alignment.
191
+ The following diagram shows what this stack frame looks like on the
192
+ stack, using the typical convention where address 0 is at the bottom:
108
193
109
194
+------------------------------+
110
195
| . . . |
@@ -121,47 +206,50 @@ like on the stack:
121
206
| stack-assigned receiver |
122
207
+------------------------------+ ↓ lower addresses
123
208
124
- (Note that, while stack diagrams conventionally have address 0 at the
125
- bottom, if this were expressed as a Go struct the fields would appear
126
- in the opposite order, starting with the stack-assigned receiver.)
127
-
128
209
To perform a call, the caller reserves space starting at the lowest
129
210
address in its stack frame for the call stack frame, stores arguments
130
- in the registers and argument stack slots determined by the above
211
+ in the registers and argument stack fields determined by the above
131
212
algorithm, and performs the call.
132
- At the time of a call, spill slots , result stack slots , and result
133
- registers are assumed to be uninitialized.
213
+ At the time of a call, spill space , result stack fields , and result
214
+ registers are left uninitialized.
134
215
Upon return, the callee must have stored results to all result
135
- registers and result stack slots determined by the above algorithm.
216
+ registers and result stack fields determined by the above algorithm.
136
217
137
218
There are no callee-save registers, so a call may overwrite any
138
219
register that doesn’t have a fixed meaning, including argument
139
220
registers.
140
221
141
222
### Example
142
223
143
- The function `func f(a1 uint8, a2 [ 2] uintptr, a3 uint8) (r1 struct { x
144
- uintptr; y [ 2] uintptr }, r2 string)` has the following argument frame
145
- layout on a 64-bit host with hypothetical integer registers R0–R9:
224
+ Consider the function `func f(a1 uint8, a2 [ 2] uintptr, a3 uint8) (r1
225
+ struct { x uintptr; y [ 2] uintptr }, r2 string)` on a 64-bit
226
+ architecture with hypothetical integer registers R0–R9.
227
+
228
+ On entry, ` a1 ` is assigned to ` R0 ` , ` a3 ` is assigned to ` R1 ` and the
229
+ stack frame is laid out in the following sequence:
230
+
231
+ a2 [2]uintptr
232
+ r1.x uintptr
233
+ r1.y [2]uintptr
234
+ a1Spill uint8
235
+ a2Spill uint8
236
+ _ [6]uint8 // alignment padding
237
+
238
+ In the stack frame, only the ` a2 ` field is initialized on entry; the
239
+ rest of the frame is left uninitialized.
146
240
147
- +-------------------+ 48
148
- | alignment padding | 42
149
- | a3 argument spill | 41
150
- | a1 argument spill | 40
151
- | r1 result | 16
152
- | a2 argument | 0
153
- +-------------------+
154
- On entry: R0=a1, R1=a3
155
- On exit: R0=r2.base, R1=r2.len
241
+ On exit, ` r2.base ` is assigned to ` R0 ` , ` r2.len ` is assigned to ` R1 ` ,
242
+ and ` r1.x ` and ` r1.y ` are initialized in the stack frame.
156
243
157
244
There are several things to note in this example.
158
- First, a2 and r1 are stack-assigned because they contain arrays.
245
+ First, ` a2 ` and ` r1 ` are stack-assigned because they contain arrays.
159
246
The other arguments and results are register-assigned.
160
- Result r2 is decomposed into its components, which are individually
247
+ Result ` r2 ` is decomposed into its components, which are individually
161
248
register-assigned.
162
- On the stack, the stack-assigned arguments appear below the
163
- stack-assigned results, which appear below the argument spill area.
164
- Only arguments, not results, are assigned a spill area.
249
+ On the stack, the stack-assigned arguments appear at lower addresses
250
+ than the stack-assigned results, which appear at lower addresses than
251
+ the argument spill area.
252
+ Only arguments, not results, are assigned a spill area on the stack.
165
253
166
254
### Rationale
167
255
@@ -196,9 +284,9 @@ kubelet (and even these very little).
196
284
197
285
We make exceptions for 0 and 1-element arrays because these don’t
198
286
require computed offsets, and 1-element arrays are already decomposed
199
- in the compiler’s SSA.
287
+ in the compiler’s SSA representation .
200
288
201
- The stack assignment algorithm above is equivalent to Go’s stack-based
289
+ The ABI assignment algorithm above is equivalent to Go’s stack-based
202
290
ABI0 calling convention if there are zero architecture registers.
203
291
This is intended to ease the transition to the register-based internal
204
292
ABI and make it easy for the compiler to generate either calling
@@ -217,12 +305,13 @@ These slots also act as the home location if these arguments need to
217
305
be spilled for any other reason, which simplifies traceback printing.
218
306
219
307
There are several options for how to lay out the argument spill space.
220
- We chose to lay out each argument in its type's usual memory layout
221
- but to separate the spill space from the regular argument space.
308
+ We chose to lay out each argument according to its type's usual memory
309
+ layout but to separate the spill space from the regular argument
310
+ space.
222
311
Using the usual memory layout simplifies the compiler because it
223
312
already understands this layout.
224
313
Also, if a function takes the address of a register-assigned argument,
225
- the compiler must spill that argument to memory in its usual in- memory
314
+ the compiler must spill that argument to memory in its usual memory
226
315
layout and it's more convenient to use the argument spill space for
227
316
this purpose.
228
317
0 commit comments