From 6de8443f3b324be69a3082a67ce71fa869d1a32b Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 22 Jan 2021 10:58:12 -0500 Subject: [PATCH] doc/asm: add a section on go_asm.h, clean up go_tls.h section Currently the only mention of go_asm.h is buried in a confusing section about the runtime-specific go_tls.h header. We actually want people to use go_asm.h, so this CL adds a section with a proper discussion of this header. As part of this, we remove the discussion of go_asm.h from the go_tls.h section and clean up what remains. I stumbled on this when working on the internal ABI specification. I wanted to refer to stable documentation on how to access struct fields from assembly and found there was none. Change-Id: I0d53741e7685e65794611939e76285f7c82e1d65 Reviewed-on: https://go-review.googlesource.com/c/go/+/286052 Trust: Austin Clements Reviewed-by: Jeremy Faller Reviewed-by: Michael Knyszek --- doc/asm.html | 72 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/doc/asm.html b/doc/asm.html index cc8598aeff8..7173d9bd514 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -464,6 +464,57 @@ Function is the top of the call stack. Traceback should stop at this function. +

Interacting with Go types and constants

+ +

+If a package has any .s files, then go build will direct +the compiler to emit a special header called go_asm.h, +which the .s files can then #include. +The file contains symbolic #define constants for the +offsets of Go struct fields, the sizes of Go struct types, and most +Go const declarations defined in the current package. +Go assembly should avoid making assumptions about the layout of Go +types and instead use these constants. +This improves the readability of assembly code, and keeps it robust to +changes in data layout either in the Go type definitions or in the +layout rules used by the Go compiler. +

+ +

+Constants are of the form const_name. +For example, given the Go declaration const bufSize = +1024, assembly code can refer to the value of this constant +as const_bufSize. +

+ +

+Field offsets are of the form type_field. +Struct sizes are of the form type__size. +For example, consider the following Go definition: +

+ +
+type reader struct {
+	buf [bufSize]byte
+	r   int
+}
+
+ +

+Assembly can refer to the size of this struct +as reader__size and the offsets of the two fields +as reader_buf and reader_r. +Hence, if register R1 contains a pointer to +a reader, assembly can reference the r field +as reader_r(R1). +

+ +

+If any of these #define names are ambiguous (for example, +a struct with a _size field), #include +"go_asm.h" will fail with a "redefinition of macro" error. +

+

Runtime Coordination

@@ -615,21 +666,15 @@ Here follow some descriptions of key Go-specific details for the supported archi

The runtime pointer to the g structure is maintained through the value of an otherwise unused (as far as Go is concerned) register in the MMU. -An OS-dependent macro get_tls is defined for the assembler if the source is -in the runtime package and includes a special header, go_tls.h: +In the runtime package, assembly code can include go_tls.h, which defines +an OS- and architecture-dependent macro get_tls for accessing this register. +The get_tls macro takes one argument, which is the register to load the +g pointer into.

-
-#include "go_tls.h"
-
-

-Within the runtime, the get_tls macro loads its argument register -with a pointer to the g pointer, and the g struct -contains the m pointer. -There's another special header containing the offsets for each -element of g, called go_asm.h. -The sequence to load g and m using CX looks like this: +For example, the sequence to load g and m +using CX looks like this:

@@ -642,8 +687,7 @@ MOVL	g_m(AX), BX   // Move g.m into BX.
 

-Note: The code above works only in the runtime package, while go_tls.h also -applies to arm, amd64 and amd64p32, and go_asm.h applies to all architectures. +The get_tls macro is also defined on amd64.