github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/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 // v and v.Args[0] must be allocated to the same register 30 } 31 32 type inputInfo struct { 33 idx int // index in Args array 34 regs regMask // allowed input registers 35 } 36 37 type regInfo struct { 38 inputs []inputInfo // ordered in register allocation order 39 clobbers regMask 40 outputs []regMask // NOTE: values can only have 1 output for now. 41 } 42 43 type auxType int8 44 45 const ( 46 auxNone auxType = iota 47 auxBool // auxInt is 0/1 for false/true 48 auxInt8 // auxInt is an 8-bit integer 49 auxInt16 // auxInt is a 16-bit integer 50 auxInt32 // auxInt is a 32-bit integer 51 auxInt64 // auxInt is a 64-bit integer 52 auxInt128 // auxInt represents a 128-bit integer. Always 0. 53 auxFloat32 // auxInt is a float32 (encoded with math.Float64bits) 54 auxFloat64 // auxInt is a float64 (encoded with math.Float64bits) 55 auxString // aux is a string 56 auxSym // aux is a symbol 57 auxSymOff // aux is a symbol, auxInt is an offset 58 auxSymValAndOff // aux is a symbol, auxInt is a ValAndOff 59 60 auxSymInt32 // aux is a symbol, auxInt is a 32-bit integer 61 ) 62 63 // A ValAndOff is used by the several opcodes. It holds 64 // both a value and a pointer offset. 65 // A ValAndOff is intended to be encoded into an AuxInt field. 66 // The zero ValAndOff encodes a value of 0 and an offset of 0. 67 // The high 32 bits hold a value. 68 // The low 32 bits hold a pointer offset. 69 type ValAndOff int64 70 71 func (x ValAndOff) Val() int64 { 72 return int64(x) >> 32 73 } 74 func (x ValAndOff) Off() int64 { 75 return int64(int32(x)) 76 } 77 func (x ValAndOff) Int64() int64 { 78 return int64(x) 79 } 80 func (x ValAndOff) String() string { 81 return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off()) 82 } 83 84 // validVal reports whether the value can be used 85 // as an argument to makeValAndOff. 86 func validVal(val int64) bool { 87 return val == int64(int32(val)) 88 } 89 90 // validOff reports whether the offset can be used 91 // as an argument to makeValAndOff. 92 func validOff(off int64) bool { 93 return off == int64(int32(off)) 94 } 95 96 // validValAndOff reports whether we can fit the value and offset into 97 // a ValAndOff value. 98 func validValAndOff(val, off int64) bool { 99 if !validVal(val) { 100 return false 101 } 102 if !validOff(off) { 103 return false 104 } 105 return true 106 } 107 108 // makeValAndOff encodes a ValAndOff into an int64 suitable for storing in an AuxInt field. 109 func makeValAndOff(val, off int64) int64 { 110 if !validValAndOff(val, off) { 111 panic("invalid makeValAndOff") 112 } 113 return ValAndOff(val<<32 + int64(uint32(off))).Int64() 114 } 115 116 func (x ValAndOff) canAdd(off int64) bool { 117 newoff := x.Off() + off 118 return newoff == int64(int32(newoff)) 119 } 120 121 func (x ValAndOff) add(off int64) int64 { 122 if !x.canAdd(off) { 123 panic("invalid ValAndOff.add") 124 } 125 return makeValAndOff(x.Val(), x.Off()+off) 126 }