github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/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  	symEffect         SymEffect // effect this op has on symbol in aux
    39  }
    40  
    41  type inputInfo struct {
    42  	idx  int     // index in Args array
    43  	regs regMask // allowed input registers
    44  }
    45  
    46  type outputInfo struct {
    47  	idx  int     // index in output tuple
    48  	regs regMask // allowed output registers
    49  }
    50  
    51  type regInfo struct {
    52  	inputs   []inputInfo // ordered in register allocation order
    53  	clobbers regMask
    54  	outputs  []outputInfo // ordered in register allocation order
    55  }
    56  
    57  type auxType int8
    58  
    59  const (
    60  	auxNone         auxType = iota
    61  	auxBool                 // auxInt is 0/1 for false/true
    62  	auxInt8                 // auxInt is an 8-bit integer
    63  	auxInt16                // auxInt is a 16-bit integer
    64  	auxInt32                // auxInt is a 32-bit integer
    65  	auxInt64                // auxInt is a 64-bit integer
    66  	auxInt128               // auxInt represents a 128-bit integer.  Always 0.
    67  	auxFloat32              // auxInt is a float32 (encoded with math.Float64bits)
    68  	auxFloat64              // auxInt is a float64 (encoded with math.Float64bits)
    69  	auxString               // aux is a string
    70  	auxSym                  // aux is a symbol (a *gc.Node for locals or an *obj.LSym for globals)
    71  	auxSymOff               // aux is a symbol, auxInt is an offset
    72  	auxSymValAndOff         // aux is a symbol, auxInt is a ValAndOff
    73  	auxTyp                  // aux is a type
    74  	auxTypSize              // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt
    75  	auxCCop                 // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan)
    76  
    77  	auxSymInt32 // aux is a symbol, auxInt is a 32-bit integer
    78  )
    79  
    80  // A SymEffect describes the effect that an SSA Value has on the variable
    81  // identified by the symbol in its Aux field.
    82  type SymEffect int8
    83  
    84  const (
    85  	SymRead SymEffect = 1 << iota
    86  	SymWrite
    87  	SymAddr
    88  
    89  	SymRdWr = SymRead | SymWrite
    90  
    91  	SymNone SymEffect = 0
    92  )
    93  
    94  // A ValAndOff is used by the several opcodes. It holds
    95  // both a value and a pointer offset.
    96  // A ValAndOff is intended to be encoded into an AuxInt field.
    97  // The zero ValAndOff encodes a value of 0 and an offset of 0.
    98  // The high 32 bits hold a value.
    99  // The low 32 bits hold a pointer offset.
   100  type ValAndOff int64
   101  
   102  func (x ValAndOff) Val() int64 {
   103  	return int64(x) >> 32
   104  }
   105  func (x ValAndOff) Off() int64 {
   106  	return int64(int32(x))
   107  }
   108  func (x ValAndOff) Int64() int64 {
   109  	return int64(x)
   110  }
   111  func (x ValAndOff) String() string {
   112  	return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
   113  }
   114  
   115  // validVal reports whether the value can be used
   116  // as an argument to makeValAndOff.
   117  func validVal(val int64) bool {
   118  	return val == int64(int32(val))
   119  }
   120  
   121  // validOff reports whether the offset can be used
   122  // as an argument to makeValAndOff.
   123  func validOff(off int64) bool {
   124  	return off == int64(int32(off))
   125  }
   126  
   127  // validValAndOff reports whether we can fit the value and offset into
   128  // a ValAndOff value.
   129  func validValAndOff(val, off int64) bool {
   130  	if !validVal(val) {
   131  		return false
   132  	}
   133  	if !validOff(off) {
   134  		return false
   135  	}
   136  	return true
   137  }
   138  
   139  // makeValAndOff encodes a ValAndOff into an int64 suitable for storing in an AuxInt field.
   140  func makeValAndOff(val, off int64) int64 {
   141  	if !validValAndOff(val, off) {
   142  		panic("invalid makeValAndOff")
   143  	}
   144  	return ValAndOff(val<<32 + int64(uint32(off))).Int64()
   145  }
   146  
   147  func (x ValAndOff) canAdd(off int64) bool {
   148  	newoff := x.Off() + off
   149  	return newoff == int64(int32(newoff))
   150  }
   151  
   152  func (x ValAndOff) add(off int64) int64 {
   153  	if !x.canAdd(off) {
   154  		panic("invalid ValAndOff.add")
   155  	}
   156  	return makeValAndOff(x.Val(), x.Off()+off)
   157  }