github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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  }
    38  
    39  type inputInfo struct {
    40  	idx  int     // index in Args array
    41  	regs regMask // allowed input registers
    42  }
    43  
    44  type outputInfo struct {
    45  	idx  int     // index in output tuple
    46  	regs regMask // allowed output registers
    47  }
    48  
    49  type regInfo struct {
    50  	inputs   []inputInfo // ordered in register allocation order
    51  	clobbers regMask
    52  	outputs  []outputInfo // ordered in register allocation order
    53  }
    54  
    55  type auxType int8
    56  
    57  const (
    58  	auxNone            auxType = iota
    59  	auxBool                    // auxInt is 0/1 for false/true
    60  	auxInt8                    // auxInt is an 8-bit integer
    61  	auxInt16                   // auxInt is a 16-bit integer
    62  	auxInt32                   // auxInt is a 32-bit integer
    63  	auxInt64                   // auxInt is a 64-bit integer
    64  	auxInt128                  // auxInt represents a 128-bit integer.  Always 0.
    65  	auxFloat32                 // auxInt is a float32 (encoded with math.Float64bits)
    66  	auxFloat64                 // auxInt is a float64 (encoded with math.Float64bits)
    67  	auxSizeAndAlign            // auxInt is a SizeAndAlign
    68  	auxString                  // aux is a string
    69  	auxSym                     // aux is a symbol
    70  	auxSymOff                  // aux is a symbol, auxInt is an offset
    71  	auxSymValAndOff            // aux is a symbol, auxInt is a ValAndOff
    72  	auxSymSizeAndAlign         // aux is a symbol, auxInt is a SizeAndAlign
    73  
    74  	auxSymInt32 // aux is a symbol, auxInt is a 32-bit integer
    75  )
    76  
    77  // A ValAndOff is used by the several opcodes. It holds
    78  // both a value and a pointer offset.
    79  // A ValAndOff is intended to be encoded into an AuxInt field.
    80  // The zero ValAndOff encodes a value of 0 and an offset of 0.
    81  // The high 32 bits hold a value.
    82  // The low 32 bits hold a pointer offset.
    83  type ValAndOff int64
    84  
    85  func (x ValAndOff) Val() int64 {
    86  	return int64(x) >> 32
    87  }
    88  func (x ValAndOff) Off() int64 {
    89  	return int64(int32(x))
    90  }
    91  func (x ValAndOff) Int64() int64 {
    92  	return int64(x)
    93  }
    94  func (x ValAndOff) String() string {
    95  	return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
    96  }
    97  
    98  // validVal reports whether the value can be used
    99  // as an argument to makeValAndOff.
   100  func validVal(val int64) bool {
   101  	return val == int64(int32(val))
   102  }
   103  
   104  // validOff reports whether the offset can be used
   105  // as an argument to makeValAndOff.
   106  func validOff(off int64) bool {
   107  	return off == int64(int32(off))
   108  }
   109  
   110  // validValAndOff reports whether we can fit the value and offset into
   111  // a ValAndOff value.
   112  func validValAndOff(val, off int64) bool {
   113  	if !validVal(val) {
   114  		return false
   115  	}
   116  	if !validOff(off) {
   117  		return false
   118  	}
   119  	return true
   120  }
   121  
   122  // makeValAndOff encodes a ValAndOff into an int64 suitable for storing in an AuxInt field.
   123  func makeValAndOff(val, off int64) int64 {
   124  	if !validValAndOff(val, off) {
   125  		panic("invalid makeValAndOff")
   126  	}
   127  	return ValAndOff(val<<32 + int64(uint32(off))).Int64()
   128  }
   129  
   130  func (x ValAndOff) canAdd(off int64) bool {
   131  	newoff := x.Off() + off
   132  	return newoff == int64(int32(newoff))
   133  }
   134  
   135  func (x ValAndOff) add(off int64) int64 {
   136  	if !x.canAdd(off) {
   137  		panic("invalid ValAndOff.add")
   138  	}
   139  	return makeValAndOff(x.Val(), x.Off()+off)
   140  }
   141  
   142  // SizeAndAlign holds both the size and the alignment of a type,
   143  // used in Zero and Move ops.
   144  // The high 8 bits hold the alignment.
   145  // The low 56 bits hold the size.
   146  type SizeAndAlign int64
   147  
   148  func (x SizeAndAlign) Size() int64 {
   149  	return int64(x) & (1<<56 - 1)
   150  }
   151  func (x SizeAndAlign) Align() int64 {
   152  	return int64(uint64(x) >> 56)
   153  }
   154  func (x SizeAndAlign) Int64() int64 {
   155  	return int64(x)
   156  }
   157  func (x SizeAndAlign) String() string {
   158  	return fmt.Sprintf("size=%d,align=%d", x.Size(), x.Align())
   159  }
   160  func MakeSizeAndAlign(size, align int64) SizeAndAlign {
   161  	if size&^(1<<56-1) != 0 {
   162  		panic("size too big in SizeAndAlign")
   163  	}
   164  	if align >= 1<<8 {
   165  		panic("alignment too big in SizeAndAlign")
   166  	}
   167  	return SizeAndAlign(size | align<<56)
   168  }