github.com/freddyisaac/sicortex-golang@v0.0.0-20231019035217-e03519e66f60/src/cmd/compile/internal/ssa/op.go (about)

     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 ssa
     6  
     7  import (
     8  	"cmd/internal/obj"
     9  	"fmt"
    10  )
    11  
    12  // An Op encodes the specific operation that a Value performs.
    13  // Opcodes' semantics can be modified by the type and aux fields of the Value.
    14  // For instance, OpAdd can be 32 or 64 bit, signed or unsigned, float or complex, depending on Value.Type.
    15  // Semantics of each op are described in the opcode files in gen/*Ops.go.
    16  // There is one file for generic (architecture-independent) ops and one file
    17  // for each architecture.
    18  type Op int32
    19  
    20  type opInfo struct {
    21  	name              string
    22  	reg               regInfo
    23  	auxType           auxType
    24  	argLen            int32 // the number of arguments, -1 if variable length
    25  	asm               obj.As
    26  	generic           bool // this is a generic (arch-independent) opcode
    27  	rematerializeable bool // this op is rematerializeable
    28  	commutative       bool // this operation is commutative (e.g. addition)
    29  	resultInArg0      bool // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
    30  	resultNotInArgs   bool // outputs must not be allocated to the same registers as inputs
    31  	clobberFlags      bool // this op clobbers flags register
    32  	call              bool // is a function call
    33  	nilCheck          bool // this op is a nil check on arg0
    34  	faultOnNilArg0    bool // this op will fault if arg0 is nil (and aux encodes a small offset)
    35  	faultOnNilArg1    bool // this op will fault if arg1 is nil (and aux encodes a small offset)
    36  	usesScratch       bool // this op requires scratch memory space
    37  	hasSideEffects    bool // for "reasons", not to be eliminated.  E.g., atomic store, #19182.
    38  }
    39  
    40  type inputInfo struct {
    41  	idx  int     // index in Args array
    42  	regs regMask // allowed input registers
    43  }
    44  
    45  type outputInfo struct {
    46  	idx  int     // index in output tuple
    47  	regs regMask // allowed output registers
    48  }
    49  
    50  type regInfo struct {
    51  	inputs   []inputInfo // ordered in register allocation order
    52  	clobbers regMask
    53  	outputs  []outputInfo // ordered in register allocation order
    54  }
    55  
    56  type auxType int8
    57  
    58  const (
    59  	auxNone            auxType = iota
    60  	auxBool                    // auxInt is 0/1 for false/true
    61  	auxInt8                    // auxInt is an 8-bit integer
    62  	auxInt16                   // auxInt is a 16-bit integer
    63  	auxInt32                   // auxInt is a 32-bit integer
    64  	auxInt64                   // auxInt is a 64-bit integer
    65  	auxInt128                  // auxInt represents a 128-bit integer.  Always 0.
    66  	auxFloat32                 // auxInt is a float32 (encoded with math.Float64bits)
    67  	auxFloat64                 // auxInt is a float64 (encoded with math.Float64bits)
    68  	auxSizeAndAlign            // auxInt is a SizeAndAlign
    69  	auxString                  // aux is a string
    70  	auxSym                     // aux is a symbol
    71  	auxSymOff                  // aux is a symbol, auxInt is an offset
    72  	auxSymValAndOff            // aux is a symbol, auxInt is a ValAndOff
    73  	auxSymSizeAndAlign         // aux is a symbol, auxInt is a SizeAndAlign
    74  
    75  	auxSymInt32 // aux is a symbol, auxInt is a 32-bit integer
    76  )
    77  
    78  // A ValAndOff is used by the several opcodes. It holds
    79  // both a value and a pointer offset.
    80  // A ValAndOff is intended to be encoded into an AuxInt field.
    81  // The zero ValAndOff encodes a value of 0 and an offset of 0.
    82  // The high 32 bits hold a value.
    83  // The low 32 bits hold a pointer offset.
    84  type ValAndOff int64
    85  
    86  func (x ValAndOff) Val() int64 {
    87  	return int64(x) >> 32
    88  }
    89  func (x ValAndOff) Off() int64 {
    90  	return int64(int32(x))
    91  }
    92  func (x ValAndOff) Int64() int64 {
    93  	return int64(x)
    94  }
    95  func (x ValAndOff) String() string {
    96  	return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
    97  }
    98  
    99  // validVal reports whether the value can be used
   100  // as an argument to makeValAndOff.
   101  func validVal(val int64) bool {
   102  	return val == int64(int32(val))
   103  }
   104  
   105  // validOff reports whether the offset can be used
   106  // as an argument to makeValAndOff.
   107  func validOff(off int64) bool {
   108  	return off == int64(int32(off))
   109  }
   110  
   111  // validValAndOff reports whether we can fit the value and offset into
   112  // a ValAndOff value.
   113  func validValAndOff(val, off int64) bool {
   114  	if !validVal(val) {
   115  		return false
   116  	}
   117  	if !validOff(off) {
   118  		return false
   119  	}
   120  	return true
   121  }
   122  
   123  // makeValAndOff encodes a ValAndOff into an int64 suitable for storing in an AuxInt field.
   124  func makeValAndOff(val, off int64) int64 {
   125  	if !validValAndOff(val, off) {
   126  		panic("invalid makeValAndOff")
   127  	}
   128  	return ValAndOff(val<<32 + int64(uint32(off))).Int64()
   129  }
   130  
   131  func (x ValAndOff) canAdd(off int64) bool {
   132  	newoff := x.Off() + off
   133  	return newoff == int64(int32(newoff))
   134  }
   135  
   136  func (x ValAndOff) add(off int64) int64 {
   137  	if !x.canAdd(off) {
   138  		panic("invalid ValAndOff.add")
   139  	}
   140  	return makeValAndOff(x.Val(), x.Off()+off)
   141  }
   142  
   143  // SizeAndAlign holds both the size and the alignment of a type,
   144  // used in Zero and Move ops.
   145  // The high 8 bits hold the alignment.
   146  // The low 56 bits hold the size.
   147  type SizeAndAlign int64
   148  
   149  func (x SizeAndAlign) Size() int64 {
   150  	return int64(x) & (1<<56 - 1)
   151  }
   152  func (x SizeAndAlign) Align() int64 {
   153  	return int64(uint64(x) >> 56)
   154  }
   155  func (x SizeAndAlign) Int64() int64 {
   156  	return int64(x)
   157  }
   158  func (x SizeAndAlign) String() string {
   159  	return fmt.Sprintf("size=%d,align=%d", x.Size(), x.Align())
   160  }
   161  func MakeSizeAndAlign(size, align int64) SizeAndAlign {
   162  	if size&^(1<<56-1) != 0 {
   163  		panic("size too big in SizeAndAlign")
   164  	}
   165  	if align >= 1<<8 {
   166  		panic("alignment too big in SizeAndAlign")
   167  	}
   168  	return SizeAndAlign(size | align<<56)
   169  }