Skip to content

Commit 202bf8d

Browse files
committedOct 28, 2014
doc/asm: explain coordination with garbage collector
Also a few other minor changes. Fixes golang#8712. LGTM=r R=r CC=golang-codereviews https://golang.org/cl/164150043
1 parent 8a9c2c5 commit 202bf8d

File tree

2 files changed

+114
-20
lines changed

2 files changed

+114
-20
lines changed
 

‎doc/asm.html

+111-20
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ <h3 id="symbols">Symbols</h3>
117117
<p>
118118
The <code>SB</code> pseudo-register can be thought of as the origin of memory, so the symbol <code>foo(SB)</code>
119119
is the name <code>foo</code> as an address in memory.
120+
This form is used to name global functions and data.
121+
Adding <code>&lt;&gt;</code> to the name, as in <code>foo&lt;&gt;(SB)</code>, makes the name
122+
visible only in the current source file, like a top-level <code>static</code> declaration in a C file.
120123
</p>
121124

122125
<p>
@@ -128,8 +131,11 @@ <h3 id="symbols">Symbols</h3>
128131
When referring to a function argument this way, it is conventional to place the name
129132
at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.
130133
Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.
131-
For assembly functions with Go prototypes, <code>go vet</code> will check that the argument names
134+
For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the argument names
132135
and offsets match.
136+
On 32-bit systems, the low and high 32 bits of a 64-bit value are distinguished by adding
137+
a <code>_lo</code> or <code>_hi</code> suffix to the name, as in <code>arg_lo+0(FP)</code> or <code>arg_hi+4(FP)</code>.
138+
If a Go prototype does not name its result, the expected assembly name is <code>ret</code>.
133139
</p>
134140

135141
<p>
@@ -206,6 +212,8 @@ <h3 id="directives">Directives</h3>
206212
and is called with 8 bytes of argument, which live on the caller's frame.
207213
If <code>NOSPLIT</code> is not specified for the <code>TEXT</code>,
208214
the argument size must be provided.
215+
For assembly functions with Go prototypes, <code>go</code> <code>vet</code> will check that the
216+
argument size is correct.
209217
</p>
210218

211219
<p>
@@ -216,19 +224,20 @@ <h3 id="directives">Directives</h3>
216224
</p>
217225

218226
<p>
219-
For <code>DATA</code> directives, the symbol is followed by a slash and the number
220-
of bytes the memory associated with the symbol occupies.
221-
The arguments are optional flags and the data itself.
222-
For instance,
223-
</p>
227+
Global data symbols are defined by a sequence of initializing
228+
<code>DATA</code> directives followed by a <code>GLOBL</code> directive.
229+
Each <code>DATA</code> directive initializes a section of the
230+
corresponding memory.
231+
The memory not explicitly initialized is zeroed.
232+
The general form of the <code>DATA</code> directive is
224233

225234
<pre>
226-
DATA runtime·isplan9(SB)/4, $1
235+
DATA symbol+offset(SB)/width, value
227236
</pre>
228237

229238
<p>
230-
declares the local symbol <code>runtime·isplan9</code> of size 4 and value 1.
231-
Again the symbol has the middle dot and is offset from <code>SB</code>.
239+
which initializes the symbol memory at the given offset and width with the given value.
240+
The <code>DATA</code> directives for a given symbol must be written with increasing offsets.
232241
</p>
233242

234243
<p>
@@ -237,15 +246,26 @@ <h3 id="directives">Directives</h3>
237246
which will have initial value all zeros unless a <code>DATA</code> directive
238247
has initialized it.
239248
The <code>GLOBL</code> directive must follow any corresponding <code>DATA</code> directives.
240-
This example
249+
</p>
250+
251+
<p>
252+
For example,
241253
</p>
242254

243255
<pre>
244-
GLOBL runtime·tlsoffset(SB),$4
256+
DATA divtab&lt;&gt;+0x00(SB)/4, $0xf4f8fcff
257+
DATA divtab&lt;&gt;+0x04(SB)/4, $0xe6eaedf0
258+
...
259+
DATA divtab&lt;&gt;+0x3c(SB)/4, $0x81828384
260+
GLOBL divtab&lt;&gt;(SB), RODATA, $64
261+
262+
GLOBL runtime·tlsoffset(SB), NOPTR, $4
245263
</pre>
246264

247265
<p>
248-
declares <code>runtime·tlsoffset</code> to have size 4.
266+
declares and initializes <code>divtab&lt;&gt;</code>, a read-only 64-byte table of 4-byte integer values,
267+
and declares <code>runtime·tlsoffset</code>, a 4-byte, implicitly zeroed variable that
268+
contains no pointers.
249269
</p>
250270

251271
<p>
@@ -299,6 +319,80 @@ <h3 id="directives">Directives</h3>
299319
</li>
300320
</ul>
301321

322+
<h3 id="runtime">Runtime Coordination</h3>
323+
324+
<p>
325+
For garbage collection to run correctly, the runtime must know the
326+
location of pointers in all global data and in most stack frames.
327+
The Go compiler emits this information when compiling Go source files,
328+
but assembly programs must define it explicitly.
329+
</p>
330+
331+
<p>
332+
A data symbol marked with the <code>NOPTR</code> flag (see above)
333+
is treated as containing no pointers to runtime-allocated data.
334+
A data symbol with the <code>RODATA</code> flag
335+
is allocated in read-only memory and is therefore treated
336+
as implicitly marked <code>NOPTR</code>.
337+
A data symbol with a total size smaller than a pointer
338+
is also treated as implicitly marked <code>NOPTR</code>.
339+
It is not possible to define a symbol containing pointers in an assembly source file;
340+
such a symbol must be defined in a Go source file instead.
341+
Assembly source can still refer to the symbol by name
342+
even without <code>DATA</code> and <code>GLOBL</code> directives.
343+
A good general rule of thumb is to define all non-<code>RODATA</code>
344+
symbols in Go instead of in assembly.
345+
</p>
346+
347+
<p>
348+
Each function also needs annotations giving the location of
349+
live pointers in its arguments, results, and local stack frame.
350+
For an assembly function with no pointer results and
351+
either no local stack frame or no function calls,
352+
the only requirement is to define a Go prototype for the function
353+
in a Go source file in the same package.
354+
For more complex situations, explicit annotation is needed.
355+
These annotations use pseudo-instructions defined in the standard
356+
<code>#include</code> file <code>funcdata.h</code>.
357+
</p>
358+
359+
<p>
360+
If a function has no arguments and no results,
361+
the pointer information can be omitted.
362+
This is indicated by an argument size annotation of <code>$<i>n</i>-0</code>
363+
on the <code>TEXT</code> instruction.
364+
Otherwise, pointer information must be provided by
365+
a Go prototype for the function in a Go source file,
366+
even for assembly functions not called directly from Go.
367+
(The prototype will also let <code>go</code> <code>vet</code> check the argument references.)
368+
At the start of the function, the arguments are assumed
369+
to be initialized but the results are assumed uninitialized.
370+
If the results will hold live pointers during a call instruction,
371+
the function should start by zeroing the results and then
372+
executing the pseudo-instruction <code>GO_RESULTS_INITIALIZED</code>.
373+
This instruction records that the results are now initialized
374+
and should be scanned during stack movement and garbage collection.
375+
It is typically easier to arrange that assembly functions do not
376+
return pointers or do not contain call instructions;
377+
no assembly functions in the standard library use
378+
<code>GO_RESULTS_INITIALIZED</code>.
379+
</p>
380+
381+
<p>
382+
If a function has no local stack frame,
383+
the pointer information can be omitted.
384+
This is indicated by a local frame size annotation of <code>$0-<i>n</i></code>
385+
on the <code>TEXT</code> instruction.
386+
The pointer information can also be omitted if the
387+
function contains no call instructions.
388+
Otherwise, the local stack frame must not contain pointers,
389+
and the assembly must confirm this fact by executing the
390+
pseudo-instruction <code>NO_LOCAL_POINTERS</code>.
391+
Because stack resizing is implemented by moving the stack,
392+
the stack pointer may change during any function call:
393+
even pointers to stack data must not be kept in local variables.
394+
</p>
395+
302396
<h2 id="architectures">Architecture-specific details</h2>
303397

304398
<p>
@@ -434,13 +528,10 @@ <h3 id="unsupported_opcodes">Unsupported opcodes</h3>
434528
// so actually
435529
// void atomicload64(uint64 *res, uint64 volatile *addr);
436530
TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
437-
MOVL 4(SP), BX
438-
MOVL 8(SP), AX
439-
// MOVQ (%EAX), %MM0
440-
BYTE $0x0f; BYTE $0x6f; BYTE $0x00
441-
// MOVQ %MM0, 0(%EBX)
442-
BYTE $0x0f; BYTE $0x7f; BYTE $0x03
443-
// EMMS
444-
BYTE $0x0F; BYTE $0x77
531+
MOVL ptr+0(FP), AX
532+
LEAL ret_lo+4(FP), BX
533+
BYTE $0x0f; BYTE $0x6f; BYTE $0x00 // MOVQ (%EAX), %MM0
534+
BYTE $0x0f; BYTE $0x7f; BYTE $0x03 // MOVQ %MM0, 0(%EBX)
535+
BYTE $0x0F; BYTE $0x77 // EMMS
445536
RET
446537
</pre>

‎src/runtime/funcdata.h

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
// defines the pointer map for the function's arguments.
2929
// GO_ARGS should be the first instruction in a function that uses it.
3030
// It can be omitted if there are no arguments at all.
31+
// GO_ARGS is inserted implicitly by the linker for any function
32+
// that also has a Go prototype and therefore is usually not necessary
33+
// to write explicitly.
3134
#define GO_ARGS FUNCDATA $FUNCDATA_ArgsPointerMaps, go_args_stackmap(SB)
3235

3336
// GO_RESULTS_INITIALIZED indicates that the assembly function

0 commit comments

Comments
 (0)
Please sign in to comment.