Documentation ¶
Index ¶
- Constants
- Variables
- func Bool2int(b bool) int
- func CConv(s uint8) string
- func Dconv(p *Prog, a *Addr) string
- func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc)
- func Mconv(a *Addr) string
- func Nopout(p *Prog)
- func Rconv(reg int) string
- func RegisterOpcode(lo As, Anames []string)
- func RegisterRegister(lo, hi int, Rconv func(int) string)
- func SortSlice(slice interface{}, less func(i, j int) bool)
- func WriteObjFile(ctxt *Link, b *bufio.Writer)
- type Addr
- type AddrName
- type AddrType
- type As
- type Attribute
- func (a Attribute) CFunc() bool
- func (a Attribute) DuplicateOK() bool
- func (a Attribute) Leaf() bool
- func (a Attribute) Local() bool
- func (a Attribute) MakeTypelink() bool
- func (a Attribute) NeedCtxt() bool
- func (a Attribute) NoFrame() bool
- func (a Attribute) NoSplit() bool
- func (a Attribute) OnList() bool
- func (a Attribute) ReflectMethod() bool
- func (a Attribute) SeenGlobl() bool
- func (a *Attribute) Set(flag Attribute, value bool)
- func (a Attribute) Static() bool
- func (a Attribute) TextAttrString() string
- func (a Attribute) Wrapper() bool
- type Auto
- type FuncInfo
- type InlTree
- type InlinedCall
- type LSym
- func (s *LSym) Grow(lsiz int64)
- func (s *LSym) GrowCap(c int64)
- func (s *LSym) Len() int64
- func (s *LSym) String() string
- func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64)
- func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64
- func (s *LSym) WriteFloat32(ctxt *Link, off int64, f float32)
- func (s *LSym) WriteFloat64(ctxt *Link, off int64, f float64)
- func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64)
- func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64)
- func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string)
- func (s *LSym) WriteWeakOff(ctxt *Link, off int64, rsym *LSym, roff int64)
- type Link
- func (ctxt *Link) AddImport(pkg string)
- func (ctxt *Link) CanReuseProgs() bool
- func (ctxt *Link) Dconv(a *Addr) string
- func (ctxt *Link) Diag(format string, args ...interface{})
- func (ctxt *Link) FixedFrameSize() int64
- func (ctxt *Link) Float32Sym(f float32) *LSym
- func (ctxt *Link) Float64Sym(f float64) *LSym
- func (ctxt *Link) Globl(s *LSym, size int64, flag int)
- func (ctxt *Link) InitTextSym(s *LSym, flag int)
- func (ctxt *Link) Int64Sym(i int64) *LSym
- func (ctxt *Link) Logf(format string, args ...interface{})
- func (ctxt *Link) Lookup(name string) *LSym
- func (ctxt *Link) LookupDerived(s *LSym, name string) *LSym
- func (ctxt *Link) LookupInit(name string, init func(s *LSym)) *LSym
- func (ctxt *Link) LookupStatic(name string) *LSym
- func (ctxt *Link) NewProg() *Prog
- func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos
- type LinkArch
- type Pcdata
- type Pcln
- type Plist
- type Prog
- type ProgAlloc
- type Reloc
Constants ¶
const ( ABase386 = (1 + iota) << 10 ABaseARM ABaseAMD64 ABasePPC64 ABaseARM64 ABaseMIPS ABaseS390X AllowedOpCodes = 1 << 10 // The number of opcodes available for any given architecture. AMask = AllowedOpCodes - 1 // AND with this to use the opcode as an array index. )
Each architecture is allotted a distinct subspace of opcode values for declaring its arch-specific opcodes. Within this subspace, the first arch-specific opcode should be at offset A_ARCHSPECIFIC.
Subspaces are aligned to a power of two so opcodes can be masked with AMask and used as compact array indices.
const ( // Don't profile the marked routine. // // Deprecated: Not implemented, do not use. NOPROF = 1 // It is ok for the linker to get multiple of these symbols. It will // pick one of the duplicates to use. DUPOK = 2 // Don't insert stack check preamble. NOSPLIT = 4 // Put this data in a read-only section. RODATA = 8 // This data contains no pointers. NOPTR = 16 // This is a wrapper function and should not count as disabling 'recover'. WRAPPER = 32 // This function uses its incoming context register. NEEDCTXT = 64 // When passed to ggloblsym, causes Local to be set to true on the LSym it creates. LOCAL = 128 // Allocate a word of thread local storage and store the offset from the // thread local base to the thread local storage in this variable. TLSBSS = 256 // Do not insert instructions to allocate a stack frame for this function. // Only valid on functions that declare a frame size of 0. // TODO(mwhudson): only implemented for ppc64x at present. NOFRAME = 512 // Function can call reflect.Type.Method or reflect.Type.MethodByName. REFLECTMETHOD = 1024 )
const ( C_SCOND = (1 << 4) - 1 C_SBIT = 1 << 4 C_PBIT = 1 << 5 C_WBIT = 1 << 6 C_FBIT = 1 << 7 C_UBIT = 1 << 7 C_SCOND_XOR = 14 )
ARM scond byte
const ( // Because of masking operations in the encodings, each register // space should start at 0 modulo some power of 2. RBase386 = 1 * 1024 RBaseAMD64 = 2 * 1024 RBaseARM = 3 * 1024 RBasePPC64 = 4 * 1024 // range [4k, 8k) RBaseARM64 = 8 * 1024 // range [8k, 13k) RBaseMIPS = 13 * 1024 // range [13k, 14k) RBaseS390X = 14 * 1024 // range [14k, 15k) )
const (
LOG = 5
)
const REG_NONE = 0
Variables ¶
var Anames = []string{
"XXX",
"CALL",
"DUFFCOPY",
"DUFFZERO",
"END",
"FUNCDATA",
"JMP",
"NOP",
"PCDATA",
"RET",
"TEXT",
"UNDEF",
}
Functions ¶
func Flushplist ¶
func RegisterOpcode ¶
RegisterOpcode binds a list of instruction names to a given instruction number range.
func RegisterRegister ¶
RegisterRegister binds a pretty-printer (Rconv) for register numbers to a given register number range. Lo is inclusive, hi exclusive (valid registers are lo through hi-1).
func WriteObjFile ¶
Types ¶
type Addr ¶
type Addr struct { Reg int16 Index int16 Scale int16 // Sometimes holds a register. Type AddrType Name AddrName Class int8 Offset int64 Sym *LSym // argument value: // for TYPE_SCONST, a string // for TYPE_FCONST, a float64 // for TYPE_BRANCH, a *Prog (optional) // for TYPE_TEXTSIZE, an int32 (optional) Val interface{} }
An Addr is an argument to an instruction. The general forms and their encodings are:
sym±offset(symkind)(reg)(index*scale) Memory reference at address &sym(symkind) + offset + reg + index*scale. Any of sym(symkind), ±offset, (reg), (index*scale), and *scale can be omitted. If (reg) and *scale are both omitted, the resulting expression (index) is parsed as (reg). To force a parsing as index*scale, write (index*1). Encoding: type = TYPE_MEM name = symkind (NAME_AUTO, ...) or 0 (NAME_NONE) sym = sym offset = ±offset reg = reg (REG_*) index = index (REG_*) scale = scale (1, 2, 4, 8) $<mem> Effective address of memory reference <mem>, defined above. Encoding: same as memory reference, but type = TYPE_ADDR. $<±integer value> This is a special case of $<mem>, in which only ±offset is present. It has a separate type for easy recognition. Encoding: type = TYPE_CONST offset = ±integer value *<mem> Indirect reference through memory reference <mem>, defined above. Only used on x86 for CALL/JMP *sym(SB), which calls/jumps to a function pointer stored in the data word sym(SB), not a function named sym(SB). Encoding: same as above, but type = TYPE_INDIR. $*$<mem> No longer used. On machines with actual SB registers, $*$<mem> forced the instruction encoding to use a full 32-bit constant, never a reference relative to SB. $<floating point literal> Floating point constant value. Encoding: type = TYPE_FCONST val = floating point value $<string literal, up to 8 chars> String literal value (raw bytes used for DATA instruction). Encoding: type = TYPE_SCONST val = string <register name> Any register: integer, floating point, control, segment, and so on. If looking for specific register kind, must check type and reg value range. Encoding: type = TYPE_REG reg = reg (REG_*) x(PC) Encoding: type = TYPE_BRANCH val = Prog* reference OR ELSE offset = target pc (branch takes priority) $±x-±y Final argument to TEXT, specifying local frame size x and argument size y. In this form, x and y are integer literals only, not arbitrary expressions. This avoids parsing ambiguities due to the use of - as a separator. The ± are optional. If the final argument to TEXT omits the -±y, the encoding should still use TYPE_TEXTSIZE (not TYPE_CONST), with u.argsize = ArgsSizeUnknown. Encoding: type = TYPE_TEXTSIZE offset = x val = int32(y) reg<<shift, reg>>shift, reg->shift, reg@>shift Shifted register value, for ARM and ARM64. In this form, reg must be a register and shift can be a register or an integer constant. Encoding: type = TYPE_SHIFT On ARM: offset = (reg&15) | shifttype<<5 | count shifttype = 0, 1, 2, 3 for <<, >>, ->, @> count = (reg&15)<<8 | 1<<4 for a register shift count, (n&31)<<7 for an integer constant. On ARM64: offset = (reg&31)<<16 | shifttype<<22 | (count&63)<<10 shifttype = 0, 1, 2 for <<, >>, -> (reg, reg) A destination register pair. When used as the last argument of an instruction, this form makes clear that both registers are destinations. Encoding: type = TYPE_REGREG reg = first register offset = second register [reg, reg, reg-reg] Register list for ARM. Encoding: type = TYPE_REGLIST offset = bit mask of registers in list; R0 is low bit. reg, reg Register pair for ARM. TYPE_REGREG2 (reg+reg) Register pair for PPC64. Encoding: type = TYPE_MEM reg = first register index = second register scale = 1
type As ¶
type As int16
An As denotes an assembler opcode. There are some portable opcodes, declared here in package obj, that are common to all architectures. However, the majority of opcodes are arch-specific and are declared in their respective architecture's subpackage.
type Attribute ¶
type Attribute int16
Attribute is a set of symbol attributes.
const ( AttrDuplicateOK Attribute = 1 << iota AttrCFunc AttrNoSplit AttrLeaf AttrWrapper AttrNeedCtxt AttrNoFrame AttrSeenGlobl AttrOnList AttrStatic // MakeTypelink means that the type should have an entry in the typelink table. AttrMakeTypelink // ReflectMethod means the function may call reflect.Type.Method or // reflect.Type.MethodByName. Matching is imprecise (as reflect.Type // can be used through a custom interface), so ReflectMethod may be // set in some cases when the reflect package is not called. // // Used by the linker to determine what methods can be pruned. AttrReflectMethod // Local means make the symbol local even when compiling Go code to reference Go // symbols in other shared libraries, as in this mode symbols are global by // default. "local" here means in the sense of the dynamic linker, i.e. not // visible outside of the module (shared library or executable) that contains its // definition. (When not compiling to support Go shared libraries, all symbols are // local in this sense unless there is a cgo_export_* directive). AttrLocal )
func (Attribute) DuplicateOK ¶
func (Attribute) MakeTypelink ¶
func (Attribute) ReflectMethod ¶
func (Attribute) TextAttrString ¶
TextAttrString formats a for printing in as part of a TEXT prog.
type FuncInfo ¶
type FuncInfo struct { Args int32 Locals int32 Text *Prog Autom []*Auto Pcln Pcln GCArgs LSym GCLocals LSym // contains filtered or unexported fields }
A FuncInfo contains extra fields for STEXT symbols.
type InlTree ¶
type InlTree struct {
// contains filtered or unexported fields
}
InlTree s a collection of inlined calls. The Parent field of an InlinedCall is the index of another InlinedCall in InlTree.
The compiler maintains a global inlining tree and adds a node to it every time a function is inlined. For example, suppose f() calls g() and g has two calls to h(), and that f, g, and h are inlineable:
1 func main() { 2 f() 3 } 4 func f() { 5 g() 6 } 7 func g() { 8 h() 9 h()
10 }
Assuming the global tree starts empty, inlining will produce the following tree:
[]InlinedCall{ {Parent: -1, Func: "f", Pos: <line 2>}, {Parent: 0, Func: "g", Pos: <line 5>}, {Parent: 1, Func: "h", Pos: <line 8>}, {Parent: 1, Func: "h", Pos: <line 9>}, }
The nodes of h inlined into main will have inlining indexes 2 and 3.
Eventually, the compiler extracts a per-function inlining tree from the global inlining tree (see pcln.go).
type InlinedCall ¶
type InlinedCall struct { Parent int // index of the parent in the InlTree or < 0 if outermost call Pos src.XPos // position of the inlined call Func *LSym // function that was inlined }
InlinedCall is a node in an InlTree.
type LSym ¶
type LSym struct { Name string Type objabi.SymKind Attribute RefIdx int // Index of this symbol in the symbol reference list. Size int64 Gotype *LSym P []byte R []Reloc Func *FuncInfo }
An LSym is the sort of symbol that is written to an object file.
func (*LSym) String ¶
The compiler needs LSym to satisfy fmt.Stringer, because it stores an LSym in ssa.ExternSymbol.
func (*LSym) WriteAddr ¶
WriteAddr writes an address of size siz into s at offset off. rsym and roff specify the relocation for the address.
func (*LSym) WriteBytes ¶
WriteBytes writes a slice of bytes into s at offset off.
func (*LSym) WriteFloat32 ¶
WriteFloat32 writes f into s at offset off.
func (*LSym) WriteFloat64 ¶
WriteFloat64 writes f into s at offset off.
func (*LSym) WriteOff ¶
WriteOff writes a 4 byte offset to rsym+roff into s at offset off. After linking the 4 bytes stored at s+off will be rsym+roff-(start of section that s is in).
func (*LSym) WriteString ¶
WriteString writes a string of size siz into s at offset off.
type Link ¶
type Link struct { Headtype objabi.HeadType Arch *LinkArch Debugasm bool Debugvlog bool Debugpcln string Flag_dynlink bool Flag_optimize bool Bso *bufio.Writer Pathname string PosTable src.PosTable InlTree InlTree // global inlining tree used by gc/inl.go Imports []string DiagFunc func(string, ...interface{}) DebugInfo func(fn *LSym, curfn interface{}) []dwarf.Scope // if non-nil, curfn is a *gc.Node Errors int Framepointer_enabled bool // state for writing objects Text []*LSym Data []*LSym // contains filtered or unexported fields }
Link holds the context for writing object code from a compiler to be linker input or for reading that input into the linker.
func (*Link) CanReuseProgs ¶
func (*Link) FixedFrameSize ¶
The smallest possible offset from the hardware stack pointer to a local variable on the stack. Architectures that use a link register save its value on the stack in the function prologue and so always have a pointer between the hardware stack pointer and the local variable area.
func (*Link) Float32Sym ¶
func (*Link) Float64Sym ¶
func (*Link) InitTextSym ¶
func (*Link) Lookup ¶
Lookup looks up the symbol with name name. If it does not exist, it creates it.
func (*Link) LookupDerived ¶
LookupDerived looks up or creates the symbol with name name derived from symbol s. The resulting symbol will be static iff s is.
func (*Link) LookupInit ¶
LookupInit looks up the symbol with name name. If it does not exist, it creates it and passes it to init for one-time initialization.
func (*Link) LookupStatic ¶
LookupStatic looks up the static symbol with name name. If it does not exist, it creates it.
func (*Link) OutermostPos ¶
OutermostPos returns the outermost position corresponding to xpos, which is where xpos was ultimately inlined to. In the example for InlTree, main() contains inlined AST nodes from h(), but the outermost position for those nodes is line 2.
type LinkArch ¶
type LinkArch struct { *sys.Arch Init func(*Link) Preprocess func(*Link, *LSym, ProgAlloc) Assemble func(*Link, *LSym, ProgAlloc) Progedit func(*Link, *Prog, ProgAlloc) UnaryDst map[As]bool // Instruction takes one operand, a destination. }
LinkArch is the definition of a single architecture.
type Prog ¶
type Prog struct { Ctxt *Link // linker context Link *Prog // next Prog in linked list From Addr // first source operand From3 *Addr // third source operand (second is Reg below) To Addr // destination operand (second is RegTo2 below) Pcond *Prog // target of conditional jump Forwd *Prog // for x86 back end Rel *Prog // for x86, arm back ends Pc int64 // for back ends or assembler: virtual or actual program counter, depending on phase Pos src.XPos // source position of this instruction Spadj int32 // effect of instruction on stack pointer (increment or decrement amount) As As // assembler opcode Reg int16 // 2nd source operand RegTo2 int16 // 2nd destination operand Mark uint16 // bitmask of arch-specific items Optab uint16 // arch-specific opcode index Scond uint8 // condition bits for conditional instruction (e.g., on ARM) Back uint8 // for x86 back end: backwards branch state Ft uint8 // for x86 back end: type index of Prog.From Tt uint8 // for x86 back end: type index of Prog.To Isize uint8 // for x86 back end: size of the instruction in bytes }
Prog describes a single machine instruction.
The general instruction form is:
As.Scond From, Reg, From3, To, RegTo2
where As is an opcode and the others are arguments: From, Reg, From3 are sources, and To, RegTo2 are destinations. Usually, not all arguments are present. For example, MOVL R1, R2 encodes using only As=MOVL, From=R1, To=R2. The Scond field holds additional condition bits for systems (like arm) that have generalized conditional execution.
Jump instructions use the Pcond field to point to the target instruction, which must be in the same linked list as the jump instruction.
The Progs for a given function are arranged in a list linked through the Link field.
Each Prog is charged to a specific source line in the debug information, specified by Pos.Line(). Every Prog has a Ctxt field that defines its context. For performance reasons, Progs usually are usually bulk allocated, cached, and reused; those bulk allocators should always be used, rather than new(Prog).
The other fields not yet mentioned are for use by the back ends and should be left zeroed by creators of Prog lists.