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  

View as plain text