blob: 71955aaddd100a96c0644abe82e63dc648dcee82 [file] [log] [blame]
Keith Randallf52b2342015-03-03 13:38:14 -08001// 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
5package ssa
6
Todd Neal19447a62015-09-04 06:33:56 -05007import (
8 "fmt"
9 "math"
10)
Keith Randallf52b2342015-03-03 13:38:14 -080011
12// A Value represents a value in the SSA representation of the program.
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000013// The ID and Type fields must not be modified. The remainder may be modified
Keith Randallf52b2342015-03-03 13:38:14 -080014// if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)).
15type Value struct {
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000016 // A unique identifier for the value. For performance we allocate these IDs
Keith Randall0b46b422015-08-11 12:51:33 -070017 // densely starting at 1. There is no guarantee that there won't be occasional holes, though.
Keith Randallf52b2342015-03-03 13:38:14 -080018 ID ID
19
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000020 // The operation that computes this value. See op.go.
Keith Randallf52b2342015-03-03 13:38:14 -080021 Op Op
22
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000023 // The type of this value. Normally this will be a Go type, but there
Keith Randallf52b2342015-03-03 13:38:14 -080024 // are a few other pseudo-types, see type.go.
25 Type Type
26
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000027 // Auxiliary info for this value. The type of this information depends on the opcode and type.
Keith Randall8f22b522015-06-11 21:29:25 -070028 // AuxInt is used for integer values, Aux is used for other values.
Kevin Burke8e24a982016-08-20 22:05:47 -070029 // Floats are stored in AuxInt using math.Float64bits(f).
Keith Randall8f22b522015-06-11 21:29:25 -070030 AuxInt int64
31 Aux interface{}
Keith Randallf52b2342015-03-03 13:38:14 -080032
33 // Arguments of this value
34 Args []*Value
35
36 // Containing basic block
37 Block *Block
38
Michael Matloob81ccf502015-05-30 01:03:06 -040039 // Source line number
40 Line int32
41
Keith Randall56e0ecc2016-03-15 20:45:50 -070042 // Use count. Each appearance in Value.Args and Block.Control counts once.
43 Uses int32
44
Josh Bleecher Snyderf3a29f12016-03-06 21:22:11 -080045 // Storage for the first three args
46 argstorage [3]*Value
Keith Randallf52b2342015-03-03 13:38:14 -080047}
48
49// Examples:
50// Opcode aux args
51// OpAdd nil 2
Keith Randall2c9b4912015-03-26 10:49:03 -070052// OpConst string 0 string constant
53// OpConst int64 0 int64 constant
Keith Randallf52b2342015-03-03 13:38:14 -080054// OpAddcq int64 1 amd64 op: v = arg[0] + constant
55
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +000056// short form print. Just v#.
Keith Randallf52b2342015-03-03 13:38:14 -080057func (v *Value) String() string {
Josh Bleecher Snyder220e7052015-08-22 13:30:45 -070058 if v == nil {
59 return "nil" // should never happen, but not panicking helps with debugging
60 }
Keith Randallf52b2342015-03-03 13:38:14 -080061 return fmt.Sprintf("v%d", v.ID)
62}
63
Keith Randall16b1fce2016-01-31 11:39:39 -080064func (v *Value) AuxInt8() int8 {
65 if opcodeTable[v.Op].auxType != auxInt8 {
66 v.Fatalf("op %s doesn't have an int8 aux field", v.Op)
67 }
68 return int8(v.AuxInt)
69}
70
71func (v *Value) AuxInt16() int16 {
72 if opcodeTable[v.Op].auxType != auxInt16 {
73 v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
74 }
75 return int16(v.AuxInt)
76}
77
78func (v *Value) AuxInt32() int32 {
79 if opcodeTable[v.Op].auxType != auxInt32 {
80 v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
81 }
82 return int32(v.AuxInt)
83}
Todd Nealc17b6b42016-02-19 16:58:21 -060084
Keith Randall16b1fce2016-01-31 11:39:39 -080085func (v *Value) AuxFloat() float64 {
Todd Nealf6ceed22016-03-11 19:36:54 -060086 if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
Keith Randall16b1fce2016-01-31 11:39:39 -080087 v.Fatalf("op %s doesn't have a float aux field", v.Op)
88 }
89 return math.Float64frombits(uint64(v.AuxInt))
90}
91func (v *Value) AuxValAndOff() ValAndOff {
92 if opcodeTable[v.Op].auxType != auxSymValAndOff {
93 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
94 }
95 return ValAndOff(v.AuxInt)
96}
97
Keith Randallf52b2342015-03-03 13:38:14 -080098// long form print. v# = opcode <type> [aux] args [: reg]
99func (v *Value) LongString() string {
Keith Randall0dca7352015-06-06 16:03:33 -0700100 s := fmt.Sprintf("v%d = %s", v.ID, v.Op.String())
Keith Randallf52b2342015-03-03 13:38:14 -0800101 s += " <" + v.Type.String() + ">"
Frits van Bommelb13b2492016-04-30 11:13:29 +0200102 s += v.auxString()
Keith Randallf52b2342015-03-03 13:38:14 -0800103 for _, a := range v.Args {
104 s += fmt.Sprintf(" %v", a)
105 }
106 r := v.Block.Func.RegAlloc
Keith Randall0b46b422015-08-11 12:51:33 -0700107 if int(v.ID) < len(r) && r[v.ID] != nil {
Keith Randallf52b2342015-03-03 13:38:14 -0800108 s += " : " + r[v.ID].Name()
109 }
110 return s
111}
112
Frits van Bommelb13b2492016-04-30 11:13:29 +0200113func (v *Value) auxString() string {
114 switch opcodeTable[v.Op].auxType {
115 case auxBool:
116 if v.AuxInt == 0 {
117 return " [false]"
118 } else {
119 return " [true]"
120 }
121 case auxInt8:
122 return fmt.Sprintf(" [%d]", v.AuxInt8())
123 case auxInt16:
124 return fmt.Sprintf(" [%d]", v.AuxInt16())
125 case auxInt32:
126 return fmt.Sprintf(" [%d]", v.AuxInt32())
127 case auxInt64, auxInt128:
128 return fmt.Sprintf(" [%d]", v.AuxInt)
Keith Randall33bb5972016-08-31 12:30:46 -0700129 case auxSizeAndAlign:
130 return fmt.Sprintf(" [%s]", SizeAndAlign(v.AuxInt))
Frits van Bommelb13b2492016-04-30 11:13:29 +0200131 case auxFloat32, auxFloat64:
132 return fmt.Sprintf(" [%g]", v.AuxFloat())
133 case auxString:
134 return fmt.Sprintf(" {%q}", v.Aux)
135 case auxSym:
136 if v.Aux != nil {
137 return fmt.Sprintf(" {%s}", v.Aux)
138 }
139 case auxSymOff, auxSymInt32:
140 s := ""
141 if v.Aux != nil {
142 s = fmt.Sprintf(" {%s}", v.Aux)
143 }
144 if v.AuxInt != 0 {
145 s += fmt.Sprintf(" [%v]", v.AuxInt)
146 }
147 return s
148 case auxSymValAndOff:
149 s := ""
150 if v.Aux != nil {
151 s = fmt.Sprintf(" {%s}", v.Aux)
152 }
153 return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
154 }
155 return ""
156}
157
Keith Randallf52b2342015-03-03 13:38:14 -0800158func (v *Value) AddArg(w *Value) {
Josh Bleecher Snyder7c2c0b42015-03-16 16:31:13 -0700159 if v.Args == nil {
160 v.resetArgs() // use argstorage
161 }
Keith Randallf52b2342015-03-03 13:38:14 -0800162 v.Args = append(v.Args, w)
Keith Randall56e0ecc2016-03-15 20:45:50 -0700163 w.Uses++
Keith Randallf52b2342015-03-03 13:38:14 -0800164}
165func (v *Value) AddArgs(a ...*Value) {
Josh Bleecher Snyder7c2c0b42015-03-16 16:31:13 -0700166 if v.Args == nil {
167 v.resetArgs() // use argstorage
168 }
Keith Randallf52b2342015-03-03 13:38:14 -0800169 v.Args = append(v.Args, a...)
Keith Randall56e0ecc2016-03-15 20:45:50 -0700170 for _, x := range a {
171 x.Uses++
172 }
Keith Randallf52b2342015-03-03 13:38:14 -0800173}
174func (v *Value) SetArg(i int, w *Value) {
Keith Randall56e0ecc2016-03-15 20:45:50 -0700175 v.Args[i].Uses--
Keith Randallf52b2342015-03-03 13:38:14 -0800176 v.Args[i] = w
Keith Randall56e0ecc2016-03-15 20:45:50 -0700177 w.Uses++
Keith Randallf52b2342015-03-03 13:38:14 -0800178}
179func (v *Value) RemoveArg(i int) {
Keith Randall56e0ecc2016-03-15 20:45:50 -0700180 v.Args[i].Uses--
Keith Randallf52b2342015-03-03 13:38:14 -0800181 copy(v.Args[i:], v.Args[i+1:])
Josh Bleecher Snyder7c2c0b42015-03-16 16:31:13 -0700182 v.Args[len(v.Args)-1] = nil // aid GC
Keith Randallf52b2342015-03-03 13:38:14 -0800183 v.Args = v.Args[:len(v.Args)-1]
184}
185func (v *Value) SetArgs1(a *Value) {
186 v.resetArgs()
187 v.AddArg(a)
188}
189func (v *Value) SetArgs2(a *Value, b *Value) {
190 v.resetArgs()
191 v.AddArg(a)
192 v.AddArg(b)
193}
194
195func (v *Value) resetArgs() {
Keith Randall56e0ecc2016-03-15 20:45:50 -0700196 for _, a := range v.Args {
197 a.Uses--
198 }
Keith Randallf52b2342015-03-03 13:38:14 -0800199 v.argstorage[0] = nil
200 v.argstorage[1] = nil
Keith Randall7e406272016-04-11 13:17:52 -0700201 v.argstorage[2] = nil
Keith Randallf52b2342015-03-03 13:38:14 -0800202 v.Args = v.argstorage[:0]
203}
Josh Bleecher Snyder8c6abfe2015-06-12 11:01:13 -0700204
Alexandru Moșoi2df4b9c2016-02-04 17:21:57 +0100205func (v *Value) reset(op Op) {
206 v.Op = op
207 v.resetArgs()
208 v.AuxInt = 0
209 v.Aux = nil
210}
211
Keith Randallc140df02015-12-09 15:58:18 -0800212// copyInto makes a new value identical to v and adds it to the end of b.
213func (v *Value) copyInto(b *Block) *Value {
214 c := b.NewValue0(v.Line, v.Op, v.Type)
215 c.Aux = v.Aux
216 c.AuxInt = v.AuxInt
217 c.AddArgs(v.Args...)
Keith Randallf94e0742016-01-26 15:47:08 -0800218 for _, a := range v.Args {
219 if a.Type.IsMemory() {
220 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
221 }
222 }
Keith Randallc140df02015-12-09 15:58:18 -0800223 return c
224}
225
Keith Randallda8af472016-01-13 11:14:57 -0800226func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
David Chase88b230e2016-01-29 14:44:15 -0500227func (v *Value) Log() bool { return v.Block.Log() }
Keith Randallda8af472016-01-13 11:14:57 -0800228func (v *Value) Fatalf(msg string, args ...interface{}) {
229 v.Block.Func.Config.Fatalf(v.Line, msg, args...)
230}
Keith Randall8c46aa52015-06-19 21:02:28 -0700231
Keith Randall47c9e132016-03-23 10:20:44 -0700232// isGenericIntConst returns whether v is a generic integer constant.
233func (v *Value) isGenericIntConst() bool {
234 return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
235}
236
Keith Randall8c46aa52015-06-19 21:02:28 -0700237// ExternSymbol is an aux value that encodes a variable's
238// constant offset from the static base pointer.
239type ExternSymbol struct {
240 Typ Type // Go type
241 Sym fmt.Stringer // A *gc.Sym referring to a global variable
242 // Note: the offset for an external symbol is not
243 // calculated until link time.
244}
245
246// ArgSymbol is an aux value that encodes an argument or result
247// variable's constant offset from FP (FP = SP + framesize).
248type ArgSymbol struct {
Keith Randallc24681a2015-10-22 14:22:38 -0700249 Typ Type // Go type
250 Node GCNode // A *gc.Node referring to the argument/result variable.
Keith Randall8c46aa52015-06-19 21:02:28 -0700251}
252
253// AutoSymbol is an aux value that encodes a local variable's
254// constant offset from SP.
255type AutoSymbol struct {
Keith Randallc24681a2015-10-22 14:22:38 -0700256 Typ Type // Go type
257 Node GCNode // A *gc.Node referring to a local (auto) variable.
Keith Randall8c46aa52015-06-19 21:02:28 -0700258}
259
260func (s *ExternSymbol) String() string {
261 return s.Sym.String()
262}
263
264func (s *ArgSymbol) String() string {
Keith Randalld2107fc2015-08-24 02:16:19 -0700265 return s.Node.String()
Keith Randall8c46aa52015-06-19 21:02:28 -0700266}
267
268func (s *AutoSymbol) String() string {
Keith Randalld2107fc2015-08-24 02:16:19 -0700269 return s.Node.String()
Keith Randall8c46aa52015-06-19 21:02:28 -0700270}
Keith Randall833ed7c2016-09-16 09:36:00 -0700271
272// Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering.
273func (v *Value) Reg() int16 {
274 reg := v.Block.Func.RegAlloc[v.ID]
275 if reg == nil {
276 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
277 }
278 return reg.(*Register).objNum
279}
280
281// Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering.
282func (v *Value) Reg0() int16 {
283 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
284 if reg == nil {
285 v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
286 }
287 return reg.(*Register).objNum
288}
289
290// Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering.
291func (v *Value) Reg1() int16 {
292 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
293 if reg == nil {
294 v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
295 }
296 return reg.(*Register).objNum
297}
298
299func (v *Value) RegName() string {
300 reg := v.Block.Func.RegAlloc[v.ID]
301 if reg == nil {
302 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
303 }
304 return reg.(*Register).name
305}