// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssaop import ( "fmt" "strings" "cmd/internal/obj" ) type AuxType int8 const ( AuxTypeNone AuxType = iota AuxTypeBool // auxInt is 0/1 for false/true AuxTypeInt8 // auxInt is an 8-bit integer AuxTypeInt16 // auxInt is a 16-bit integer AuxTypeInt32 // auxInt is a 32-bit integer AuxTypeInt64 // auxInt is a 64-bit integer AuxTypeInt128 // auxInt represents a 128-bit integer. Always 0. AuxTypeUInt8 // auxInt is an 8-bit unsigned integer AuxTypeFloat32 // auxInt is a float32 (encoded with math.Float64bits) AuxTypeFloat64 // auxInt is a float64 (encoded with math.Float64bits) AuxTypeFlagConstant // auxInt is a flagConstant AuxTypeCCop // auxInt is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan) AuxTypeNameOffsetInt8 // aux is a &struct{Name ir.Name, Offset int64}; auxInt is index in parameter registers array AuxTypeString // aux is a string AuxTypeSym // aux is a symbol (a *ir.Name for locals, an *obj.LSym for globals, or nil for none) AuxTypeSymOff // aux is a symbol, auxInt is an offset AuxTypeSymValAndOff // aux is a symbol, auxInt is a ValAndOff AuxTypeTyp // aux is a type AuxTypeTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt AuxTypeCall // aux is a *ssa.AuxCall AuxTypeCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size AuxTypePanicBoundsC // constant for a bounds failure AuxTypePanicBoundsCC // two constants for a bounds failure // architecture specific aux types AuxTypeARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt AuxTypeARM64ConditionalParams // aux is a structure, which contains condition, NZCV flags and constant with indicator of using it AuxTypeS390XRotateParams // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount AuxTypeS390XCCMask // aux is a s390x 4-bit condition code mask AuxTypeS390XCCMaskInt8 // aux is a s390x 4-bit condition code mask, auxInt is an int8 immediate AuxTypeS390XCCMaskUint8 // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate ) // An Op encodes the specific operation that a Value performs. // Opcodes' semantics can be modified by the type and aux fields of the Value. // For instance, OpAdd can be 32 or 64 bit, signed or unsigned, float or complex, depending on Value.Type. // Semantics of each op are described in the opcode files in _gen/*Ops.go. // There is one file for generic (architecture-independent) ops and one file // for each architecture. type Op int32 type OpInfo struct { Name string Reg RegInfo AuxType AuxType ArgLen int32 // the number of arguments, -1 if variable length asm obj.As Generic bool // this is a generic (arch-independent) opcode Rematerializeable bool // this op is rematerializeable Commutative bool // this operation is commutative (e.g. addition) ResultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register ResultNotInArgs bool // outputs must not be allocated to the same registers as inputs ClobberFlags bool // this op clobbers flags register NeedIntTemp bool // need a temporary free integer register Call bool // is a function call tailCall bool // is a tail call NilCheck bool // this op is a nil check on arg0 FaultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset) FaultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset) usesScratch bool // this op requires scratch memory space HasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182. ZeroWidth bool // op never translates into any machine code. example: copy, which may sometimes translate to machine code, is not zero-width. unsafePoint bool // this op is an unsafe point, i.e. not safe for async preemption FixedReg bool // this op will be assigned a fixed register EarlyOk bool // executing this op in an earlier block is ok AddrSinkArg0 bool // the address in arg0 does not propagate to the result AddrSinkArg1 bool // the address in arg1 does not propagate to the result symEffect SymEffect // effect this op has on symbol in aux scale uint8 // amd64/386 indexed load scale ZeroUpperBits uint8 // the op writes a 64-bit GPR whose upper N bits are always zero (0, 32, 48 or 56); for a tuple op, this holds for every integer result } type OutputInfo struct { Idx int // index in output tuple Regs RegMask // allowed output registers } type RegInfo struct { // Inputs encodes the register restrictions for an instruction's Inputs. // Each entry specifies an allowed register set for a particular input. // They are listed in the order in which regalloc should pick a register // from the register set (most constrained first). // Inputs which do not need registers are not listed. Inputs []InputInfo // Clobbers encodes the set of registers that are overwritten by // the instruction (other than the output registers). Clobbers RegMask // Instruction clobbers the register containing input 0. ClobbersArg0 bool // Instruction clobbers the register containing input 1. ClobbersArg1 bool // Outputs is the same as inputs, but for the Outputs of the instruction. Outputs []OutputInfo } // A SymEffect describes the effect that an SSA Value has on the variable // identified by the symbol in its Aux field. type SymEffect int8 const ( SymRead SymEffect = 1 << iota SymWrite SymAddr SymRdWr = SymRead | SymWrite SymNone SymEffect = 0 ) type InputInfo struct { Idx int // index in Args array Regs RegMask // allowed input registers } func (r *RegInfo) String() string { s := "" s += "INS:\n" for _, i := range r.Inputs { mask := fmt.Sprintf("%64b", i.Regs) mask = strings.ReplaceAll(mask, "0", ".") s += fmt.Sprintf("%2d |%s|\n", i.Idx, mask) } s += "OUTS:\n" for _, i := range r.Outputs { mask := fmt.Sprintf("%64b", i.Regs) mask = strings.ReplaceAll(mask, "0", ".") s += fmt.Sprintf("%2d |%s|\n", i.Idx, mask) } s += "CLOBBERS:\n" mask := fmt.Sprintf("%64b", r.Clobbers) mask = strings.ReplaceAll(mask, "0", ".") s += fmt.Sprintf(" |%s|\n", mask) return s } func (op Op) IsLoweredGetClosurePtr() bool { switch op { case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr, Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpLOONG64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr, OpRISCV64LoweredGetClosurePtr, OpWasmLoweredGetClosurePtr: return true } return false }