Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 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 | |
Todd Neal | 19447a6 | 2015-09-04 06:33:56 -0500 | [diff] [blame] | 7 | import ( |
Josh Bleecher Snyder | 46b88c9 | 2017-04-28 14:12:28 -0700 | [diff] [blame] | 8 | "cmd/compile/internal/types" |
Robert Griesemer | 24597c0 | 2016-12-06 17:08:06 -0800 | [diff] [blame] | 9 | "cmd/internal/src" |
Todd Neal | 19447a6 | 2015-09-04 06:33:56 -0500 | [diff] [blame] | 10 | "fmt" |
| 11 | "math" |
David Chase | bd41c67 | 2017-11-20 16:47:08 -0500 | [diff] [blame] | 12 | "sort" |
Heschi Kreinick | 4c54a04 | 2017-07-21 18:30:19 -0400 | [diff] [blame] | 13 | "strings" |
Todd Neal | 19447a6 | 2015-09-04 06:33:56 -0500 | [diff] [blame] | 14 | ) |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 15 | |
| 16 | // A Value represents a value in the SSA representation of the program. |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 17 | // The ID and Type fields must not be modified. The remainder may be modified |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 18 | // if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)). |
| 19 | type Value struct { |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 20 | // A unique identifier for the value. For performance we allocate these IDs |
Keith Randall | 0b46b42 | 2015-08-11 12:51:33 -0700 | [diff] [blame] | 21 | // densely starting at 1. There is no guarantee that there won't be occasional holes, though. |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 22 | ID ID |
| 23 | |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 24 | // The operation that computes this value. See op.go. |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 25 | Op Op |
| 26 | |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 27 | // The type of this value. Normally this will be a Go type, but there |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 28 | // are a few other pseudo-types, see type.go. |
Josh Bleecher Snyder | 46b88c9 | 2017-04-28 14:12:28 -0700 | [diff] [blame] | 29 | Type *types.Type |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 30 | |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 31 | // Auxiliary info for this value. The type of this information depends on the opcode and type. |
Keith Randall | 8f22b52 | 2015-06-11 21:29:25 -0700 | [diff] [blame] | 32 | // AuxInt is used for integer values, Aux is used for other values. |
Kevin Burke | 8e24a98 | 2016-08-20 22:05:47 -0700 | [diff] [blame] | 33 | // Floats are stored in AuxInt using math.Float64bits(f). |
Keith Randall | 8f22b52 | 2015-06-11 21:29:25 -0700 | [diff] [blame] | 34 | AuxInt int64 |
| 35 | Aux interface{} |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 36 | |
| 37 | // Arguments of this value |
| 38 | Args []*Value |
| 39 | |
| 40 | // Containing basic block |
| 41 | Block *Block |
| 42 | |
Robert Griesemer | cfd17f5 | 2016-12-07 18:14:35 -0800 | [diff] [blame] | 43 | // Source position |
Robert Griesemer | 472c792 | 2016-12-15 17:17:01 -0800 | [diff] [blame] | 44 | Pos src.XPos |
Michael Matloob | 81ccf50 | 2015-05-30 01:03:06 -0400 | [diff] [blame] | 45 | |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 46 | // Use count. Each appearance in Value.Args and Block.Control counts once. |
| 47 | Uses int32 |
| 48 | |
Josh Bleecher Snyder | f3a29f1 | 2016-03-06 21:22:11 -0800 | [diff] [blame] | 49 | // Storage for the first three args |
| 50 | argstorage [3]*Value |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | // Examples: |
| 54 | // Opcode aux args |
| 55 | // OpAdd nil 2 |
Keith Randall | 2c9b491 | 2015-03-26 10:49:03 -0700 | [diff] [blame] | 56 | // OpConst string 0 string constant |
| 57 | // OpConst int64 0 int64 constant |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 58 | // OpAddcq int64 1 amd64 op: v = arg[0] + constant |
| 59 | |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 60 | // short form print. Just v#. |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 61 | func (v *Value) String() string { |
Josh Bleecher Snyder | 220e705 | 2015-08-22 13:30:45 -0700 | [diff] [blame] | 62 | if v == nil { |
| 63 | return "nil" // should never happen, but not panicking helps with debugging |
| 64 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 65 | return fmt.Sprintf("v%d", v.ID) |
| 66 | } |
| 67 | |
Keith Randall | 16b1fce | 2016-01-31 11:39:39 -0800 | [diff] [blame] | 68 | func (v *Value) AuxInt8() int8 { |
| 69 | if opcodeTable[v.Op].auxType != auxInt8 { |
| 70 | v.Fatalf("op %s doesn't have an int8 aux field", v.Op) |
| 71 | } |
| 72 | return int8(v.AuxInt) |
| 73 | } |
| 74 | |
| 75 | func (v *Value) AuxInt16() int16 { |
| 76 | if opcodeTable[v.Op].auxType != auxInt16 { |
| 77 | v.Fatalf("op %s doesn't have an int16 aux field", v.Op) |
| 78 | } |
| 79 | return int16(v.AuxInt) |
| 80 | } |
| 81 | |
| 82 | func (v *Value) AuxInt32() int32 { |
| 83 | if opcodeTable[v.Op].auxType != auxInt32 { |
| 84 | v.Fatalf("op %s doesn't have an int32 aux field", v.Op) |
| 85 | } |
| 86 | return int32(v.AuxInt) |
| 87 | } |
Todd Neal | c17b6b4 | 2016-02-19 16:58:21 -0600 | [diff] [blame] | 88 | |
Keith Randall | 16b1fce | 2016-01-31 11:39:39 -0800 | [diff] [blame] | 89 | func (v *Value) AuxFloat() float64 { |
Todd Neal | f6ceed2 | 2016-03-11 19:36:54 -0600 | [diff] [blame] | 90 | if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 { |
Keith Randall | 16b1fce | 2016-01-31 11:39:39 -0800 | [diff] [blame] | 91 | v.Fatalf("op %s doesn't have a float aux field", v.Op) |
| 92 | } |
| 93 | return math.Float64frombits(uint64(v.AuxInt)) |
| 94 | } |
| 95 | func (v *Value) AuxValAndOff() ValAndOff { |
| 96 | if opcodeTable[v.Op].auxType != auxSymValAndOff { |
| 97 | v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op) |
| 98 | } |
| 99 | return ValAndOff(v.AuxInt) |
| 100 | } |
| 101 | |
Heschi Kreinick | 4c54a04 | 2017-07-21 18:30:19 -0400 | [diff] [blame] | 102 | // long form print. v# = opcode <type> [aux] args [: reg] (names) |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 103 | func (v *Value) LongString() string { |
Keith Randall | 2e2db7a | 2016-09-16 16:56:29 -0700 | [diff] [blame] | 104 | s := fmt.Sprintf("v%d = %s", v.ID, v.Op) |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 105 | s += " <" + v.Type.String() + ">" |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 106 | s += v.auxString() |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 107 | for _, a := range v.Args { |
| 108 | s += fmt.Sprintf(" %v", a) |
| 109 | } |
| 110 | r := v.Block.Func.RegAlloc |
Keith Randall | 0b46b42 | 2015-08-11 12:51:33 -0700 | [diff] [blame] | 111 | if int(v.ID) < len(r) && r[v.ID] != nil { |
Keith Randall | bf4d8d3 | 2017-08-17 12:23:34 -0700 | [diff] [blame] | 112 | s += " : " + r[v.ID].String() |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 113 | } |
Heschi Kreinick | 4c54a04 | 2017-07-21 18:30:19 -0400 | [diff] [blame] | 114 | var names []string |
| 115 | for name, values := range v.Block.Func.NamedValues { |
| 116 | for _, value := range values { |
| 117 | if value == v { |
Keith Randall | bf4d8d3 | 2017-08-17 12:23:34 -0700 | [diff] [blame] | 118 | names = append(names, name.String()) |
Heschi Kreinick | 4c54a04 | 2017-07-21 18:30:19 -0400 | [diff] [blame] | 119 | break // drop duplicates. |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | if len(names) != 0 { |
David Chase | bd41c67 | 2017-11-20 16:47:08 -0500 | [diff] [blame] | 124 | sort.Strings(names) // Otherwise a source of variation in debugging output. |
Heschi Kreinick | 4c54a04 | 2017-07-21 18:30:19 -0400 | [diff] [blame] | 125 | s += " (" + strings.Join(names, ", ") + ")" |
| 126 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 127 | return s |
| 128 | } |
| 129 | |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 130 | func (v *Value) auxString() string { |
| 131 | switch opcodeTable[v.Op].auxType { |
| 132 | case auxBool: |
| 133 | if v.AuxInt == 0 { |
| 134 | return " [false]" |
| 135 | } else { |
| 136 | return " [true]" |
| 137 | } |
| 138 | case auxInt8: |
| 139 | return fmt.Sprintf(" [%d]", v.AuxInt8()) |
| 140 | case auxInt16: |
| 141 | return fmt.Sprintf(" [%d]", v.AuxInt16()) |
| 142 | case auxInt32: |
| 143 | return fmt.Sprintf(" [%d]", v.AuxInt32()) |
| 144 | case auxInt64, auxInt128: |
| 145 | return fmt.Sprintf(" [%d]", v.AuxInt) |
| 146 | case auxFloat32, auxFloat64: |
| 147 | return fmt.Sprintf(" [%g]", v.AuxFloat()) |
| 148 | case auxString: |
| 149 | return fmt.Sprintf(" {%q}", v.Aux) |
Cherry Zhang | c8f38b3 | 2017-03-13 21:51:08 -0400 | [diff] [blame] | 150 | case auxSym, auxTyp: |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 151 | if v.Aux != nil { |
Keith Randall | 2e2db7a | 2016-09-16 16:56:29 -0700 | [diff] [blame] | 152 | return fmt.Sprintf(" {%v}", v.Aux) |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 153 | } |
Cherry Zhang | c8f38b3 | 2017-03-13 21:51:08 -0400 | [diff] [blame] | 154 | case auxSymOff, auxSymInt32, auxTypSize: |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 155 | s := "" |
| 156 | if v.Aux != nil { |
Keith Randall | 2e2db7a | 2016-09-16 16:56:29 -0700 | [diff] [blame] | 157 | s = fmt.Sprintf(" {%v}", v.Aux) |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 158 | } |
| 159 | if v.AuxInt != 0 { |
| 160 | s += fmt.Sprintf(" [%v]", v.AuxInt) |
| 161 | } |
| 162 | return s |
| 163 | case auxSymValAndOff: |
| 164 | s := "" |
| 165 | if v.Aux != nil { |
Keith Randall | 2e2db7a | 2016-09-16 16:56:29 -0700 | [diff] [blame] | 166 | s = fmt.Sprintf(" {%v}", v.Aux) |
Frits van Bommel | b13b249 | 2016-04-30 11:13:29 +0200 | [diff] [blame] | 167 | } |
| 168 | return s + fmt.Sprintf(" [%s]", v.AuxValAndOff()) |
| 169 | } |
| 170 | return "" |
| 171 | } |
| 172 | |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 173 | func (v *Value) AddArg(w *Value) { |
Josh Bleecher Snyder | 7c2c0b4 | 2015-03-16 16:31:13 -0700 | [diff] [blame] | 174 | if v.Args == nil { |
| 175 | v.resetArgs() // use argstorage |
| 176 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 177 | v.Args = append(v.Args, w) |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 178 | w.Uses++ |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 179 | } |
| 180 | func (v *Value) AddArgs(a ...*Value) { |
Josh Bleecher Snyder | 7c2c0b4 | 2015-03-16 16:31:13 -0700 | [diff] [blame] | 181 | if v.Args == nil { |
| 182 | v.resetArgs() // use argstorage |
| 183 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 184 | v.Args = append(v.Args, a...) |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 185 | for _, x := range a { |
| 186 | x.Uses++ |
| 187 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 188 | } |
| 189 | func (v *Value) SetArg(i int, w *Value) { |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 190 | v.Args[i].Uses-- |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 191 | v.Args[i] = w |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 192 | w.Uses++ |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 193 | } |
| 194 | func (v *Value) RemoveArg(i int) { |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 195 | v.Args[i].Uses-- |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 196 | copy(v.Args[i:], v.Args[i+1:]) |
Josh Bleecher Snyder | 7c2c0b4 | 2015-03-16 16:31:13 -0700 | [diff] [blame] | 197 | v.Args[len(v.Args)-1] = nil // aid GC |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 198 | v.Args = v.Args[:len(v.Args)-1] |
| 199 | } |
| 200 | func (v *Value) SetArgs1(a *Value) { |
| 201 | v.resetArgs() |
| 202 | v.AddArg(a) |
| 203 | } |
| 204 | func (v *Value) SetArgs2(a *Value, b *Value) { |
| 205 | v.resetArgs() |
| 206 | v.AddArg(a) |
| 207 | v.AddArg(b) |
| 208 | } |
| 209 | |
| 210 | func (v *Value) resetArgs() { |
Keith Randall | 56e0ecc | 2016-03-15 20:45:50 -0700 | [diff] [blame] | 211 | for _, a := range v.Args { |
| 212 | a.Uses-- |
| 213 | } |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 214 | v.argstorage[0] = nil |
| 215 | v.argstorage[1] = nil |
Keith Randall | 7e40627 | 2016-04-11 13:17:52 -0700 | [diff] [blame] | 216 | v.argstorage[2] = nil |
Keith Randall | f52b234 | 2015-03-03 13:38:14 -0800 | [diff] [blame] | 217 | v.Args = v.argstorage[:0] |
| 218 | } |
Josh Bleecher Snyder | 8c6abfe | 2015-06-12 11:01:13 -0700 | [diff] [blame] | 219 | |
Alexandru Moșoi | 2df4b9c | 2016-02-04 17:21:57 +0100 | [diff] [blame] | 220 | func (v *Value) reset(op Op) { |
| 221 | v.Op = op |
| 222 | v.resetArgs() |
| 223 | v.AuxInt = 0 |
| 224 | v.Aux = nil |
| 225 | } |
| 226 | |
Keith Randall | c140df0 | 2015-12-09 15:58:18 -0800 | [diff] [blame] | 227 | // copyInto makes a new value identical to v and adds it to the end of b. |
| 228 | func (v *Value) copyInto(b *Block) *Value { |
David Chase | 00263a8 | 2017-02-02 14:51:15 -0500 | [diff] [blame] | 229 | c := b.NewValue0(v.Pos, v.Op, v.Type) // Lose the position, this causes line number churn otherwise. |
| 230 | c.Aux = v.Aux |
| 231 | c.AuxInt = v.AuxInt |
| 232 | c.AddArgs(v.Args...) |
| 233 | for _, a := range v.Args { |
| 234 | if a.Type.IsMemory() { |
| 235 | v.Fatalf("can't move a value with a memory arg %s", v.LongString()) |
| 236 | } |
| 237 | } |
| 238 | return c |
| 239 | } |
| 240 | |
David Chase | 643be70 | 2017-05-10 13:50:19 -0400 | [diff] [blame] | 241 | // copyIntoNoXPos makes a new value identical to v and adds it to the end of b. |
| 242 | // The copied value receives no source code position to avoid confusing changes |
| 243 | // in debugger information (the intended user is the register allocator). |
David Chase | 00263a8 | 2017-02-02 14:51:15 -0500 | [diff] [blame] | 244 | func (v *Value) copyIntoNoXPos(b *Block) *Value { |
David Chase | ca360c3 | 2017-07-21 12:00:38 -0400 | [diff] [blame] | 245 | return v.copyIntoWithXPos(b, src.NoXPos) |
| 246 | } |
| 247 | |
| 248 | // copyIntoWithXPos makes a new value identical to v and adds it to the end of b. |
| 249 | // The supplied position is used as the position of the new value. |
| 250 | func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value { |
| 251 | c := b.NewValue0(pos, v.Op, v.Type) |
Keith Randall | c140df0 | 2015-12-09 15:58:18 -0800 | [diff] [blame] | 252 | c.Aux = v.Aux |
| 253 | c.AuxInt = v.AuxInt |
| 254 | c.AddArgs(v.Args...) |
Keith Randall | f94e074 | 2016-01-26 15:47:08 -0800 | [diff] [blame] | 255 | for _, a := range v.Args { |
| 256 | if a.Type.IsMemory() { |
| 257 | v.Fatalf("can't move a value with a memory arg %s", v.LongString()) |
| 258 | } |
| 259 | } |
Keith Randall | c140df0 | 2015-12-09 15:58:18 -0800 | [diff] [blame] | 260 | return c |
| 261 | } |
| 262 | |
Keith Randall | da8af47 | 2016-01-13 11:14:57 -0800 | [diff] [blame] | 263 | func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) } |
David Chase | 88b230e | 2016-01-29 14:44:15 -0500 | [diff] [blame] | 264 | func (v *Value) Log() bool { return v.Block.Log() } |
Keith Randall | da8af47 | 2016-01-13 11:14:57 -0800 | [diff] [blame] | 265 | func (v *Value) Fatalf(msg string, args ...interface{}) { |
Josh Bleecher Snyder | 2cdb7f1 | 2017-03-16 22:42:10 -0700 | [diff] [blame] | 266 | v.Block.Func.fe.Fatalf(v.Pos, msg, args...) |
Keith Randall | da8af47 | 2016-01-13 11:14:57 -0800 | [diff] [blame] | 267 | } |
Keith Randall | 8c46aa5 | 2015-06-19 21:02:28 -0700 | [diff] [blame] | 268 | |
Keith Randall | 47c9e13 | 2016-03-23 10:20:44 -0700 | [diff] [blame] | 269 | // isGenericIntConst returns whether v is a generic integer constant. |
| 270 | func (v *Value) isGenericIntConst() bool { |
| 271 | return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8) |
| 272 | } |
| 273 | |
Keith Randall | 833ed7c | 2016-09-16 09:36:00 -0700 | [diff] [blame] | 274 | // Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering. |
| 275 | func (v *Value) Reg() int16 { |
| 276 | reg := v.Block.Func.RegAlloc[v.ID] |
| 277 | if reg == nil { |
| 278 | v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func) |
| 279 | } |
| 280 | return reg.(*Register).objNum |
| 281 | } |
| 282 | |
| 283 | // Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering. |
| 284 | func (v *Value) Reg0() int16 { |
| 285 | reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0] |
| 286 | if reg == nil { |
| 287 | v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func) |
| 288 | } |
| 289 | return reg.(*Register).objNum |
| 290 | } |
| 291 | |
| 292 | // Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering. |
| 293 | func (v *Value) Reg1() int16 { |
| 294 | reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1] |
| 295 | if reg == nil { |
| 296 | v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func) |
| 297 | } |
| 298 | return reg.(*Register).objNum |
| 299 | } |
| 300 | |
| 301 | func (v *Value) RegName() string { |
| 302 | reg := v.Block.Func.RegAlloc[v.ID] |
| 303 | if reg == nil { |
| 304 | v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func) |
| 305 | } |
| 306 | return reg.(*Register).name |
| 307 | } |
Philip Hofer | b0e91d8 | 2017-03-03 13:44:18 -0800 | [diff] [blame] | 308 | |
| 309 | // MemoryArg returns the memory argument for the Value. |
Keith Randall | 256210c | 2017-05-15 09:00:55 -0700 | [diff] [blame] | 310 | // The returned value, if non-nil, will be memory-typed (or a tuple with a memory-typed second part). |
| 311 | // Otherwise, nil is returned. |
Philip Hofer | b0e91d8 | 2017-03-03 13:44:18 -0800 | [diff] [blame] | 312 | func (v *Value) MemoryArg() *Value { |
| 313 | if v.Op == OpPhi { |
| 314 | v.Fatalf("MemoryArg on Phi") |
| 315 | } |
| 316 | na := len(v.Args) |
| 317 | if na == 0 { |
| 318 | return nil |
| 319 | } |
Keith Randall | 256210c | 2017-05-15 09:00:55 -0700 | [diff] [blame] | 320 | if m := v.Args[na-1]; m.Type.IsMemory() { |
Philip Hofer | b0e91d8 | 2017-03-03 13:44:18 -0800 | [diff] [blame] | 321 | return m |
| 322 | } |
| 323 | return nil |
| 324 | } |
David Chase | a042221 | 2017-10-29 11:53:18 -0400 | [diff] [blame] | 325 | |
| 326 | // LackingPos indicates whether v is a value that is unlikely to have a correct |
| 327 | // position assigned to it. Ignoring such values leads to more user-friendly positions |
| 328 | // assigned to nearby values and the blocks containing them. |
| 329 | func (v *Value) LackingPos() bool { |
| 330 | // The exact definition of LackingPos is somewhat heuristically defined and may change |
| 331 | // in the future, for example if some of these operations are generated more carefully |
| 332 | // with respect to their source position. |
| 333 | return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi || |
| 334 | (v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem |
| 335 | } |