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 }