Functions
AbiForBodylessFuncStackMap
function
#
AbiForBodylessFuncStackMap returns the ABI for a bodyless function's stack map.
This is not necessarily the ABI used to call it.
Currently (1.17 dev) such a stack map is always ABI0;
any ABI wrapper that is present is nosplit, hence a precise
stack map is not needed there (the parameters survive only long
enough to call the wrapped assembly function).
This always returns a freshly copied ABI.
func AbiForBodylessFuncStackMap(fn *ir.Func) *abi.ABIConfig
AddAux
function
#
AddAux adds the offset in the aux fields (AuxInt and Aux) of v to a.
func AddAux(a *obj.Addr, v *ssa.Value)
AddAux2
function
#
func AddAux2(a *obj.Addr, v *ssa.Value, offset int64)
AddrAuto
function
#
func AddrAuto(a *obj.Addr, v *ssa.Value)
AllocFrame
method
#
func (s *ssafn) AllocFrame(f *ssa.Func)
Br
method
#
Br emits a single branch instruction and returns the instruction.
Not all architectures need the returned instruction, but otherwise
the boilerplate is common to all.
func (s *State) Br(op obj.As, target *ssa.Block) *obj.Prog
Call
method
#
Call returns a new CALL instruction for the SSA value v.
It uses PrepareCall to prepare the call.
func (s *State) Call(v *ssa.Value) *obj.Prog
CanBeAnSSAAux
method
#
func (fwdRefAux) CanBeAnSSAAux()
CheckArgReg
function
#
CheckArgReg ensures that v is in the function's entry block.
func CheckArgReg(v *ssa.Value)
CheckLargeStacks
function
#
func CheckLargeStacks()
CheckLoweredGetClosurePtr
function
#
CheckLoweredGetClosurePtr checks that v is the first instruction in the function's entry block,
except for incoming in-register arguments.
The output of LoweredGetClosurePtr is generally hardwired to the correct register.
That register contains the closure pointer on closure entry.
func CheckLoweredGetClosurePtr(v *ssa.Value)
CheckLoweredPhi
function
#
CheckLoweredPhi checks that regalloc and stackalloc correctly handled phi values.
Called during ssaGenValue.
func CheckLoweredPhi(v *ssa.Value)
CombJump
method
#
CombJump generates combinational instructions (2 at present) for a block jump,
thereby the behaviour of non-standard condition codes could be simulated
func (s *State) CombJump(b *ssa.Block, next *ssa.Block, jumps *[2][2]IndexJump)
Compile
function
#
Compile builds an SSA backend function,
uses it to generate a plist,
and flushes that plist to machine code.
worker indicates which of the backend workers is doing the processing.
func Compile(fn *ir.Func, worker int, profile *pgoir.Profile)
CreateWasmImportWrapper
function
#
CreateWasmImportWrapper creates a wrapper for imported WASM functions to
adapt them to the Go calling convention. The body for this function is
generated in cmd/internal/obj/wasm/wasmobj.go
func CreateWasmImportWrapper(fn *ir.Func) bool
DebugFriendlySetPosFrom
method
#
DebugFriendlySetPosFrom adjusts Pos.IsStmt subject to heuristics
that reduce "jumpy" line number churn when debugging.
Spill/fill/copy instructions from the register allocator,
phi functions, and instructions with a no-pos position
are examples of instructions that can cause churn.
func (s *State) DebugFriendlySetPosFrom(v *ssa.Value)
Debug_checknil
method
#
func (s *state) Debug_checknil() bool
Debug_checknil
method
#
func (e *ssafn) Debug_checknil() bool
DumpInline
function
#
func DumpInline(fn *ir.Func)
EmitArgInfo
function
#
emit argument info (locations on stack) of f for traceback.
func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym
EnableNoWriteBarrierRecCheck
function
#
func EnableNoWriteBarrierRecCheck()
Fatalf
method
#
Fatalf reports a compiler error and exits.
func (e *ssafn) Fatalf(pos src.XPos, msg string, args ...interface{})
Fatalf
method
#
func (s *state) Fatalf(msg string, args ...interface{})
Func
method
#
func (e *ssafn) Func() *ir.Func
FuncInfo
method
#
func (s *State) FuncInfo() *obj.FuncInfo
GenABIWrappers
method
#
GenABIWrappers applies ABI information to Funcs and generates ABI
wrapper functions where necessary.
func (s *SymABIs) GenABIWrappers()
GenWasmExportWrapper
function
#
func GenWasmExportWrapper(wrapped *ir.Func)
InitConfig
function
#
func InitConfig()
InitEnv
function
#
func InitEnv()
InitTables
function
#
func InitTables()
IsIntrinsicCall
function
#
func IsIntrinsicCall(n *ir.CallExpr) bool
Len
method
#
func (h *blockHeap) Len() int
Less
method
#
func (h *blockHeap) Less(i int, j int) bool
Log
method
#
func (s *state) Log() bool
Log
method
#
func (e *ssafn) Log() bool
Logf
method
#
Logf logs a message from the compiler.
func (e *ssafn) Logf(msg string, args ...interface{})
Logf
method
#
func (s *state) Logf(msg string, args ...interface{})
NewSymABIs
function
#
func NewSymABIs() *SymABIs
NoWriteBarrierRecCheck
function
#
func NoWriteBarrierRecCheck()
Pc
method
#
Pc returns the current Prog.
func (s *State) Pc() *obj.Prog
Pop
method
#
func (h *blockHeap) Pop() interface{}
PrepareCall
method
#
PrepareCall prepares to emit a CALL instruction for v and does call-related bookkeeping.
It must be called immediately before emitting the actual CALL instruction,
since it emits PCDATA for the stack map at the call (calls are safe points).
func (s *State) PrepareCall(v *ssa.Value)
Prog
method
#
Prog appends a new Prog.
func (s *State) Prog(as obj.As) *obj.Prog
Push
method
#
func (h *blockHeap) Push(x interface{})
ReadSymABIs
method
#
ReadSymABIs reads a symabis file that specifies definitions and
references of text symbols by ABI.
The symabis format is a set of lines, where each line is a sequence
of whitespace-separated fields. The first field is a verb and is
either "def" for defining a symbol ABI or "ref" for referencing a
symbol using an ABI. For both "def" and "ref", the second field is
the symbol name and the third field is the ABI name, as one of the
named cmd/internal/obj.ABI constants.
func (s *SymABIs) ReadSymABIs(file string)
RegisterMapInitLsym
function
#
RegisterMapInitLsym records "s" in the set of outlined map initializer
functions.
func RegisterMapInitLsym(s *obj.LSym)
SetPos
method
#
SetPos sets the current source position.
func (s *State) SetPos(pos src.XPos)
SpillSlotAddr
function
#
SpillSlotAddr uses LocalSlot information to initialize an obj.Addr
The resulting addr is used in a non-standard context -- in the prologue
of a function, before the frame has been constructed, so the standard
addressing for the parameters will be wrong.
func SpillSlotAddr(spill ssa.Spill, baseReg int16, extraOffset int64) obj.Addr
SplitSlot
method
#
SplitSlot returns a slot representing the data of parent starting at offset.
func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t *types.Type) ssa.LocalSlot
StackOffset
function
#
StackOffset returns the stack location of a LocalSlot relative to the
stack pointer, suitable for use in a DWARF location entry. This has nothing
to do with its offset in the user variable.
func StackOffset(slot ssa.LocalSlot) int32
StringData
method
#
StringData returns a symbol which
is the data component of a global string constant containing s.
func (e *ssafn) StringData(s string) *obj.LSym
Swap
method
#
func (h *blockHeap) Swap(i int, j int)
Syslook
method
#
func (e *ssafn) Syslook(name string) *obj.LSym
TailCall
method
#
TailCall returns a new tail call instruction for the SSA value v.
It is like Call, but for a tail call.
func (s *State) TailCall(v *ssa.Value) *obj.Prog
UseArgs
method
#
UseArgs records the fact that an instruction needs a certain amount of
callee args space for its use.
func (s *State) UseArgs(n int64)
UseWriteBarrier
method
#
func (e *ssafn) UseWriteBarrier() bool
Warnl
method
#
func (s *state) Warnl(pos src.XPos, msg string, args ...interface{})
Warnl
method
#
Warnl reports a "warning", which is usually flag-triggered
logging output for the benefit of tests.
func (e *ssafn) Warnl(pos src.XPos, fmt_ string, args ...interface{})
abiForFunc
function
#
abiForFunc implements ABI policy for a function, but does not return a copy of the ABI.
Passing a nil function returns the default ABI based on experiment configuration.
func abiForFunc(fn *ir.Func, abi0 *abi.ABIConfig, abi1 *abi.ABIConfig) *abi.ABIConfig
add
method
#
func (s *sparseSet) add(x ssa.ID)
add
method
#
add adds the intrinsic builder b for pkg.fn for the given architecture.
func (ib intrinsicBuilders) add(arch *sys.Arch, pkg string, fn string, b intrinsicBuilder)
addForArchs
method
#
addForArchs adds the intrinsic builder b for pkg.fn for the given architectures.
func (ib intrinsicBuilders) addForArchs(pkg string, fn string, b intrinsicBuilder, archs ...*sys.Arch)
addForFamilies
method
#
addForFamilies does the same as addForArchs but operates on architecture families.
func (ib intrinsicBuilders) addForFamilies(pkg string, fn string, b intrinsicBuilder, archFamilies ...sys.ArchFamily)
addNamedValue
method
#
func (s *state) addNamedValue(n *ir.Name, v *ssa.Value)
addr
method
#
addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
The value that the returned Value represents is guaranteed to be non-nil.
func (s *state) addr(n ir.Node) *ssa.Value
alias
method
#
alias aliases pkg.fn to targetPkg.targetFn for all architectures in archs
for which targetPkg.targetFn already exists.
func (ib intrinsicBuilders) alias(pkg string, fn string, targetPkg string, targetFn string, archs ...*sys.Arch)
append
method
#
append converts an OAPPEND node to SSA.
If inplace is false, it converts the OAPPEND expression n to an ssa.Value,
adds it to s, and returns the Value.
If inplace is true, it writes the result of the OAPPEND expression n
back to the slice being appended to, and returns nil.
inplace MUST be set to false if the slice can be SSA'd.
Note: this code only handles fixed-count appends. Dotdotdot appends
have already been rewritten at this point (by walk).
func (s *state) append(n *ir.CallExpr, inplace bool) *ssa.Value
assign
method
#
assign does left = right.
Right has already been evaluated to ssa, left has not.
If deref is true, then we do left = *right instead (and right has already been nil-checked).
If deref is true and right == nil, just do left = 0.
skip indicates assignments (at the top level) that can be avoided.
mayOverlap indicates whether left&right might partially overlap in memory. Default is false.
func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask)
assignWhichMayOverlap
method
#
func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool, skip skipMask, mayOverlap bool)
boundsCheck
method
#
boundsCheck generates bounds checking code. Checks if 0 <= idx <[=] len, branches to exit if not.
Starts a new block on return.
On input, len must be converted to full int width and be nonnegative.
Returns idx converted to full int width.
If bounded is true then caller guarantees the index is not out of bounds
(but boundsCheck will still extend the index to full int width).
func (s *state) boundsCheck(idx *ssa.Value, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value
buildssa
function
#
buildssa builds an SSA function for fn.
worker indicates which of the backend workers is doing the processing.
func buildssa(fn *ir.Func, worker int, isPgoHot bool) *ssa.Func
call
method
#
Calls the function n using the specified call type.
Returns the address of the return value (or nil if none).
func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExtra ir.Expr) *ssa.Value
callAddr
method
#
func (s *state) callAddr(n *ir.CallExpr, k callKind) *ssa.Value
callResult
method
#
func (s *state) callResult(n *ir.CallExpr, k callKind) *ssa.Value
callTargetLSym
function
#
callTargetLSym returns the correct LSym to call 'callee' using its ABI.
func callTargetLSym(callee *ir.Name) *obj.LSym
canSSA
method
#
canSSA reports whether n is SSA-able.
n must be an ONAME (or an ODOT sequence with an ONAME base).
func (s *state) canSSA(n ir.Node) bool
canSSAName
method
#
func (s *state) canSSAName(name *ir.Name) bool
canonicalize
method
#
canonicalize returns the canonical name used for a linker symbol in
s's maps. Symbols in this package may be written either as "".X or
with the package's import path already in the symbol. This rewrites
both to use the full path, which matches compiler-generated linker
symbol names.
func (s *SymABIs) canonicalize(linksym string) string
check
method
#
If cmp (a bool) is false, panic using the given function.
func (s *state) check(cmp *ssa.Value, fn *obj.LSym)
check
method
#
func (c *nowritebarrierrecChecker) check()
checkPtrAlignment
method
#
func (s *state) checkPtrAlignment(n *ir.ConvExpr, v *ssa.Value, count *ssa.Value)
clear
method
#
func (s *sparseSet) clear()
clobberBase
function
#
func clobberBase(n ir.Node) ir.Node
cmpstackvarlt
function
#
cmpstackvarlt reports whether the stack variable a sorts before b.
func cmpstackvarlt(a *ir.Name, b *ir.Name, mls *liveness.MergeLocalsState) bool
concreteEtype
method
#
func (s *state) concreteEtype(t *types.Type) types.Kind
condBranch
method
#
condBranch evaluates the boolean expression cond and branches to yes
if cond is true and no if cond is false.
This function is intended to handle && and || better than just calling
s.expr(cond) and branching on the result.
func (s *state) condBranch(cond ir.Node, yes *ssa.Block, no *ssa.Block, likely int8)
constBool
method
#
func (s *state) constBool(c bool) *ssa.Value
constEmptyString
method
#
func (s *state) constEmptyString(t *types.Type) *ssa.Value
constFloat32
method
#
func (s *state) constFloat32(t *types.Type, c float64) *ssa.Value
constFloat64
method
#
func (s *state) constFloat64(t *types.Type, c float64) *ssa.Value
constInt
method
#
func (s *state) constInt(t *types.Type, c int64) *ssa.Value
constInt16
method
#
func (s *state) constInt16(t *types.Type, c int16) *ssa.Value
constInt32
method
#
func (s *state) constInt32(t *types.Type, c int32) *ssa.Value
constInt64
method
#
func (s *state) constInt64(t *types.Type, c int64) *ssa.Value
constInt8
method
#
func (s *state) constInt8(t *types.Type, c int8) *ssa.Value
constInterface
method
#
func (s *state) constInterface(t *types.Type) *ssa.Value
constNil
method
#
func (s *state) constNil(t *types.Type) *ssa.Value
constOffPtrSP
method
#
func (s *state) constOffPtrSP(t *types.Type, c int64) *ssa.Value
constSlice
method
#
const* routines add a new const value to the entry block.
func (s *state) constSlice(t *types.Type) *ssa.Value
contains
method
#
func (s *sparseSet) contains(x ssa.ID) bool
conv
method
#
func (s *state) conv(n ir.Node, v *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
deferstruct
function
#
deferstruct returns a type interchangeable with runtime._defer.
Make sure this stays in sync with runtime/runtime2.go:_defer.
func deferstruct() *types.Type
defframe
function
#
func defframe(s *State, e *ssafn, f *ssa.Func)
dottype
method
#
dottype generates SSA for a type assertion node.
commaok indicates whether to panic or return a bool.
If commaok is false, resok will be nil.
func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res *ssa.Value, resok *ssa.Value)
dottype1
method
#
dottype1 implements a x.(T) operation. iface is the argument (x), dst is the type we're asserting to (T)
and src is the type we're asserting from.
source is the *runtime._type of src
target is the *runtime._type of dst.
If src is a nonempty interface and dst is not an interface, targetItab is an itab representing (dst, src). Otherwise it is nil.
commaok is true if the caller wants a boolean success value. Otherwise, the generated code panics if the conversion fails.
descriptor is a compiler-allocated internal/abi.TypeAssert whose address is passed to runtime.typeAssert when
the target type is a compile-time-known non-empty interface. It may be nil.
func (s *state) dottype1(pos src.XPos, src *types.Type, dst *types.Type, iface *ssa.Value, source *ssa.Value, target *ssa.Value, targetItab *ssa.Value, commaok bool, descriptor *obj.LSym) (res *ssa.Value, resok *ssa.Value)
dumpSourcesColumn
function
#
func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *ir.Func)
dynamicDottype
method
#
func (s *state) dynamicDottype(n *ir.DynamicTypeAssertExpr, commaok bool) (res *ssa.Value, resok *ssa.Value)
emitArgInfo
function
#
emit argument info (locations on stack) for traceback.
func emitArgInfo(e *ssafn, f *ssa.Func, pp *objw.Progs)
emitOpenDeferInfo
method
#
emitOpenDeferInfo emits FUNCDATA information about the defers in a function
that is using open-coded defers. This funcdata is used to determine the active
defers in a function and execute those defers during panic processing.
The funcdata is all encoded in varints (since values will almost always be less than
128, but stack offsets could potentially be up to 2Gbyte). All "locations" (offsets)
for stack variables are specified as the number of bytes below varp (pointer to the
top of the local variables) for their starting address. The format is:
- Offset of the deferBits variable
- Offset of the first closure slot (the rest are laid out consecutively).
func (s *state) emitOpenDeferInfo()
emitWrappedFuncInfo
function
#
for wrapper, emit info of wrapped function.
func emitWrappedFuncInfo(e *ssafn, pp *objw.Progs)
endBlock
method
#
endBlock marks the end of generating code for the current block.
Returns the (former) current block. Returns nil if there is no current
block, i.e. if no code flows to the current execution point.
func (s *state) endBlock() *ssa.Block
entryBlock
method
#
func (s *state) entryBlock() *ssa.Block
entryNewValue0
method
#
entryNewValue0 adds a new value with no arguments to the entry block.
func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value
entryNewValue0A
method
#
entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value
entryNewValue1
method
#
entryNewValue1 adds a new value with one argument to the entry block.
func (s *state) entryNewValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value
entryNewValue1A
method
#
entryNewValue1A adds a new value with one argument and an aux value to the entry block.
func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value
entryNewValue1I
method
#
entryNewValue1I adds a new value with one argument and an auxint value to the entry block.
func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa.Value) *ssa.Value
entryNewValue2
method
#
entryNewValue2 adds a new value with two arguments to the entry block.
func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
entryNewValue2A
method
#
entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
etypesign
function
#
etypesign returns the signed-ness of e, for integer/pointer etypes.
-1 means signed, +1 means unsigned, 0 means non-integer/non-pointer.
func etypesign(e types.Kind) int8
exit
method
#
exit processes any code that needs to be generated just before returning.
It returns a BlockRet block that ends the control flow. Its control value
will be set to the final memory state.
func (s *state) exit() *ssa.Block
expr
method
#
expr converts the expression n to ssa, adds it to s and returns the ssa result.
func (s *state) expr(n ir.Node) *ssa.Value
exprCheckPtr
method
#
func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value
exprPtr
method
#
exprPtr evaluates n to a pointer and nil-checks it.
func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value
extendIndex
method
#
extendIndex extends v to a full int width.
panic with the given kind if v does not fit in an int (only on 32-bit archs).
func (s *state) extendIndex(idx *ssa.Value, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value
fieldIdx
function
#
fieldIdx finds the index of the field referred to by the ODOT node n.
func fieldIdx(n *ir.SelectorExpr) int
fieldtrack
function
#
fieldtrack adds R_USEFIELD relocations to fnsym to record any
struct fields that it used.
func fieldtrack(fnsym *obj.LSym, tracked map[*obj.LSym]struct{...})
findIntrinsic
function
#
findIntrinsic returns a function which builds the SSA equivalent of the
function identified by the symbol sym. If sym is not an intrinsic call, returns nil.
func findIntrinsic(sym *types.Sym) intrinsicBuilder
float32ToUint32
method
#
func (s *state) float32ToUint32(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
float32ToUint64
method
#
func (s *state) float32ToUint64(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
float64ToUint32
method
#
func (s *state) float64ToUint32(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
float64ToUint64
method
#
func (s *state) float64ToUint64(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
floatToUint
method
#
func (s *state) floatToUint(cvttab *f2uCvtTab, n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
forEachWrapperABI
function
#
func forEachWrapperABI(fn *ir.Func, cb func(fn *ir.Func, wrapperABI obj.ABI))
genssa
function
#
genssa appends entries to pp for each instruction in f.
func genssa(f *ssa.Func, pp *objw.Progs)
getClosureAndRcvr
method
#
getClosureAndRcvr returns values for the appropriate closure and receiver of an
interface call
func (s *state) getClosureAndRcvr(fn *ir.SelectorExpr) (*ssa.Value, *ssa.Value)
initIntrinsics
function
#
func initIntrinsics(cfg *intrinsicBuildConfig)
insertPhis
method
#
func (s *phiState) insertPhis()
insertPhis
method
#
func (s *simplePhiState) insertPhis()
insertPhis
method
#
insertPhis finds all the places in the function where a phi is
necessary and inserts them.
Uses FwdRef ops to find all uses of variables, and s.defvars to find
all definitions.
Phi values are inserted, and all FwdRefs are changed to a Copy
of the appropriate phi or definition.
TODO: make this part of cmd/compile/internal/ssa somehow?
func (s *state) insertPhis()
insertVarPhis
method
#
func (s *phiState) insertVarPhis(n int, var_ ir.Node, defs []*ssa.Block, typ *types.Type)
instrument
method
#
func (s *state) instrument(t *types.Type, addr *ssa.Value, kind instrumentKind)
instrument2
method
#
func (s *state) instrument2(t *types.Type, addr *ssa.Value, addr2 *ssa.Value, kind instrumentKind)
instrumentFields
method
#
instrumentFields instruments a read/write operation on addr.
If it is instrumenting for MSAN or ASAN and t is a struct type, it instruments
operation for each field, instead of for the whole struct.
func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrumentKind)
instrumentMove
method
#
func (s *state) instrumentMove(t *types.Type, dst *ssa.Value, src *ssa.Value)
intDivide
method
#
func (s *state) intDivide(n ir.Node, a *ssa.Value, b *ssa.Value) *ssa.Value
intrinsicArgs
method
#
intrinsicArgs extracts args from n, evaluates them to SSA values, and returns them.
func (s *state) intrinsicArgs(n *ir.CallExpr) []*ssa.Value
intrinsicCall
method
#
intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation.
func (s *state) intrinsicCall(n *ir.CallExpr) *ssa.Value
label
method
#
label returns the label associated with sym, creating it if necessary.
func (s *state) label(sym *types.Sym) *ssaLabel
load
method
#
func (s *state) load(t *types.Type, src *ssa.Value) *ssa.Value
lookup
method
#
lookup looks up the intrinsic for a pkg.fn on the specified architecture.
func (ib intrinsicBuilders) lookup(arch *sys.Arch, pkg string, fn string) intrinsicBuilder
lookupVarOutgoing
method
#
lookupVarOutgoing finds the variable's value at the end of block b.
func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t *types.Type, var_ ir.Node, line src.XPos) *ssa.Value
makeABIWrapper
function
#
makeABIWrapper creates a new function that will be called with
wrapperABI and calls "f" using f.ABI.
func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI)
maybeNilCheckClosure
method
#
maybeNilCheckClosure checks if a nil check of a closure is needed in some
architecture-dependent situations and, if so, emits the nil check.
func (s *state) maybeNilCheckClosure(closure *ssa.Value, k callKind)
mem
method
#
func (s *state) mem() *ssa.Value
minMax
method
#
minMax converts an OMIN/OMAX builtin call into SSA.
func (s *state) minMax(n *ir.CallExpr) *ssa.Value
move
method
#
func (s *state) move(t *types.Type, dst *ssa.Value, src *ssa.Value)
moveWhichMayOverlap
method
#
func (s *state) moveWhichMayOverlap(t *types.Type, dst *ssa.Value, src *ssa.Value, mayOverlap bool)
needAlloc
function
#
needAlloc reports whether n is within the current frame, for which we need to
allocate space. In particular, it excludes arguments and results, which are in
the callers frame.
func needAlloc(n *ir.Name) bool
newHeapaddr
method
#
newHeapaddr allocates heap memory for n and sets its heap address.
func (s *state) newHeapaddr(n *ir.Name)
newNowritebarrierrecChecker
function
#
newNowritebarrierrecChecker creates a nowritebarrierrecChecker. It
must be called before walk.
func newNowritebarrierrecChecker() *nowritebarrierrecChecker
newObject
method
#
newObject returns an SSA value denoting new(typ).
func (s *state) newObject(typ *types.Type, rtype *ssa.Value) *ssa.Value
newSparseSet
function
#
newSparseSet returns a sparseSet that can represent
integers between 0 and n-1.
func newSparseSet(n int) *sparseSet
newValue0
method
#
newValue0 adds a new value with no arguments to the current block.
func (s *state) newValue0(op ssa.Op, t *types.Type) *ssa.Value
newValue0A
method
#
newValue0A adds a new value with no arguments and an aux value to the current block.
func (s *state) newValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value
newValue0I
method
#
newValue0I adds a new value with no arguments and an auxint value to the current block.
func (s *state) newValue0I(op ssa.Op, t *types.Type, auxint int64) *ssa.Value
newValue1
method
#
newValue1 adds a new value with one argument to the current block.
func (s *state) newValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value
newValue1A
method
#
newValue1A adds a new value with one argument and an aux value to the current block.
func (s *state) newValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value
newValue1Apos
method
#
newValue1Apos adds a new value with one argument and an aux value to the current block.
isStmt determines whether the created values may be a statement or not
(i.e., false means never, yes means maybe).
func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value, isStmt bool) *ssa.Value
newValue1I
method
#
newValue1I adds a new value with one argument and an auxint value to the current block.
func (s *state) newValue1I(op ssa.Op, t *types.Type, aux int64, arg *ssa.Value) *ssa.Value
newValue2
method
#
newValue2 adds a new value with two arguments to the current block.
func (s *state) newValue2(op ssa.Op, t *types.Type, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
newValue2A
method
#
newValue2A adds a new value with two arguments and an aux value to the current block.
func (s *state) newValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
newValue2Apos
method
#
newValue2Apos adds a new value with two arguments and an aux value to the current block.
isStmt determines whether the created values may be a statement or not
(i.e., false means never, yes means maybe).
func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0 *ssa.Value, arg1 *ssa.Value, isStmt bool) *ssa.Value
newValue2I
method
#
newValue2I adds a new value with two arguments and an auxint value to the current block.
func (s *state) newValue2I(op ssa.Op, t *types.Type, aux int64, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
newValue3
method
#
newValue3 adds a new value with three arguments to the current block.
func (s *state) newValue3(op ssa.Op, t *types.Type, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value) *ssa.Value
newValue3A
method
#
newValue3A adds a new value with three arguments and an aux value to the current block.
func (s *state) newValue3A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value) *ssa.Value
newValue3Apos
method
#
newValue3Apos adds a new value with three arguments and an aux value to the current block.
isStmt determines whether the created values may be a statement or not
(i.e., false means never, yes means maybe).
func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value, isStmt bool) *ssa.Value
newValue3I
method
#
newValue3I adds a new value with three arguments and an auxint value to the current block.
func (s *state) newValue3I(op ssa.Op, t *types.Type, aux int64, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value) *ssa.Value
newValue4
method
#
newValue4 adds a new value with four arguments to the current block.
func (s *state) newValue4(op ssa.Op, t *types.Type, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value, arg3 *ssa.Value) *ssa.Value
newValue4I
method
#
newValue4I adds a new value with four arguments and an auxint value to the current block.
func (s *state) newValue4I(op ssa.Op, t *types.Type, aux int64, arg0 *ssa.Value, arg1 *ssa.Value, arg2 *ssa.Value, arg3 *ssa.Value) *ssa.Value
newValueOrSfCall1
method
#
newValueOrSfCall* are wrappers around newValue*, which may create a call to a
soft-float runtime function instead (when emitting soft-float code).
func (s *state) newValueOrSfCall1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value
newValueOrSfCall2
method
#
func (s *state) newValueOrSfCall2(op ssa.Op, t *types.Type, arg0 *ssa.Value, arg1 *ssa.Value) *ssa.Value
nilCheck
method
#
nilCheck generates nil pointer checking code.
Used only for automatically inserted nil checks,
not for user code like 'x != nil'.
Returns a "definitely not nil" copy of x to ensure proper ordering
of the uses of the post-nilcheck pointer.
func (s *state) nilCheck(ptr *ssa.Value) *ssa.Value
oneJump
method
#
func (s *State) oneJump(b *ssa.Block, jump *IndexJump)
openDeferExit
method
#
openDeferExit generates SSA for processing all the open coded defers at exit.
The code involves loading deferBits, and checking each of the bits to see if
the corresponding defer statement was executed. For each bit that is turned
on, the associated defer call is made.
func (s *state) openDeferExit()
openDeferRecord
method
#
openDeferRecord adds code to evaluate and store the function for an open-code defer
call, and records info about the defer, so we can generate proper code on the
exit paths. n is the sub-node of the defer node that is the actual function
call. We will also record funcdata information on where the function is stored
(as well as the deferBits variable), and this will enable us to run the proper
defer calls during panics.
func (s *state) openDeferRecord(n *ir.CallExpr)
openDeferSave
method
#
openDeferSave generates SSA nodes to store a value (with type t) for an
open-coded defer at an explicit autotmp location on the stack, so it can be
reloaded and used for the appropriate call on exit. Type t must be a function type
(therefore SSAable). val is the value to be stored. The function returns an SSA
value representing a pointer to the autotmp location.
func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value
paramsToHeap
method
#
paramsToHeap produces code to allocate memory for heap-escaped parameters
and to copy non-result parameters' values from the stack.
func (s *state) paramsToHeap()
paramsToWasmFields
function
#
func paramsToWasmFields(f *ir.Func, pragma string, result *abi.ABIParamResultInfo, abiParams []abi.ABIParamAssignment) []obj.WasmField
peekPos
method
#
peekPos peeks the top of the line number stack.
func (s *state) peekPos() src.XPos
popLine
method
#
popLine pops the top of the line number stack.
func (s *state) popLine()
pushLine
method
#
pushLine pushes a line number on the line number stack.
func (s *state) pushLine(line src.XPos)
putArg
method
#
putArg evaluates n for the purpose of passing it as an argument to a function and returns the value for the call.
func (s *state) putArg(n ir.Node, t *types.Type) *ssa.Value
rawLoad
method
#
func (s *state) rawLoad(t *types.Type, src *ssa.Value) *ssa.Value
readFuncLines
function
#
func readFuncLines(file string, start uint, end uint) (*ssa.FuncLines, error)
recordCall
method
#
recordCall records a call from ODCLFUNC node "from", to function
symbol "to" at position pos.
This should be done as late as possible during compilation to
capture precise call graphs. The target of the call is an LSym
because that's all we know after we start SSA.
This can be called concurrently for different from Nodes.
func (c *nowritebarrierrecChecker) recordCall(fn *ir.Func, to *obj.LSym, pos src.XPos)
referenceTypeBuiltin
method
#
referenceTypeBuiltin generates code for the len/cap builtins for maps and channels.
func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value
reflectType
method
#
reflectType returns an SSA value representing a pointer to typ's
reflection type descriptor.
func (s *state) reflectType(typ *types.Type) *ssa.Value
resolveFwdRefs
method
#
resolveFwdRefs links all FwdRef uses up to their nearest dominating definition.
func (s *phiState) resolveFwdRefs()
resultAddrOfCall
method
#
func (s *state) resultAddrOfCall(c *ssa.Value, which int64, t *types.Type) *ssa.Value
resultOfCall
method
#
func (s *state) resultOfCall(c *ssa.Value, which int64, t *types.Type) *ssa.Value
resultsToWasmFields
function
#
func resultsToWasmFields(f *ir.Func, pragma string, result *abi.ABIParamResultInfo, abiParams []abi.ABIParamAssignment) []obj.WasmField
rtcall
method
#
rtcall issues a call to the given runtime function fn with the listed args.
Returns a slice of results of the given result types.
The call is added to the end of the current block.
If returns is false, the block is marked as an exit block.
func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value
setHeapaddr
method
#
setHeapaddr allocates a new PAUTO variable to store ptr (which must be non-nil)
and then sets it as n's heap address.
func (s *state) setHeapaddr(pos src.XPos, n *ir.Name, ptr *ssa.Value)
setupWasmExport
function
#
setupWasmExport calculates the params and results in terms of WebAssembly values for the given function,
and sets up the wasmexport metadata.
func setupWasmExport(f *ir.Func, wrapped *ir.Func)
setupWasmImport
function
#
setupWasmImport calculates the params and results in terms of WebAssembly values for the given function,
and sets up the wasmimport metadata.
func setupWasmImport(f *ir.Func)
sfcall
method
#
TODO: do not emit sfcall if operation can be optimized to constant in later
opt phase
func (s *state) sfcall(op ssa.Op, args ...*ssa.Value) (*ssa.Value, bool)
slice
method
#
slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
i,j,k may be nil, in which case they are set to their default value.
v may be a slice, string or pointer to an array.
func (s *state) slice(v *ssa.Value, i *ssa.Value, j *ssa.Value, k *ssa.Value, bounded bool) (p *ssa.Value, l *ssa.Value, c *ssa.Value)
softfloatInit
function
#
func softfloatInit()
split
method
#
split breaks up a tuple-typed value into its 2 parts.
func (s *state) split(v *ssa.Value) (*ssa.Value, *ssa.Value)
ssaMarker
function
#
func ssaMarker(name string) *ir.Name
ssaOp
method
#
func (s *state) ssaOp(op ir.Op, t *types.Type) ssa.Op
ssaShiftOp
method
#
func (s *state) ssaShiftOp(op ir.Op, t *types.Type, u *types.Type) ssa.Op
startBlock
method
#
startBlock sets the current block we're generating code in to b.
func (s *state) startBlock(b *ssa.Block)
stmt
method
#
stmt converts the statement n to SSA and adds it to s.
func (s *state) stmt(n ir.Node)
stmtList
method
#
stmtList converts the statement list n to SSA and adds it to s.
func (s *state) stmtList(l ir.Nodes)
store
method
#
func (s *state) store(t *types.Type, dst *ssa.Value, val *ssa.Value)
storeArgWithBase
method
#
func (s *state) storeArgWithBase(n ir.Node, t *types.Type, base *ssa.Value, off int64)
storeParameterRegsToStack
method
#
func (s *state) storeParameterRegsToStack(abi *abi.ABIConfig, paramAssignment *abi.ABIParamAssignment, n *ir.Name, addr *ssa.Value, pointersOnly bool)
storeType
method
#
do *left = right for type t.
func (s *state) storeType(t *types.Type, left *ssa.Value, right *ssa.Value, skip skipMask, leftIsStmt bool)
storeTypePtrs
method
#
do *left = right for all pointer parts of t.
func (s *state) storeTypePtrs(t *types.Type, left *ssa.Value, right *ssa.Value)
storeTypeScalars
method
#
do *left = right for all scalar (non-pointer) parts of t.
func (s *state) storeTypeScalars(t *types.Type, left *ssa.Value, right *ssa.Value, skip skipMask)
temp
method
#
temp allocates a temp of type t at position pos
func (s *state) temp(pos src.XPos, t *types.Type) (*ir.Name, *ssa.Value)
ternary
method
#
ternary emits code to evaluate cond ? x : y.
func (s *state) ternary(cond *ssa.Value, x *ssa.Value, y *ssa.Value) *ssa.Value
uint32Tofloat
method
#
func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uint32Tofloat32
method
#
func (s *state) uint32Tofloat32(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uint32Tofloat64
method
#
func (s *state) uint32Tofloat64(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uint64Tofloat
method
#
func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uint64Tofloat32
method
#
func (s *state) uint64Tofloat32(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uint64Tofloat64
method
#
func (s *state) uint64Tofloat64(n ir.Node, x *ssa.Value, ft *types.Type, tt *types.Type) *ssa.Value
uintptrConstant
method
#
func (s *state) uintptrConstant(v uint64) *ssa.Value
updateUnsetPredPos
method
#
updateUnsetPredPos propagates the earliest-value position information for b
towards all of b's predecessors that need a position, and recurs on that
predecessor if its position is updated. B should have a non-empty position.
func (s *state) updateUnsetPredPos(b *ssa.Block)
variable
method
#
variable returns the value of a variable at the current location.
func (s *state) variable(n ir.Node, t *types.Type) *ssa.Value
wasmElemTypeAllowed
function
#
wasmElemTypeAllowed reports whether t is allowed to be passed in memory
(as a pointer's element type, a field of it, etc.) between the Go wasm
module and the host.
func wasmElemTypeAllowed(t *types.Type) bool
weakenGlobalMapInitRelocs
function
#
weakenGlobalMapInitRelocs walks through all of the relocations on a
given a package init function "fn" and looks for relocs that target
outlined global map initializer functions; if it finds any such
relocs, it flags them as R_WEAK.
func weakenGlobalMapInitRelocs(fn *ir.Func)
zero
method
#
func (s *state) zero(t *types.Type, dst *ssa.Value)
zeroResults
method
#
zeroResults zeros the return values at the start of the function.
We need to do this very early in the function. Defer might stop a
panic and show the return values as they exist at the time of
panic. For precise stacks, the garbage collector assumes results
are always live, so we need to zero them before any allocations,
even allocations to move params/results to the heap.
func (s *state) zeroResults()
zeroVal
method
#
zeroVal returns the zero value for type t.
func (s *state) zeroVal(t *types.Type) *ssa.Value