1
2
3
4
5 package ir
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/types"
10 "cmd/internal/obj"
11 "cmd/internal/objabi"
12 "cmd/internal/src"
13 "fmt"
14
15 "go/constant"
16 )
17
18
19 type Ident struct {
20 miniExpr
21 sym *types.Sym
22 }
23
24 func NewIdent(pos src.XPos, sym *types.Sym) *Ident {
25 n := new(Ident)
26 n.op = ONONAME
27 n.pos = pos
28 n.sym = sym
29 return n
30 }
31
32 func (n *Ident) Sym() *types.Sym { return n.sym }
33
34 func (*Ident) CanBeNtype() {}
35
36
37 type Name struct {
38 miniExpr
39 BuiltinOp Op
40 Class Class
41 pragma PragmaFlag
42 flags bitset16
43 DictIndex uint16
44 sym *types.Sym
45 Func *Func
46 Offset_ int64
47 val constant.Value
48 Opt interface{}
49 Embed *[]Embed
50
51 PkgName *PkgName
52
53
54
55
56
57
58 Defn Node
59
60
61 Curfn *Func
62
63 Ntype Ntype
64 Heapaddr *Name
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 Innermost *Name
136 Outer *Name
137 }
138
139 func (n *Name) isExpr() {}
140
141 func (n *Name) copy() Node { panic(n.no("copy")) }
142 func (n *Name) doChildren(do func(Node) bool) bool { return false }
143 func (n *Name) editChildren(edit func(Node) Node) {}
144
145
146
147
148 func (n *Name) TypeDefn() *types.Type {
149 if n.Ntype != nil {
150 return n.Ntype.Type()
151 }
152 return n.Type()
153 }
154
155
156
157 func (n *Name) RecordFrameOffset(offset int64) {
158 n.SetFrameOffset(offset)
159 }
160
161
162
163 func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
164 if sym == nil {
165 base.Fatalf("NewNameAt nil")
166 }
167 return newNameAt(pos, ONAME, sym)
168 }
169
170
171 func NewIota(pos src.XPos, sym *types.Sym) *Name {
172 if sym == nil {
173 base.Fatalf("NewIota nil")
174 }
175 return newNameAt(pos, OIOTA, sym)
176 }
177
178
179
180 func NewDeclNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
181 if sym == nil {
182 base.Fatalf("NewDeclNameAt nil")
183 }
184 switch op {
185 case ONAME, OTYPE, OLITERAL:
186
187 default:
188 base.Fatalf("NewDeclNameAt op %v", op)
189 }
190 return newNameAt(pos, op, sym)
191 }
192
193
194 func NewConstAt(pos src.XPos, sym *types.Sym, typ *types.Type, val constant.Value) *Name {
195 if sym == nil {
196 base.Fatalf("NewConstAt nil")
197 }
198 n := newNameAt(pos, OLITERAL, sym)
199 n.SetType(typ)
200 n.SetVal(val)
201 return n
202 }
203
204
205 func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
206 n := new(Name)
207 n.op = op
208 n.pos = pos
209 n.sym = sym
210 return n
211 }
212
213 func (n *Name) Name() *Name { return n }
214 func (n *Name) Sym() *types.Sym { return n.sym }
215 func (n *Name) SetSym(x *types.Sym) { n.sym = x }
216 func (n *Name) SubOp() Op { return n.BuiltinOp }
217 func (n *Name) SetSubOp(x Op) { n.BuiltinOp = x }
218 func (n *Name) SetFunc(x *Func) { n.Func = x }
219 func (n *Name) Offset() int64 { panic("Name.Offset") }
220 func (n *Name) SetOffset(x int64) {
221 if x != 0 {
222 panic("Name.SetOffset")
223 }
224 }
225 func (n *Name) FrameOffset() int64 { return n.Offset_ }
226 func (n *Name) SetFrameOffset(x int64) { n.Offset_ = x }
227 func (n *Name) Iota() int64 { return n.Offset_ }
228 func (n *Name) SetIota(x int64) { n.Offset_ = x }
229 func (n *Name) Walkdef() uint8 { return n.bits.get2(miniWalkdefShift) }
230 func (n *Name) SetWalkdef(x uint8) {
231 if x > 3 {
232 panic(fmt.Sprintf("cannot SetWalkdef %d", x))
233 }
234 n.bits.set2(miniWalkdefShift, x)
235 }
236
237 func (n *Name) Linksym() *obj.LSym { return n.sym.Linksym() }
238 func (n *Name) LinksymABI(abi obj.ABI) *obj.LSym { return n.sym.LinksymABI(abi) }
239
240 func (*Name) CanBeNtype() {}
241 func (*Name) CanBeAnSSASym() {}
242 func (*Name) CanBeAnSSAAux() {}
243
244
245 func (n *Name) Pragma() PragmaFlag { return n.pragma }
246
247
248 func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag }
249
250
251 func (n *Name) Alias() bool { return n.flags&nameAlias != 0 }
252
253
254 func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) }
255
256 const (
257 nameReadonly = 1 << iota
258 nameByval
259 nameNeedzero
260 nameAutoTemp
261 nameUsed
262 nameIsClosureVar
263 nameIsOutputParamHeapAddr
264 nameIsOutputParamInRegisters
265 nameAddrtaken
266 nameInlFormal
267 nameInlLocal
268 nameOpenDeferSlot
269 nameLibfuzzerExtraCounter
270 nameAlias
271 )
272
273 func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 }
274 func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 }
275 func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 }
276 func (n *Name) Used() bool { return n.flags&nameUsed != 0 }
277 func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 }
278 func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 }
279 func (n *Name) IsOutputParamInRegisters() bool { return n.flags&nameIsOutputParamInRegisters != 0 }
280 func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 }
281 func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 }
282 func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 }
283 func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 }
284 func (n *Name) LibfuzzerExtraCounter() bool { return n.flags&nameLibfuzzerExtraCounter != 0 }
285
286 func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) }
287 func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) }
288 func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) }
289 func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) }
290 func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) }
291 func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) }
292 func (n *Name) SetIsOutputParamInRegisters(b bool) { n.flags.set(nameIsOutputParamInRegisters, b) }
293 func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) }
294 func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) }
295 func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) }
296 func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) }
297 func (n *Name) SetLibfuzzerExtraCounter(b bool) { n.flags.set(nameLibfuzzerExtraCounter, b) }
298
299
300 func (n *Name) OnStack() bool {
301 if n.Op() == ONAME {
302 switch n.Class {
303 case PPARAM, PPARAMOUT, PAUTO:
304 return n.Esc() != EscHeap
305 case PEXTERN, PAUTOHEAP:
306 return false
307 }
308 }
309
310
311 panic(fmt.Sprintf("%v: not a variable: %v", base.FmtPos(n.Pos()), n))
312 }
313
314
315 func (n *Name) MarkReadonly() {
316 if n.Op() != ONAME {
317 base.Fatalf("Node.MarkReadonly %v", n.Op())
318 }
319 n.setReadonly(true)
320
321
322
323 n.Linksym().Type = objabi.SRODATA
324 }
325
326
327 func (n *Name) Val() constant.Value {
328 if n.val == nil {
329 return constant.MakeUnknown()
330 }
331 return n.val
332 }
333
334
335 func (n *Name) SetVal(v constant.Value) {
336 if n.op != OLITERAL {
337 panic(n.no("SetVal"))
338 }
339 AssertValidTypeForConst(n.Type(), v)
340 n.val = v
341 }
342
343
344
345
346
347 func (n *Name) Canonical() *Name {
348 if n.IsClosureVar() && n.Defn != nil {
349 n = n.Defn.(*Name)
350 }
351 return n
352 }
353
354 func (n *Name) SetByval(b bool) {
355 if n.Canonical() != n {
356 base.Fatalf("SetByval called on non-canonical variable: %v", n)
357 }
358 n.flags.set(nameByval, b)
359 }
360
361 func (n *Name) Byval() bool {
362
363
364 return n.Canonical().flags&nameByval != 0
365 }
366
367
368
369 func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name {
370 c := NewNameAt(pos, n.Sym())
371 c.Curfn = fn
372 c.Class = PAUTOHEAP
373 c.SetIsClosureVar(true)
374 c.Defn = n.Canonical()
375 c.Outer = n
376
377 c.SetType(n.Type())
378 c.SetTypecheck(n.Typecheck())
379
380 fn.ClosureVars = append(fn.ClosureVars, c)
381
382 return c
383 }
384
385
386
387 func NewHiddenParam(pos src.XPos, fn *Func, sym *types.Sym, typ *types.Type) *Name {
388 if fn.OClosure != nil {
389 base.FatalfAt(fn.Pos(), "cannot add hidden parameters to closures")
390 }
391
392 fn.SetNeedctxt(true)
393
394
395
396 fake := NewNameAt(pos, sym)
397 fake.Class = PPARAM
398 fake.SetType(typ)
399 fake.SetByval(true)
400
401 return NewClosureVar(pos, fn, fake)
402 }
403
404
405
406
407
408
409 func CaptureName(pos src.XPos, fn *Func, n *Name) *Name {
410 if n.Op() != ONAME || n.Curfn == nil {
411 return n
412 }
413 if n.IsClosureVar() {
414 base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n)
415 }
416
417 c := n.Innermost
418 if c == nil {
419 c = n
420 }
421 if c.Curfn == fn {
422 return c
423 }
424
425 if fn == nil {
426 base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn)
427 }
428
429
430 c = NewClosureVar(pos, fn, c)
431
432
433
434 n.Innermost = c
435
436 return c
437 }
438
439
440
441 func FinishCaptureNames(pos src.XPos, outerfn, fn *Func) {
442
443
444
445
446 for _, cv := range fn.ClosureVars {
447
448 n := cv.Defn.(*Name)
449 n.Innermost = cv.Outer
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474 cv.Outer = CaptureName(pos, outerfn, n)
475 }
476 }
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493 func SameSource(n1, n2 Node) bool {
494 return n1 == n2
495 }
496
497
498
499 func Uses(x Node, v *Name) bool {
500 if v == nil || v.Op() != ONAME {
501 base.Fatalf("RefersTo bad Name: %v", v)
502 }
503 return x.Op() == ONAME && x.Name() == v
504 }
505
506
507
508 func DeclaredBy(x, stmt Node) bool {
509 if stmt == nil {
510 base.Fatalf("DeclaredBy nil")
511 }
512 return x.Op() == ONAME && SameSource(x.Name().Defn, stmt)
513 }
514
515
516
517
518 type Class uint8
519
520
521 const (
522 Pxxx Class = iota
523 PEXTERN
524 PAUTO
525 PAUTOHEAP
526 PPARAM
527 PPARAMOUT
528 PTYPEPARAM
529 PFUNC
530
531
532 _ = uint((1 << 3) - iota)
533 )
534
535 type Embed struct {
536 Pos src.XPos
537 Patterns []string
538 }
539
540
541 type PkgName struct {
542 miniNode
543 sym *types.Sym
544 Pkg *types.Pkg
545 Used bool
546 }
547
548 func (p *PkgName) Sym() *types.Sym { return p.sym }
549
550 func (*PkgName) CanBeNtype() {}
551
552 func NewPkgName(pos src.XPos, sym *types.Sym, pkg *types.Pkg) *PkgName {
553 p := &PkgName{sym: sym, Pkg: pkg}
554 p.op = OPACK
555 p.pos = pos
556 return p
557 }
558
View as plain text