Source file src/cmd/compile/internal/ssa/ssaop/op.go
1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssaop 6 7 import ( 8 "fmt" 9 "strings" 10 11 "cmd/internal/obj" 12 ) 13 14 type AuxType int8 15 16 const ( 17 AuxTypeNone AuxType = iota 18 AuxTypeBool // auxInt is 0/1 for false/true 19 AuxTypeInt8 // auxInt is an 8-bit integer 20 AuxTypeInt16 // auxInt is a 16-bit integer 21 AuxTypeInt32 // auxInt is a 32-bit integer 22 AuxTypeInt64 // auxInt is a 64-bit integer 23 AuxTypeInt128 // auxInt represents a 128-bit integer. Always 0. 24 AuxTypeUInt8 // auxInt is an 8-bit unsigned integer 25 AuxTypeFloat32 // auxInt is a float32 (encoded with math.Float64bits) 26 AuxTypeFloat64 // auxInt is a float64 (encoded with math.Float64bits) 27 AuxTypeFlagConstant // auxInt is a flagConstant 28 AuxTypeCCop // auxInt is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan) 29 AuxTypeNameOffsetInt8 // aux is a &struct{Name ir.Name, Offset int64}; auxInt is index in parameter registers array 30 AuxTypeString // aux is a string 31 AuxTypeSym // aux is a symbol (a *ir.Name for locals, an *obj.LSym for globals, or nil for none) 32 AuxTypeSymOff // aux is a symbol, auxInt is an offset 33 AuxTypeSymValAndOff // aux is a symbol, auxInt is a ValAndOff 34 AuxTypeTyp // aux is a type 35 AuxTypeTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt 36 AuxTypeCall // aux is a *ssa.AuxCall 37 AuxTypeCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size 38 39 AuxTypePanicBoundsC // constant for a bounds failure 40 AuxTypePanicBoundsCC // two constants for a bounds failure 41 42 // architecture specific aux types 43 AuxTypeARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt 44 AuxTypeARM64ConditionalParams // aux is a structure, which contains condition, NZCV flags and constant with indicator of using it 45 AuxTypeS390XRotateParams // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount 46 AuxTypeS390XCCMask // aux is a s390x 4-bit condition code mask 47 AuxTypeS390XCCMaskInt8 // aux is a s390x 4-bit condition code mask, auxInt is an int8 immediate 48 AuxTypeS390XCCMaskUint8 // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate 49 ) 50 51 // An Op encodes the specific operation that a Value performs. 52 // Opcodes' semantics can be modified by the type and aux fields of the Value. 53 // For instance, OpAdd can be 32 or 64 bit, signed or unsigned, float or complex, depending on Value.Type. 54 // Semantics of each op are described in the opcode files in _gen/*Ops.go. 55 // There is one file for generic (architecture-independent) ops and one file 56 // for each architecture. 57 type Op int32 58 59 type OpInfo struct { 60 Name string 61 Reg RegInfo 62 AuxType AuxType 63 ArgLen int32 // the number of arguments, -1 if variable length 64 asm obj.As 65 Generic bool // this is a generic (arch-independent) opcode 66 Rematerializeable bool // this op is rematerializeable 67 Commutative bool // this operation is commutative (e.g. addition) 68 ResultInArg0 bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register 69 ResultNotInArgs bool // outputs must not be allocated to the same registers as inputs 70 ClobberFlags bool // this op clobbers flags register 71 NeedIntTemp bool // need a temporary free integer register 72 Call bool // is a function call 73 tailCall bool // is a tail call 74 NilCheck bool // this op is a nil check on arg0 75 FaultOnNilArg0 bool // this op will fault if arg0 is nil (and aux encodes a small offset) 76 FaultOnNilArg1 bool // this op will fault if arg1 is nil (and aux encodes a small offset) 77 usesScratch bool // this op requires scratch memory space 78 HasSideEffects bool // for "reasons", not to be eliminated. E.g., atomic store, #19182. 79 ZeroWidth bool // op never translates into any machine code. example: copy, which may sometimes translate to machine code, is not zero-width. 80 unsafePoint bool // this op is an unsafe point, i.e. not safe for async preemption 81 FixedReg bool // this op will be assigned a fixed register 82 EarlyOk bool // executing this op in an earlier block is ok 83 AddrSinkArg0 bool // the address in arg0 does not propagate to the result 84 AddrSinkArg1 bool // the address in arg1 does not propagate to the result 85 symEffect SymEffect // effect this op has on symbol in aux 86 scale uint8 // amd64/386 indexed load scale 87 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 88 } 89 90 type OutputInfo struct { 91 Idx int // index in output tuple 92 Regs RegMask // allowed output registers 93 } 94 95 type RegInfo struct { 96 // Inputs encodes the register restrictions for an instruction's Inputs. 97 // Each entry specifies an allowed register set for a particular input. 98 // They are listed in the order in which regalloc should pick a register 99 // from the register set (most constrained first). 100 // Inputs which do not need registers are not listed. 101 Inputs []InputInfo 102 // Clobbers encodes the set of registers that are overwritten by 103 // the instruction (other than the output registers). 104 Clobbers RegMask 105 // Instruction clobbers the register containing input 0. 106 ClobbersArg0 bool 107 // Instruction clobbers the register containing input 1. 108 ClobbersArg1 bool 109 // Outputs is the same as inputs, but for the Outputs of the instruction. 110 Outputs []OutputInfo 111 } 112 113 // A SymEffect describes the effect that an SSA Value has on the variable 114 // identified by the symbol in its Aux field. 115 type SymEffect int8 116 117 const ( 118 SymRead SymEffect = 1 << iota 119 SymWrite 120 SymAddr 121 122 SymRdWr = SymRead | SymWrite 123 124 SymNone SymEffect = 0 125 ) 126 127 type InputInfo struct { 128 Idx int // index in Args array 129 Regs RegMask // allowed input registers 130 } 131 132 func (r *RegInfo) String() string { 133 s := "" 134 s += "INS:\n" 135 for _, i := range r.Inputs { 136 mask := fmt.Sprintf("%64b", i.Regs) 137 mask = strings.ReplaceAll(mask, "0", ".") 138 s += fmt.Sprintf("%2d |%s|\n", i.Idx, mask) 139 } 140 s += "OUTS:\n" 141 for _, i := range r.Outputs { 142 mask := fmt.Sprintf("%64b", i.Regs) 143 mask = strings.ReplaceAll(mask, "0", ".") 144 s += fmt.Sprintf("%2d |%s|\n", i.Idx, mask) 145 } 146 s += "CLOBBERS:\n" 147 mask := fmt.Sprintf("%64b", r.Clobbers) 148 mask = strings.ReplaceAll(mask, "0", ".") 149 s += fmt.Sprintf(" |%s|\n", mask) 150 return s 151 } 152 153 func (op Op) IsLoweredGetClosurePtr() bool { 154 switch op { 155 case OpAMD64LoweredGetClosurePtr, OpPPC64LoweredGetClosurePtr, OpARMLoweredGetClosurePtr, OpARM64LoweredGetClosurePtr, 156 Op386LoweredGetClosurePtr, OpMIPS64LoweredGetClosurePtr, OpLOONG64LoweredGetClosurePtr, OpS390XLoweredGetClosurePtr, OpMIPSLoweredGetClosurePtr, 157 OpRISCV64LoweredGetClosurePtr, OpWasmLoweredGetClosurePtr: 158 return true 159 } 160 return false 161 } 162