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