]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/ssa/debug.go
all: fix typos in go file comments
[gostls13.git] / src / cmd / compile / internal / ssa / debug.go
1 // Copyright 2017 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/compile/internal/abi"
9         "cmd/compile/internal/abt"
10         "cmd/compile/internal/ir"
11         "cmd/compile/internal/types"
12         "cmd/internal/dwarf"
13         "cmd/internal/obj"
14         "cmd/internal/src"
15         "encoding/hex"
16         "fmt"
17         "internal/buildcfg"
18         "math/bits"
19         "sort"
20         "strings"
21 )
22
23 type SlotID int32
24 type VarID int32
25
26 // A FuncDebug contains all the debug information for the variables in a
27 // function. Variables are identified by their LocalSlot, which may be
28 // the result of decomposing a larger variable.
29 type FuncDebug struct {
30         // Slots is all the slots used in the debug info, indexed by their SlotID.
31         Slots []LocalSlot
32         // The user variables, indexed by VarID.
33         Vars []*ir.Name
34         // The slots that make up each variable, indexed by VarID.
35         VarSlots [][]SlotID
36         // The location list data, indexed by VarID. Must be processed by PutLocationList.
37         LocationLists [][]byte
38         // Register-resident output parameters for the function. This is filled in at
39         // SSA generation time.
40         RegOutputParams []*ir.Name
41         // Variable declarations that were removed during optimization
42         OptDcl []*ir.Name
43
44         // Filled in by the user. Translates Block and Value ID to PC.
45         GetPC func(ID, ID) int64
46 }
47
48 type BlockDebug struct {
49         // State at the start and end of the block. These are initialized,
50         // and updated from new information that flows on back edges.
51         startState, endState abt.T
52         // Use these to avoid excess work in the merge. If none of the
53         // predecessors has changed since the last check, the old answer is
54         // still good.
55         lastCheckedTime, lastChangedTime int32
56         // Whether the block had any changes to user variables at all.
57         relevant bool
58         // false until the block has been processed at least once. This
59         // affects how the merge is done; the goal is to maximize sharing
60         // and avoid allocation.
61         everProcessed bool
62 }
63
64 // A liveSlot is a slot that's live in loc at entry/exit of a block.
65 type liveSlot struct {
66         VarLoc
67 }
68
69 func (ls *liveSlot) String() string {
70         return fmt.Sprintf("0x%x.%d.%d", ls.Registers, ls.stackOffsetValue(), int32(ls.StackOffset)&1)
71 }
72
73 func (loc liveSlot) absent() bool {
74         return loc.Registers == 0 && !loc.onStack()
75 }
76
77 // StackOffset encodes whether a value is on the stack and if so, where.
78 // It is a 31-bit integer followed by a presence flag at the low-order
79 // bit.
80 type StackOffset int32
81
82 func (s StackOffset) onStack() bool {
83         return s != 0
84 }
85
86 func (s StackOffset) stackOffsetValue() int32 {
87         return int32(s) >> 1
88 }
89
90 // stateAtPC is the current state of all variables at some point.
91 type stateAtPC struct {
92         // The location of each known slot, indexed by SlotID.
93         slots []VarLoc
94         // The slots present in each register, indexed by register number.
95         registers [][]SlotID
96 }
97
98 // reset fills state with the live variables from live.
99 func (state *stateAtPC) reset(live abt.T) {
100         slots, registers := state.slots, state.registers
101         for i := range slots {
102                 slots[i] = VarLoc{}
103         }
104         for i := range registers {
105                 registers[i] = registers[i][:0]
106         }
107         for it := live.Iterator(); !it.Done(); {
108                 k, d := it.Next()
109                 live := d.(*liveSlot)
110                 slots[k] = live.VarLoc
111                 if live.VarLoc.Registers == 0 {
112                         continue
113                 }
114
115                 mask := uint64(live.VarLoc.Registers)
116                 for {
117                         if mask == 0 {
118                                 break
119                         }
120                         reg := uint8(bits.TrailingZeros64(mask))
121                         mask &^= 1 << reg
122
123                         registers[reg] = append(registers[reg], SlotID(k))
124                 }
125         }
126         state.slots, state.registers = slots, registers
127 }
128
129 func (s *debugState) LocString(loc VarLoc) string {
130         if loc.absent() {
131                 return "<nil>"
132         }
133
134         var storage []string
135         if loc.onStack() {
136                 storage = append(storage, fmt.Sprintf("@%+d", loc.stackOffsetValue()))
137         }
138
139         mask := uint64(loc.Registers)
140         for {
141                 if mask == 0 {
142                         break
143                 }
144                 reg := uint8(bits.TrailingZeros64(mask))
145                 mask &^= 1 << reg
146
147                 storage = append(storage, s.registers[reg].String())
148         }
149         return strings.Join(storage, ",")
150 }
151
152 // A VarLoc describes the storage for part of a user variable.
153 type VarLoc struct {
154         // The registers this variable is available in. There can be more than
155         // one in various situations, e.g. it's being moved between registers.
156         Registers RegisterSet
157
158         StackOffset
159 }
160
161 func (loc VarLoc) absent() bool {
162         return loc.Registers == 0 && !loc.onStack()
163 }
164
165 func (loc VarLoc) intersect(other VarLoc) VarLoc {
166         if !loc.onStack() || !other.onStack() || loc.StackOffset != other.StackOffset {
167                 loc.StackOffset = 0
168         }
169         loc.Registers &= other.Registers
170         return loc
171 }
172
173 var BlockStart = &Value{
174         ID:  -10000,
175         Op:  OpInvalid,
176         Aux: StringToAux("BlockStart"),
177 }
178
179 var BlockEnd = &Value{
180         ID:  -20000,
181         Op:  OpInvalid,
182         Aux: StringToAux("BlockEnd"),
183 }
184
185 var FuncEnd = &Value{
186         ID:  -30000,
187         Op:  OpInvalid,
188         Aux: StringToAux("FuncEnd"),
189 }
190
191 // RegisterSet is a bitmap of registers, indexed by Register.num.
192 type RegisterSet uint64
193
194 // logf prints debug-specific logging to stdout (always stdout) if the
195 // current function is tagged by GOSSAFUNC (for ssa output directed
196 // either to stdout or html).
197 func (s *debugState) logf(msg string, args ...interface{}) {
198         if s.f.PrintOrHtmlSSA {
199                 fmt.Printf(msg, args...)
200         }
201 }
202
203 type debugState struct {
204         // See FuncDebug.
205         slots    []LocalSlot
206         vars     []*ir.Name
207         varSlots [][]SlotID
208         lists    [][]byte
209
210         // The user variable that each slot rolls up to, indexed by SlotID.
211         slotVars []VarID
212
213         f             *Func
214         loggingLevel  int
215         convergeCount int // testing; iterate over block debug state this many times
216         registers     []Register
217         stackOffset   func(LocalSlot) int32
218         ctxt          *obj.Link
219
220         // The names (slots) associated with each value, indexed by Value ID.
221         valueNames [][]SlotID
222
223         // The current state of whatever analysis is running.
224         currentState stateAtPC
225         changedVars  *sparseSet
226         changedSlots *sparseSet
227
228         // The pending location list entry for each user variable, indexed by VarID.
229         pendingEntries []pendingEntry
230
231         varParts         map[*ir.Name][]SlotID
232         blockDebug       []BlockDebug
233         pendingSlotLocs  []VarLoc
234         partsByVarOffset sort.Interface
235 }
236
237 func (state *debugState) initializeCache(f *Func, numVars, numSlots int) {
238         // One blockDebug per block. Initialized in allocBlock.
239         if cap(state.blockDebug) < f.NumBlocks() {
240                 state.blockDebug = make([]BlockDebug, f.NumBlocks())
241         } else {
242                 // This local variable, and the ones like it below, enable compiler
243                 // optimizations. Don't inline them.
244                 b := state.blockDebug[:f.NumBlocks()]
245                 for i := range b {
246                         b[i] = BlockDebug{}
247                 }
248         }
249
250         // A list of slots per Value. Reuse the previous child slices.
251         if cap(state.valueNames) < f.NumValues() {
252                 old := state.valueNames
253                 state.valueNames = make([][]SlotID, f.NumValues())
254                 copy(state.valueNames, old)
255         }
256         vn := state.valueNames[:f.NumValues()]
257         for i := range vn {
258                 vn[i] = vn[i][:0]
259         }
260
261         // Slot and register contents for currentState. Cleared by reset().
262         if cap(state.currentState.slots) < numSlots {
263                 state.currentState.slots = make([]VarLoc, numSlots)
264         } else {
265                 state.currentState.slots = state.currentState.slots[:numSlots]
266         }
267         if cap(state.currentState.registers) < len(state.registers) {
268                 state.currentState.registers = make([][]SlotID, len(state.registers))
269         } else {
270                 state.currentState.registers = state.currentState.registers[:len(state.registers)]
271         }
272
273         // A relatively small slice, but used many times as the return from processValue.
274         state.changedVars = newSparseSet(numVars)
275         state.changedSlots = newSparseSet(numSlots)
276
277         // A pending entry per user variable, with space to track each of its pieces.
278         numPieces := 0
279         for i := range state.varSlots {
280                 numPieces += len(state.varSlots[i])
281         }
282         if cap(state.pendingSlotLocs) < numPieces {
283                 state.pendingSlotLocs = make([]VarLoc, numPieces)
284         } else {
285                 psl := state.pendingSlotLocs[:numPieces]
286                 for i := range psl {
287                         psl[i] = VarLoc{}
288                 }
289         }
290         if cap(state.pendingEntries) < numVars {
291                 state.pendingEntries = make([]pendingEntry, numVars)
292         }
293         pe := state.pendingEntries[:numVars]
294         freePieceIdx := 0
295         for varID, slots := range state.varSlots {
296                 pe[varID] = pendingEntry{
297                         pieces: state.pendingSlotLocs[freePieceIdx : freePieceIdx+len(slots)],
298                 }
299                 freePieceIdx += len(slots)
300         }
301         state.pendingEntries = pe
302
303         if cap(state.lists) < numVars {
304                 state.lists = make([][]byte, numVars)
305         } else {
306                 state.lists = state.lists[:numVars]
307                 for i := range state.lists {
308                         state.lists[i] = nil
309                 }
310         }
311 }
312
313 func (state *debugState) allocBlock(b *Block) *BlockDebug {
314         return &state.blockDebug[b.ID]
315 }
316
317 func (s *debugState) blockEndStateString(b *BlockDebug) string {
318         endState := stateAtPC{slots: make([]VarLoc, len(s.slots)), registers: make([][]SlotID, len(s.registers))}
319         endState.reset(b.endState)
320         return s.stateString(endState)
321 }
322
323 func (s *debugState) stateString(state stateAtPC) string {
324         var strs []string
325         for slotID, loc := range state.slots {
326                 if !loc.absent() {
327                         strs = append(strs, fmt.Sprintf("\t%v = %v\n", s.slots[slotID], s.LocString(loc)))
328                 }
329         }
330
331         strs = append(strs, "\n")
332         for reg, slots := range state.registers {
333                 if len(slots) != 0 {
334                         var slotStrs []string
335                         for _, slot := range slots {
336                                 slotStrs = append(slotStrs, s.slots[slot].String())
337                         }
338                         strs = append(strs, fmt.Sprintf("\t%v = %v\n", &s.registers[reg], slotStrs))
339                 }
340         }
341
342         if len(strs) == 1 {
343                 return "(no vars)\n"
344         }
345         return strings.Join(strs, "")
346 }
347
348 // slotCanonicalizer is a table used to lookup and canonicalize
349 // LocalSlot's in a type insensitive way (e.g. taking into account the
350 // base name, offset, and width of the slot, but ignoring the slot
351 // type).
352 type slotCanonicalizer struct {
353         slmap  map[slotKey]SlKeyIdx
354         slkeys []LocalSlot
355 }
356
357 func newSlotCanonicalizer() *slotCanonicalizer {
358         return &slotCanonicalizer{
359                 slmap:  make(map[slotKey]SlKeyIdx),
360                 slkeys: []LocalSlot{LocalSlot{N: nil}},
361         }
362 }
363
364 type SlKeyIdx uint32
365
366 const noSlot = SlKeyIdx(0)
367
368 // slotKey is a type-insensitive encapsulation of a LocalSlot; it
369 // is used to key a map within slotCanonicalizer.
370 type slotKey struct {
371         name        *ir.Name
372         offset      int64
373         width       int64
374         splitOf     SlKeyIdx // idx in slkeys slice in slotCanonicalizer
375         splitOffset int64
376 }
377
378 // lookup looks up a LocalSlot in the slot canonicalizer "sc", returning
379 // a canonical index for the slot, and adding it to the table if need
380 // be. Return value is the canonical slot index, and a boolean indicating
381 // whether the slot was found in the table already (TRUE => found).
382 func (sc *slotCanonicalizer) lookup(ls LocalSlot) (SlKeyIdx, bool) {
383         split := noSlot
384         if ls.SplitOf != nil {
385                 split, _ = sc.lookup(*ls.SplitOf)
386         }
387         k := slotKey{
388                 name: ls.N, offset: ls.Off, width: ls.Type.Size(),
389                 splitOf: split, splitOffset: ls.SplitOffset,
390         }
391         if idx, ok := sc.slmap[k]; ok {
392                 return idx, true
393         }
394         rv := SlKeyIdx(len(sc.slkeys))
395         sc.slkeys = append(sc.slkeys, ls)
396         sc.slmap[k] = rv
397         return rv, false
398 }
399
400 func (sc *slotCanonicalizer) canonSlot(idx SlKeyIdx) LocalSlot {
401         return sc.slkeys[idx]
402 }
403
404 // PopulateABIInRegArgOps examines the entry block of the function
405 // and looks for incoming parameters that have missing or partial
406 // OpArg{Int,Float}Reg values, inserting additional values in
407 // cases where they are missing. Example:
408 //
409 //      func foo(s string, used int, notused int) int {
410 //        return len(s) + used
411 //      }
412 //
413 // In the function above, the incoming parameter "used" is fully live,
414 // "notused" is not live, and "s" is partially live (only the length
415 // field of the string is used). At the point where debug value
416 // analysis runs, we might expect to see an entry block with:
417 //
418 //      b1:
419 //        v4 = ArgIntReg <uintptr> {s+8} [0] : BX
420 //        v5 = ArgIntReg <int> {used} [0] : CX
421 //
422 // While this is an accurate picture of the live incoming params,
423 // we also want to have debug locations for non-live params (or
424 // their non-live pieces), e.g. something like
425 //
426 //      b1:
427 //        v9 = ArgIntReg <*uint8> {s+0} [0] : AX
428 //        v4 = ArgIntReg <uintptr> {s+8} [0] : BX
429 //        v5 = ArgIntReg <int> {used} [0] : CX
430 //        v10 = ArgIntReg <int> {unused} [0] : DI
431 //
432 // This function examines the live OpArg{Int,Float}Reg values and
433 // synthesizes new (dead) values for the non-live params or the
434 // non-live pieces of partially live params.
435 func PopulateABIInRegArgOps(f *Func) {
436         pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())
437
438         // When manufacturing new slots that correspond to splits of
439         // composite parameters, we want to avoid creating a new sub-slot
440         // that differs from some existing sub-slot only by type, since
441         // the debug location analysis will treat that slot as a separate
442         // entity. To achieve this, create a lookup table of existing
443         // slots that is type-insenstitive.
444         sc := newSlotCanonicalizer()
445         for _, sl := range f.Names {
446                 sc.lookup(*sl)
447         }
448
449         // Add slot -> value entry to f.NamedValues if not already present.
450         addToNV := func(v *Value, sl LocalSlot) {
451                 values, ok := f.NamedValues[sl]
452                 if !ok {
453                         // Haven't seen this slot yet.
454                         sla := f.localSlotAddr(sl)
455                         f.Names = append(f.Names, sla)
456                 } else {
457                         for _, ev := range values {
458                                 if v == ev {
459                                         return
460                                 }
461                         }
462                 }
463                 values = append(values, v)
464                 f.NamedValues[sl] = values
465         }
466
467         newValues := []*Value{}
468
469         abiRegIndexToRegister := func(reg abi.RegIndex) int8 {
470                 i := f.ABISelf.FloatIndexFor(reg)
471                 if i >= 0 { // float PR
472                         return f.Config.floatParamRegs[i]
473                 } else {
474                         return f.Config.intParamRegs[reg]
475                 }
476         }
477
478         // Helper to construct a new OpArg{Float,Int}Reg op value.
479         var pos src.XPos
480         if len(f.Entry.Values) != 0 {
481                 pos = f.Entry.Values[0].Pos
482         }
483         synthesizeOpIntFloatArg := func(n *ir.Name, t *types.Type, reg abi.RegIndex, sl LocalSlot) *Value {
484                 aux := &AuxNameOffset{n, sl.Off}
485                 op, auxInt := ArgOpAndRegisterFor(reg, f.ABISelf)
486                 v := f.newValueNoBlock(op, t, pos)
487                 v.AuxInt = auxInt
488                 v.Aux = aux
489                 v.Args = nil
490                 v.Block = f.Entry
491                 newValues = append(newValues, v)
492                 addToNV(v, sl)
493                 f.setHome(v, &f.Config.registers[abiRegIndexToRegister(reg)])
494                 return v
495         }
496
497         // Make a pass through the entry block looking for
498         // OpArg{Int,Float}Reg ops. Record the slots they use in a table
499         // ("sc"). We use a type-insensitive lookup for the slot table,
500         // since the type we get from the ABI analyzer won't always match
501         // what the compiler uses when creating OpArg{Int,Float}Reg ops.
502         for _, v := range f.Entry.Values {
503                 if v.Op == OpArgIntReg || v.Op == OpArgFloatReg {
504                         aux := v.Aux.(*AuxNameOffset)
505                         sl := LocalSlot{N: aux.Name, Type: v.Type, Off: aux.Offset}
506                         // install slot in lookup table
507                         idx, _ := sc.lookup(sl)
508                         // add to f.NamedValues if not already present
509                         addToNV(v, sc.canonSlot(idx))
510                 } else if v.Op.IsCall() {
511                         // if we hit a call, we've gone too far.
512                         break
513                 }
514         }
515
516         // Now make a pass through the ABI in-params, looking for params
517         // or pieces of params that we didn't encounter in the loop above.
518         for _, inp := range pri.InParams() {
519                 if !isNamedRegParam(inp) {
520                         continue
521                 }
522                 n := inp.Name.(*ir.Name)
523
524                 // Param is spread across one or more registers. Walk through
525                 // each piece to see whether we've seen an arg reg op for it.
526                 types, offsets := inp.RegisterTypesAndOffsets()
527                 for k, t := range types {
528                         // Note: this recipe for creating a LocalSlot is designed
529                         // to be compatible with the one used in expand_calls.go
530                         // as opposed to decompose.go. The expand calls code just
531                         // takes the base name and creates an offset into it,
532                         // without using the SplitOf/SplitOffset fields. The code
533                         // in decompose.go does the opposite -- it creates a
534                         // LocalSlot object with "Off" set to zero, but with
535                         // SplitOf pointing to a parent slot, and SplitOffset
536                         // holding the offset into the parent object.
537                         pieceSlot := LocalSlot{N: n, Type: t, Off: offsets[k]}
538
539                         // Look up this piece to see if we've seen a reg op
540                         // for it. If not, create one.
541                         _, found := sc.lookup(pieceSlot)
542                         if !found {
543                                 // This slot doesn't appear in the map, meaning it
544                                 // corresponds to an in-param that is not live, or
545                                 // a portion of an in-param that is not live/used.
546                                 // Add a new dummy OpArg{Int,Float}Reg for it.
547                                 synthesizeOpIntFloatArg(n, t, inp.Registers[k],
548                                         pieceSlot)
549                         }
550                 }
551         }
552
553         // Insert the new values into the head of the block.
554         f.Entry.Values = append(newValues, f.Entry.Values...)
555 }
556
557 // BuildFuncDebug debug information for f, placing the results
558 // in "rval". f must be fully processed, so that each Value is where it
559 // will be when machine code is emitted.
560 func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func(LocalSlot) int32, rval *FuncDebug) {
561         if f.RegAlloc == nil {
562                 f.Fatalf("BuildFuncDebug on func %v that has not been fully processed", f)
563         }
564         state := &f.Cache.debugState
565         state.loggingLevel = loggingLevel % 1000
566
567         // A specific number demands exactly that many iterations. Under
568         // particular circumstances it make require more than the total of
569         // 2 passes implied by a single run through liveness and a single
570         // run through location list generation.
571         state.convergeCount = loggingLevel / 1000
572         state.f = f
573         state.registers = f.Config.registers
574         state.stackOffset = stackOffset
575         state.ctxt = ctxt
576
577         if buildcfg.Experiment.RegabiArgs {
578                 PopulateABIInRegArgOps(f)
579         }
580
581         if state.loggingLevel > 0 {
582                 state.logf("Generating location lists for function %q\n", f.Name)
583         }
584
585         if state.varParts == nil {
586                 state.varParts = make(map[*ir.Name][]SlotID)
587         } else {
588                 for n := range state.varParts {
589                         delete(state.varParts, n)
590                 }
591         }
592
593         // Recompose any decomposed variables, and establish the canonical
594         // IDs for each var and slot by filling out state.vars and state.slots.
595
596         state.slots = state.slots[:0]
597         state.vars = state.vars[:0]
598         for i, slot := range f.Names {
599                 state.slots = append(state.slots, *slot)
600                 if ir.IsSynthetic(slot.N) {
601                         continue
602                 }
603
604                 topSlot := slot
605                 for topSlot.SplitOf != nil {
606                         topSlot = topSlot.SplitOf
607                 }
608                 if _, ok := state.varParts[topSlot.N]; !ok {
609                         state.vars = append(state.vars, topSlot.N)
610                 }
611                 state.varParts[topSlot.N] = append(state.varParts[topSlot.N], SlotID(i))
612         }
613
614         // Recreate the LocalSlot for each stack-only variable.
615         // This would probably be better as an output from stackframe.
616         for _, b := range f.Blocks {
617                 for _, v := range b.Values {
618                         if v.Op == OpVarDef {
619                                 n := v.Aux.(*ir.Name)
620                                 if ir.IsSynthetic(n) {
621                                         continue
622                                 }
623
624                                 if _, ok := state.varParts[n]; !ok {
625                                         slot := LocalSlot{N: n, Type: v.Type, Off: 0}
626                                         state.slots = append(state.slots, slot)
627                                         state.varParts[n] = []SlotID{SlotID(len(state.slots) - 1)}
628                                         state.vars = append(state.vars, n)
629                                 }
630                         }
631                 }
632         }
633
634         // Fill in the var<->slot mappings.
635         if cap(state.varSlots) < len(state.vars) {
636                 state.varSlots = make([][]SlotID, len(state.vars))
637         } else {
638                 state.varSlots = state.varSlots[:len(state.vars)]
639                 for i := range state.varSlots {
640                         state.varSlots[i] = state.varSlots[i][:0]
641                 }
642         }
643         if cap(state.slotVars) < len(state.slots) {
644                 state.slotVars = make([]VarID, len(state.slots))
645         } else {
646                 state.slotVars = state.slotVars[:len(state.slots)]
647         }
648
649         if state.partsByVarOffset == nil {
650                 state.partsByVarOffset = &partsByVarOffset{}
651         }
652         for varID, n := range state.vars {
653                 parts := state.varParts[n]
654                 state.varSlots[varID] = parts
655                 for _, slotID := range parts {
656                         state.slotVars[slotID] = VarID(varID)
657                 }
658                 *state.partsByVarOffset.(*partsByVarOffset) = partsByVarOffset{parts, state.slots}
659                 sort.Sort(state.partsByVarOffset)
660         }
661
662         state.initializeCache(f, len(state.varParts), len(state.slots))
663
664         for i, slot := range f.Names {
665                 if ir.IsSynthetic(slot.N) {
666                         continue
667                 }
668                 for _, value := range f.NamedValues[*slot] {
669                         state.valueNames[value.ID] = append(state.valueNames[value.ID], SlotID(i))
670                 }
671         }
672
673         blockLocs := state.liveness()
674         state.buildLocationLists(blockLocs)
675
676         // Populate "rval" with what we've computed.
677         rval.Slots = state.slots
678         rval.VarSlots = state.varSlots
679         rval.Vars = state.vars
680         rval.LocationLists = state.lists
681 }
682
683 // liveness walks the function in control flow order, calculating the start
684 // and end state of each block.
685 func (state *debugState) liveness() []*BlockDebug {
686         blockLocs := make([]*BlockDebug, state.f.NumBlocks())
687         counterTime := int32(1)
688
689         // Reverse postorder: visit a block after as many as possible of its
690         // predecessors have been visited.
691         po := state.f.Postorder()
692         converged := false
693
694         // The iteration rule is that by default, run until converged, but
695         // if a particular iteration count is specified, run that many
696         // iterations, no more, no less.  A count is specified as the
697         // thousands digit of the location lists debug flag,
698         // e.g. -d=locationlists=4000
699         keepGoing := func(k int) bool {
700                 if state.convergeCount == 0 {
701                         return !converged
702                 }
703                 return k < state.convergeCount
704         }
705         for k := 0; keepGoing(k); k++ {
706                 if state.loggingLevel > 0 {
707                         state.logf("Liveness pass %d\n", k)
708                 }
709                 converged = true
710                 for i := len(po) - 1; i >= 0; i-- {
711                         b := po[i]
712                         locs := blockLocs[b.ID]
713                         if locs == nil {
714                                 locs = state.allocBlock(b)
715                                 blockLocs[b.ID] = locs
716                         }
717
718                         // Build the starting state for the block from the final
719                         // state of its predecessors.
720                         startState, blockChanged := state.mergePredecessors(b, blockLocs, nil, false)
721                         locs.lastCheckedTime = counterTime
722                         counterTime++
723                         if state.loggingLevel > 1 {
724                                 state.logf("Processing %v, block changed %v, initial state:\n%v", b, blockChanged, state.stateString(state.currentState))
725                         }
726
727                         if blockChanged {
728                                 // If the start did not change, then the old endState is good
729                                 converged = false
730                                 changed := false
731                                 state.changedSlots.clear()
732
733                                 // Update locs/registers with the effects of each Value.
734                                 for _, v := range b.Values {
735                                         slots := state.valueNames[v.ID]
736
737                                         // Loads and stores inherit the names of their sources.
738                                         var source *Value
739                                         switch v.Op {
740                                         case OpStoreReg:
741                                                 source = v.Args[0]
742                                         case OpLoadReg:
743                                                 switch a := v.Args[0]; a.Op {
744                                                 case OpArg, OpPhi:
745                                                         source = a
746                                                 case OpStoreReg:
747                                                         source = a.Args[0]
748                                                 default:
749                                                         if state.loggingLevel > 1 {
750                                                                 state.logf("at %v: load with unexpected source op: %v (%v)\n", v, a.Op, a)
751                                                         }
752                                                 }
753                                         }
754                                         // Update valueNames with the source so that later steps
755                                         // don't need special handling.
756                                         if source != nil && k == 0 {
757                                                 // limit to k == 0 otherwise there are duplicates.
758                                                 slots = append(slots, state.valueNames[source.ID]...)
759                                                 state.valueNames[v.ID] = slots
760                                         }
761
762                                         reg, _ := state.f.getHome(v.ID).(*Register)
763                                         c := state.processValue(v, slots, reg)
764                                         changed = changed || c
765                                 }
766
767                                 if state.loggingLevel > 1 {
768                                         state.logf("Block %v done, locs:\n%v", b, state.stateString(state.currentState))
769                                 }
770
771                                 locs.relevant = locs.relevant || changed
772                                 if !changed {
773                                         locs.endState = startState
774                                 } else {
775                                         for _, id := range state.changedSlots.contents() {
776                                                 slotID := SlotID(id)
777                                                 slotLoc := state.currentState.slots[slotID]
778                                                 if slotLoc.absent() {
779                                                         startState.Delete(int32(slotID))
780                                                         continue
781                                                 }
782                                                 old := startState.Find(int32(slotID)) // do NOT replace existing values
783                                                 if oldLS, ok := old.(*liveSlot); !ok || oldLS.VarLoc != slotLoc {
784                                                         startState.Insert(int32(slotID),
785                                                                 &liveSlot{VarLoc: slotLoc})
786                                                 }
787                                         }
788                                         locs.endState = startState
789                                 }
790                                 locs.lastChangedTime = counterTime
791                         }
792                         counterTime++
793                 }
794         }
795         return blockLocs
796 }
797
798 // mergePredecessors takes the end state of each of b's predecessors and
799 // intersects them to form the starting state for b. It puts that state
800 // in blockLocs[b.ID].startState, and fills state.currentState with it.
801 // It returns the start state and whether this is changed from the
802 // previously approximated value of startState for this block.  After
803 // the first call, subsequent calls can only shrink startState.
804 //
805 // Passing forLocationLists=true enables additional side-effects that
806 // are necessary for building location lists but superfluous while still
807 // iterating to an answer.
808 //
809 // If previousBlock is non-nil, it registers changes vs. that block's
810 // end state in state.changedVars. Note that previousBlock will often
811 // not be a predecessor.
812 //
813 // Note that mergePredecessors behaves slightly differently between
814 // first and subsequent calls for a block.  For the first call, the
815 // starting state is approximated by taking the state from the
816 // predecessor whose state is smallest, and removing any elements not
817 // in all the other predecessors; this makes the smallest number of
818 // changes and shares the most state.  On subsequent calls the old
819 // value of startState is adjusted with new information; this is judged
820 // to do the least amount of extra work.
821 //
822 // To improve performance, each block's state information is marked with
823 // lastChanged and lastChecked "times" so unchanged predecessors can be
824 // skipped on after-the-first iterations.  Doing this allows extra
825 // iterations by the caller to be almost free.
826 //
827 // It is important to know that the set representation used for
828 // startState, endState, and merges can share data for two sets where
829 // one is a small delta from the other.  Doing this does require a
830 // little care in how sets are updated, both in mergePredecessors, and
831 // using its result.
832 func (state *debugState) mergePredecessors(b *Block, blockLocs []*BlockDebug, previousBlock *Block, forLocationLists bool) (abt.T, bool) {
833         // Filter out back branches.
834         var predsBuf [10]*Block
835
836         preds := predsBuf[:0]
837         locs := blockLocs[b.ID]
838
839         blockChanged := !locs.everProcessed // the first time it always changes.
840         updating := locs.everProcessed
841
842         // For the first merge, exclude predecessors that have not been seen yet.
843         // I.e., backedges.
844         for _, pred := range b.Preds {
845                 if bl := blockLocs[pred.b.ID]; bl != nil && bl.everProcessed {
846                         // crucially, a self-edge has bl != nil, but bl.everProcessed is false the first time.
847                         preds = append(preds, pred.b)
848                 }
849         }
850
851         locs.everProcessed = true
852
853         if state.loggingLevel > 1 {
854                 // The logf below would cause preds to be heap-allocated if
855                 // it were passed directly.
856                 preds2 := make([]*Block, len(preds))
857                 copy(preds2, preds)
858                 state.logf("Merging %v into %v (changed=%d, checked=%d)\n", preds2, b, locs.lastChangedTime, locs.lastCheckedTime)
859         }
860
861         state.changedVars.clear()
862
863         markChangedVars := func(slots, merged abt.T) {
864                 if !forLocationLists {
865                         return
866                 }
867                 // Fill changedVars with those that differ between the previous
868                 // block (in the emit order, not necessarily a flow predecessor)
869                 // and the start state for this block.
870                 for it := slots.Iterator(); !it.Done(); {
871                         k, v := it.Next()
872                         m := merged.Find(k)
873                         if m == nil || v.(*liveSlot).VarLoc != m.(*liveSlot).VarLoc {
874                                 state.changedVars.add(ID(state.slotVars[k]))
875                         }
876                 }
877         }
878
879         reset := func(ourStartState abt.T) {
880                 if !(forLocationLists || blockChanged) {
881                         // there is no change and this is not for location lists, do
882                         // not bother to reset currentState because it will not be
883                         // examined.
884                         return
885                 }
886                 state.currentState.reset(ourStartState)
887         }
888
889         // Zero predecessors
890         if len(preds) == 0 {
891                 if previousBlock != nil {
892                         state.f.Fatalf("Function %v, block %s with no predecessors is not first block, has previous %s", state.f, b.String(), previousBlock.String())
893                 }
894                 // startState is empty
895                 reset(abt.T{})
896                 return abt.T{}, blockChanged
897         }
898
899         // One predecessor
900         l0 := blockLocs[preds[0].ID]
901         p0 := l0.endState
902         if len(preds) == 1 {
903                 if previousBlock != nil && preds[0].ID != previousBlock.ID {
904                         // Change from previous block is its endState minus the predecessor's endState
905                         markChangedVars(blockLocs[previousBlock.ID].endState, p0)
906                 }
907                 locs.startState = p0
908                 blockChanged = blockChanged || l0.lastChangedTime > locs.lastCheckedTime
909                 reset(p0)
910                 return p0, blockChanged
911         }
912
913         // More than one predecessor
914
915         if updating {
916                 // After the first approximation, i.e., when updating, results
917                 // can only get smaller, because initially backedge
918                 // predecessors do not participate in the intersection.  This
919                 // means that for the update, given the prior approximation of
920                 // startState, there is no need to re-intersect with unchanged
921                 // blocks.  Therefore remove unchanged blocks from the
922                 // predecessor list.
923                 for i := len(preds) - 1; i >= 0; i-- {
924                         pred := preds[i]
925                         if blockLocs[pred.ID].lastChangedTime > locs.lastCheckedTime {
926                                 continue // keep this predecessor
927                         }
928                         preds[i] = preds[len(preds)-1]
929                         preds = preds[:len(preds)-1]
930                         if state.loggingLevel > 2 {
931                                 state.logf("Pruned b%d, lastChanged was %d but b%d lastChecked is %d\n", pred.ID, blockLocs[pred.ID].lastChangedTime, b.ID, locs.lastCheckedTime)
932                         }
933                 }
934                 // Check for an early out; this should always hit for the update
935                 // if there are no cycles.
936                 if len(preds) == 0 {
937                         blockChanged = false
938
939                         reset(locs.startState)
940                         if state.loggingLevel > 2 {
941                                 state.logf("Early out, no predecessors changed since last check\n")
942                         }
943                         if previousBlock != nil {
944                                 markChangedVars(blockLocs[previousBlock.ID].endState, locs.startState)
945                         }
946                         return locs.startState, blockChanged
947                 }
948         }
949
950         baseID := preds[0].ID
951         baseState := p0
952
953         // Choose the predecessor with the smallest endState for intersection work
954         for _, pred := range preds[1:] {
955                 if blockLocs[pred.ID].endState.Size() < baseState.Size() {
956                         baseState = blockLocs[pred.ID].endState
957                         baseID = pred.ID
958                 }
959         }
960
961         if state.loggingLevel > 2 {
962                 state.logf("Starting %v with state from b%v:\n%v", b, baseID, state.blockEndStateString(blockLocs[baseID]))
963                 for _, pred := range preds {
964                         if pred.ID == baseID {
965                                 continue
966                         }
967                         state.logf("Merging in state from %v:\n%v", pred, state.blockEndStateString(blockLocs[pred.ID]))
968                 }
969         }
970
971         state.currentState.reset(abt.T{})
972         // The normal logic of "reset" is incuded in the intersection loop below.
973
974         slotLocs := state.currentState.slots
975
976         // If this is the first call, do updates on the "baseState"; if this
977         // is a subsequent call, tweak the startState instead. Note that
978         // these "set" values are values; there are no side effects to
979         // other values as these are modified.
980         newState := baseState
981         if updating {
982                 newState = blockLocs[b.ID].startState
983         }
984
985         for it := newState.Iterator(); !it.Done(); {
986                 k, d := it.Next()
987                 thisSlot := d.(*liveSlot)
988                 x := thisSlot.VarLoc
989                 x0 := x // initial value in newState
990
991                 // Intersect this slot with the slot in all the predecessors
992                 for _, other := range preds {
993                         if !updating && other.ID == baseID {
994                                 continue
995                         }
996                         otherSlot := blockLocs[other.ID].endState.Find(k)
997                         if otherSlot == nil {
998                                 x = VarLoc{}
999                                 break
1000                         }
1001                         y := otherSlot.(*liveSlot).VarLoc
1002                         x = x.intersect(y)
1003                         if x.absent() {
1004                                 x = VarLoc{}
1005                                 break
1006                         }
1007                 }
1008
1009                 // Delete if necessary, but not otherwise (in order to maximize sharing).
1010                 if x.absent() {
1011                         if !x0.absent() {
1012                                 blockChanged = true
1013                                 newState.Delete(k)
1014                         }
1015                         slotLocs[k] = VarLoc{}
1016                         continue
1017                 }
1018                 if x != x0 {
1019                         blockChanged = true
1020                         newState.Insert(k, &liveSlot{VarLoc: x})
1021                 }
1022
1023                 slotLocs[k] = x
1024                 mask := uint64(x.Registers)
1025                 for {
1026                         if mask == 0 {
1027                                 break
1028                         }
1029                         reg := uint8(bits.TrailingZeros64(mask))
1030                         mask &^= 1 << reg
1031                         state.currentState.registers[reg] = append(state.currentState.registers[reg], SlotID(k))
1032                 }
1033         }
1034
1035         if previousBlock != nil {
1036                 markChangedVars(blockLocs[previousBlock.ID].endState, newState)
1037         }
1038         locs.startState = newState
1039         return newState, blockChanged
1040 }
1041
1042 // processValue updates locs and state.registerContents to reflect v, a
1043 // value with the names in vSlots and homed in vReg.  "v" becomes
1044 // visible after execution of the instructions evaluating it. It
1045 // returns which VarIDs were modified by the Value's execution.
1046 func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) bool {
1047         locs := state.currentState
1048         changed := false
1049         setSlot := func(slot SlotID, loc VarLoc) {
1050                 changed = true
1051                 state.changedVars.add(ID(state.slotVars[slot]))
1052                 state.changedSlots.add(ID(slot))
1053                 state.currentState.slots[slot] = loc
1054         }
1055
1056         // Handle any register clobbering. Call operations, for example,
1057         // clobber all registers even though they don't explicitly write to
1058         // them.
1059         clobbers := uint64(opcodeTable[v.Op].reg.clobbers)
1060         for {
1061                 if clobbers == 0 {
1062                         break
1063                 }
1064                 reg := uint8(bits.TrailingZeros64(clobbers))
1065                 clobbers &^= 1 << reg
1066
1067                 for _, slot := range locs.registers[reg] {
1068                         if state.loggingLevel > 1 {
1069                                 state.logf("at %v: %v clobbered out of %v\n", v, state.slots[slot], &state.registers[reg])
1070                         }
1071
1072                         last := locs.slots[slot]
1073                         if last.absent() {
1074                                 state.f.Fatalf("at %v: slot %v in register %v with no location entry", v, state.slots[slot], &state.registers[reg])
1075                                 continue
1076                         }
1077                         regs := last.Registers &^ (1 << reg)
1078                         setSlot(slot, VarLoc{regs, last.StackOffset})
1079                 }
1080
1081                 locs.registers[reg] = locs.registers[reg][:0]
1082         }
1083
1084         switch {
1085         case v.Op == OpVarDef:
1086                 n := v.Aux.(*ir.Name)
1087                 if ir.IsSynthetic(n) {
1088                         break
1089                 }
1090
1091                 slotID := state.varParts[n][0]
1092                 var stackOffset StackOffset
1093                 if v.Op == OpVarDef {
1094                         stackOffset = StackOffset(state.stackOffset(state.slots[slotID])<<1 | 1)
1095                 }
1096                 setSlot(slotID, VarLoc{0, stackOffset})
1097                 if state.loggingLevel > 1 {
1098                         if v.Op == OpVarDef {
1099                                 state.logf("at %v: stack-only var %v now live\n", v, state.slots[slotID])
1100                         } else {
1101                                 state.logf("at %v: stack-only var %v now dead\n", v, state.slots[slotID])
1102                         }
1103                 }
1104
1105         case v.Op == OpArg:
1106                 home := state.f.getHome(v.ID).(LocalSlot)
1107                 stackOffset := state.stackOffset(home)<<1 | 1
1108                 for _, slot := range vSlots {
1109                         if state.loggingLevel > 1 {
1110                                 state.logf("at %v: arg %v now on stack in location %v\n", v, state.slots[slot], home)
1111                                 if last := locs.slots[slot]; !last.absent() {
1112                                         state.logf("at %v: unexpected arg op on already-live slot %v\n", v, state.slots[slot])
1113                                 }
1114                         }
1115
1116                         setSlot(slot, VarLoc{0, StackOffset(stackOffset)})
1117                 }
1118
1119         case v.Op == OpStoreReg:
1120                 home := state.f.getHome(v.ID).(LocalSlot)
1121                 stackOffset := state.stackOffset(home)<<1 | 1
1122                 for _, slot := range vSlots {
1123                         last := locs.slots[slot]
1124                         if last.absent() {
1125                                 if state.loggingLevel > 1 {
1126                                         state.logf("at %v: unexpected spill of unnamed register %s\n", v, vReg)
1127                                 }
1128                                 break
1129                         }
1130
1131                         setSlot(slot, VarLoc{last.Registers, StackOffset(stackOffset)})
1132                         if state.loggingLevel > 1 {
1133                                 state.logf("at %v: %v spilled to stack location %v@%d\n", v, state.slots[slot], home, state.stackOffset(home))
1134                         }
1135                 }
1136
1137         case vReg != nil:
1138                 if state.loggingLevel > 1 {
1139                         newSlots := make([]bool, len(state.slots))
1140                         for _, slot := range vSlots {
1141                                 newSlots[slot] = true
1142                         }
1143
1144                         for _, slot := range locs.registers[vReg.num] {
1145                                 if !newSlots[slot] {
1146                                         state.logf("at %v: overwrote %v in register %v\n", v, state.slots[slot], vReg)
1147                                 }
1148                         }
1149                 }
1150
1151                 for _, slot := range locs.registers[vReg.num] {
1152                         last := locs.slots[slot]
1153                         setSlot(slot, VarLoc{last.Registers &^ (1 << uint8(vReg.num)), last.StackOffset})
1154                 }
1155                 locs.registers[vReg.num] = locs.registers[vReg.num][:0]
1156                 locs.registers[vReg.num] = append(locs.registers[vReg.num], vSlots...)
1157                 for _, slot := range vSlots {
1158                         if state.loggingLevel > 1 {
1159                                 state.logf("at %v: %v now in %s\n", v, state.slots[slot], vReg)
1160                         }
1161
1162                         last := locs.slots[slot]
1163                         setSlot(slot, VarLoc{1<<uint8(vReg.num) | last.Registers, last.StackOffset})
1164                 }
1165         }
1166         return changed
1167 }
1168
1169 // varOffset returns the offset of slot within the user variable it was
1170 // decomposed from. This has nothing to do with its stack offset.
1171 func varOffset(slot LocalSlot) int64 {
1172         offset := slot.Off
1173         s := &slot
1174         for ; s.SplitOf != nil; s = s.SplitOf {
1175                 offset += s.SplitOffset
1176         }
1177         return offset
1178 }
1179
1180 type partsByVarOffset struct {
1181         slotIDs []SlotID
1182         slots   []LocalSlot
1183 }
1184
1185 func (a partsByVarOffset) Len() int { return len(a.slotIDs) }
1186 func (a partsByVarOffset) Less(i, j int) bool {
1187         return varOffset(a.slots[a.slotIDs[i]]) < varOffset(a.slots[a.slotIDs[j]])
1188 }
1189 func (a partsByVarOffset) Swap(i, j int) { a.slotIDs[i], a.slotIDs[j] = a.slotIDs[j], a.slotIDs[i] }
1190
1191 // A pendingEntry represents the beginning of a location list entry, missing
1192 // only its end coordinate.
1193 type pendingEntry struct {
1194         present                bool
1195         startBlock, startValue ID
1196         // The location of each piece of the variable, in the same order as the
1197         // SlotIDs in varParts.
1198         pieces []VarLoc
1199 }
1200
1201 func (e *pendingEntry) clear() {
1202         e.present = false
1203         e.startBlock = 0
1204         e.startValue = 0
1205         for i := range e.pieces {
1206                 e.pieces[i] = VarLoc{}
1207         }
1208 }
1209
1210 // canMerge reports whether a new location description is a superset
1211 // of the (non-empty) pending location description, if so, the two
1212 // can be merged (i.e., pending is still a valid and useful location
1213 // description).
1214 func canMerge(pending, new VarLoc) bool {
1215         if pending.absent() && new.absent() {
1216                 return true
1217         }
1218         if pending.absent() || new.absent() {
1219                 return false
1220         }
1221         // pending is not absent, therefore it has either a stack mapping,
1222         // or registers, or both.
1223         if pending.onStack() && pending.StackOffset != new.StackOffset {
1224                 // if pending has a stack offset, then new must also, and it
1225                 // must be the same (StackOffset encodes onStack).
1226                 return false
1227         }
1228         if pending.Registers&new.Registers != pending.Registers {
1229                 // There is at least one register in pending not mentioned in new.
1230                 return false
1231         }
1232         return true
1233 }
1234
1235 // firstReg returns the first register in set that is present.
1236 func firstReg(set RegisterSet) uint8 {
1237         if set == 0 {
1238                 // This is wrong, but there seem to be some situations where we
1239                 // produce locations with no storage.
1240                 return 0
1241         }
1242         return uint8(bits.TrailingZeros64(uint64(set)))
1243 }
1244
1245 // buildLocationLists builds location lists for all the user variables
1246 // in state.f, using the information about block state in blockLocs.
1247 // The returned location lists are not fully complete. They are in
1248 // terms of SSA values rather than PCs, and have no base address/end
1249 // entries. They will be finished by PutLocationList.
1250 func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
1251         // Run through the function in program text order, building up location
1252         // lists as we go. The heavy lifting has mostly already been done.
1253
1254         var prevBlock *Block
1255         for _, b := range state.f.Blocks {
1256                 state.mergePredecessors(b, blockLocs, prevBlock, true)
1257
1258                 // Handle any differences among predecessor blocks and previous block (perhaps not a predecessor)
1259                 for _, varID := range state.changedVars.contents() {
1260                         state.updateVar(VarID(varID), b, BlockStart)
1261                 }
1262                 state.changedVars.clear()
1263
1264                 if !blockLocs[b.ID].relevant {
1265                         continue
1266                 }
1267
1268                 mustBeFirst := func(v *Value) bool {
1269                         return v.Op == OpPhi || v.Op.isLoweredGetClosurePtr() ||
1270                                 v.Op == OpArgIntReg || v.Op == OpArgFloatReg
1271                 }
1272
1273                 blockPrologComplete := func(v *Value) bool {
1274                         if b.ID != state.f.Entry.ID {
1275                                 return !opcodeTable[v.Op].zeroWidth
1276                         } else {
1277                                 return v.Op == OpInitMem
1278                         }
1279                 }
1280
1281                 // Examine the prolog portion of the block to process special
1282                 // zero-width ops such as Arg, Phi, LoweredGetClosurePtr (etc)
1283                 // whose lifetimes begin at the block starting point. In an
1284                 // entry block, allow for the possibility that we may see Arg
1285                 // ops that appear _after_ other non-zero-width operations.
1286                 // Example:
1287                 //
1288                 //   v33 = ArgIntReg <uintptr> {foo+0} [0] : AX (foo)
1289                 //   v34 = ArgIntReg <uintptr> {bar+0} [0] : BX (bar)
1290                 //   ...
1291                 //   v77 = StoreReg <unsafe.Pointer> v67 : ctx+8[unsafe.Pointer]
1292                 //   v78 = StoreReg <unsafe.Pointer> v68 : ctx[unsafe.Pointer]
1293                 //   v79 = Arg <*uint8> {args} : args[*uint8] (args[*uint8])
1294                 //   v80 = Arg <int> {args} [8] : args+8[int] (args+8[int])
1295                 //   ...
1296                 //   v1 = InitMem <mem>
1297                 //
1298                 // We can stop scanning the initial portion of the block when
1299                 // we either see the InitMem op (for entry blocks) or the
1300                 // first non-zero-width op (for other blocks).
1301                 for idx := 0; idx < len(b.Values); idx++ {
1302                         v := b.Values[idx]
1303                         if blockPrologComplete(v) {
1304                                 break
1305                         }
1306                         // Consider only "lifetime begins at block start" ops.
1307                         if !mustBeFirst(v) && v.Op != OpArg {
1308                                 continue
1309                         }
1310                         slots := state.valueNames[v.ID]
1311                         reg, _ := state.f.getHome(v.ID).(*Register)
1312                         changed := state.processValue(v, slots, reg) // changed == added to state.changedVars
1313                         if changed {
1314                                 for _, varID := range state.changedVars.contents() {
1315                                         state.updateVar(VarID(varID), v.Block, BlockStart)
1316                                 }
1317                                 state.changedVars.clear()
1318                         }
1319                 }
1320
1321                 // Now examine the block again, handling things other than the
1322                 // "begins at block start" lifetimes.
1323                 zeroWidthPending := false
1324                 prologComplete := false
1325                 // expect to see values in pattern (apc)* (zerowidth|real)*
1326                 for _, v := range b.Values {
1327                         if blockPrologComplete(v) {
1328                                 prologComplete = true
1329                         }
1330                         slots := state.valueNames[v.ID]
1331                         reg, _ := state.f.getHome(v.ID).(*Register)
1332                         changed := state.processValue(v, slots, reg) // changed == added to state.changedVars
1333
1334                         if opcodeTable[v.Op].zeroWidth {
1335                                 if prologComplete && mustBeFirst(v) {
1336                                         panic(fmt.Errorf("Unexpected placement of op '%s' appearing after non-pseudo-op at beginning of block %s in %s\n%s", v.LongString(), b, b.Func.Name, b.Func))
1337                                 }
1338                                 if changed {
1339                                         if mustBeFirst(v) || v.Op == OpArg {
1340                                                 // already taken care of above
1341                                                 continue
1342                                         }
1343                                         zeroWidthPending = true
1344                                 }
1345                                 continue
1346                         }
1347                         if !changed && !zeroWidthPending {
1348                                 continue
1349                         }
1350
1351                         // Not zero-width; i.e., a "real" instruction.
1352                         zeroWidthPending = false
1353                         for _, varID := range state.changedVars.contents() {
1354                                 state.updateVar(VarID(varID), v.Block, v)
1355                         }
1356                         state.changedVars.clear()
1357                 }
1358                 for _, varID := range state.changedVars.contents() {
1359                         state.updateVar(VarID(varID), b, BlockEnd)
1360                 }
1361
1362                 prevBlock = b
1363         }
1364
1365         if state.loggingLevel > 0 {
1366                 state.logf("location lists:\n")
1367         }
1368
1369         // Flush any leftover entries live at the end of the last block.
1370         for varID := range state.lists {
1371                 state.writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, FuncEnd.ID)
1372                 list := state.lists[varID]
1373                 if state.loggingLevel > 0 {
1374                         if len(list) == 0 {
1375                                 state.logf("\t%v : empty list\n", state.vars[varID])
1376                         } else {
1377                                 state.logf("\t%v : %q\n", state.vars[varID], hex.EncodeToString(state.lists[varID]))
1378                         }
1379                 }
1380         }
1381 }
1382
1383 // updateVar updates the pending location list entry for varID to
1384 // reflect the new locations in curLoc, beginning at v in block b.
1385 // v may be one of the special values indicating block start or end.
1386 func (state *debugState) updateVar(varID VarID, b *Block, v *Value) {
1387         curLoc := state.currentState.slots
1388         // Assemble the location list entry with whatever's live.
1389         empty := true
1390         for _, slotID := range state.varSlots[varID] {
1391                 if !curLoc[slotID].absent() {
1392                         empty = false
1393                         break
1394                 }
1395         }
1396         pending := &state.pendingEntries[varID]
1397         if empty {
1398                 state.writePendingEntry(varID, b.ID, v.ID)
1399                 pending.clear()
1400                 return
1401         }
1402
1403         // Extend the previous entry if possible.
1404         if pending.present {
1405                 merge := true
1406                 for i, slotID := range state.varSlots[varID] {
1407                         if !canMerge(pending.pieces[i], curLoc[slotID]) {
1408                                 merge = false
1409                                 break
1410                         }
1411                 }
1412                 if merge {
1413                         return
1414                 }
1415         }
1416
1417         state.writePendingEntry(varID, b.ID, v.ID)
1418         pending.present = true
1419         pending.startBlock = b.ID
1420         pending.startValue = v.ID
1421         for i, slot := range state.varSlots[varID] {
1422                 pending.pieces[i] = curLoc[slot]
1423         }
1424 }
1425
1426 // writePendingEntry writes out the pending entry for varID, if any,
1427 // terminated at endBlock/Value.
1428 func (state *debugState) writePendingEntry(varID VarID, endBlock, endValue ID) {
1429         pending := state.pendingEntries[varID]
1430         if !pending.present {
1431                 return
1432         }
1433
1434         // Pack the start/end coordinates into the start/end addresses
1435         // of the entry, for decoding by PutLocationList.
1436         start, startOK := encodeValue(state.ctxt, pending.startBlock, pending.startValue)
1437         end, endOK := encodeValue(state.ctxt, endBlock, endValue)
1438         if !startOK || !endOK {
1439                 // If someone writes a function that uses >65K values,
1440                 // they get incomplete debug info on 32-bit platforms.
1441                 return
1442         }
1443         if start == end {
1444                 if state.loggingLevel > 1 {
1445                         // Printf not logf so not gated by GOSSAFUNC; this should fire very rarely.
1446                         // TODO this fires a lot, need to figure out why.
1447                         state.logf("Skipping empty location list for %v in %s\n", state.vars[varID], state.f.Name)
1448                 }
1449                 return
1450         }
1451
1452         list := state.lists[varID]
1453         list = appendPtr(state.ctxt, list, start)
1454         list = appendPtr(state.ctxt, list, end)
1455         // Where to write the length of the location description once
1456         // we know how big it is.
1457         sizeIdx := len(list)
1458         list = list[:len(list)+2]
1459
1460         if state.loggingLevel > 1 {
1461                 var partStrs []string
1462                 for i, slot := range state.varSlots[varID] {
1463                         partStrs = append(partStrs, fmt.Sprintf("%v@%v", state.slots[slot], state.LocString(pending.pieces[i])))
1464                 }
1465                 state.logf("Add entry for %v: \tb%vv%v-b%vv%v = \t%v\n", state.vars[varID], pending.startBlock, pending.startValue, endBlock, endValue, strings.Join(partStrs, " "))
1466         }
1467
1468         for i, slotID := range state.varSlots[varID] {
1469                 loc := pending.pieces[i]
1470                 slot := state.slots[slotID]
1471
1472                 if !loc.absent() {
1473                         if loc.onStack() {
1474                                 if loc.stackOffsetValue() == 0 {
1475                                         list = append(list, dwarf.DW_OP_call_frame_cfa)
1476                                 } else {
1477                                         list = append(list, dwarf.DW_OP_fbreg)
1478                                         list = dwarf.AppendSleb128(list, int64(loc.stackOffsetValue()))
1479                                 }
1480                         } else {
1481                                 regnum := state.ctxt.Arch.DWARFRegisters[state.registers[firstReg(loc.Registers)].ObjNum()]
1482                                 if regnum < 32 {
1483                                         list = append(list, dwarf.DW_OP_reg0+byte(regnum))
1484                                 } else {
1485                                         list = append(list, dwarf.DW_OP_regx)
1486                                         list = dwarf.AppendUleb128(list, uint64(regnum))
1487                                 }
1488                         }
1489                 }
1490
1491                 if len(state.varSlots[varID]) > 1 {
1492                         list = append(list, dwarf.DW_OP_piece)
1493                         list = dwarf.AppendUleb128(list, uint64(slot.Type.Size()))
1494                 }
1495         }
1496         state.ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
1497         state.lists[varID] = list
1498 }
1499
1500 // PutLocationList adds list (a location list in its intermediate representation) to listSym.
1501 func (debugInfo *FuncDebug) PutLocationList(list []byte, ctxt *obj.Link, listSym, startPC *obj.LSym) {
1502         getPC := debugInfo.GetPC
1503
1504         if ctxt.UseBASEntries {
1505                 listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, ^0)
1506                 listSym.WriteAddr(ctxt, listSym.Size, ctxt.Arch.PtrSize, startPC, 0)
1507         }
1508
1509         // Re-read list, translating its address from block/value ID to PC.
1510         for i := 0; i < len(list); {
1511                 begin := getPC(decodeValue(ctxt, readPtr(ctxt, list[i:])))
1512                 end := getPC(decodeValue(ctxt, readPtr(ctxt, list[i+ctxt.Arch.PtrSize:])))
1513
1514                 // Horrible hack. If a range contains only zero-width
1515                 // instructions, e.g. an Arg, and it's at the beginning of the
1516                 // function, this would be indistinguishable from an
1517                 // end entry. Fudge it.
1518                 if begin == 0 && end == 0 {
1519                         end = 1
1520                 }
1521
1522                 if ctxt.UseBASEntries {
1523                         listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(begin))
1524                         listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, int64(end))
1525                 } else {
1526                         listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(begin))
1527                         listSym.WriteCURelativeAddr(ctxt, listSym.Size, startPC, int64(end))
1528                 }
1529
1530                 i += 2 * ctxt.Arch.PtrSize
1531                 datalen := 2 + int(ctxt.Arch.ByteOrder.Uint16(list[i:]))
1532                 listSym.WriteBytes(ctxt, listSym.Size, list[i:i+datalen]) // copy datalen and location encoding
1533                 i += datalen
1534         }
1535
1536         // Location list contents, now with real PCs.
1537         // End entry.
1538         listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)
1539         listSym.WriteInt(ctxt, listSym.Size, ctxt.Arch.PtrSize, 0)
1540 }
1541
1542 // Pack a value and block ID into an address-sized uint, returning
1543 // encoded value and boolean indicating whether the encoding succeeded.
1544 // For 32-bit architectures the process may fail for very large
1545 // procedures(the theory being that it's ok to have degraded debug
1546 // quality in this case).
1547 func encodeValue(ctxt *obj.Link, b, v ID) (uint64, bool) {
1548         if ctxt.Arch.PtrSize == 8 {
1549                 result := uint64(b)<<32 | uint64(uint32(v))
1550                 //ctxt.Logf("b %#x (%d) v %#x (%d) -> %#x\n", b, b, v, v, result)
1551                 return result, true
1552         }
1553         if ctxt.Arch.PtrSize != 4 {
1554                 panic("unexpected pointer size")
1555         }
1556         if ID(int16(b)) != b || ID(int16(v)) != v {
1557                 return 0, false
1558         }
1559         return uint64(b)<<16 | uint64(uint16(v)), true
1560 }
1561
1562 // Unpack a value and block ID encoded by encodeValue.
1563 func decodeValue(ctxt *obj.Link, word uint64) (ID, ID) {
1564         if ctxt.Arch.PtrSize == 8 {
1565                 b, v := ID(word>>32), ID(word)
1566                 //ctxt.Logf("%#x -> b %#x (%d) v %#x (%d)\n", word, b, b, v, v)
1567                 return b, v
1568         }
1569         if ctxt.Arch.PtrSize != 4 {
1570                 panic("unexpected pointer size")
1571         }
1572         return ID(word >> 16), ID(int16(word))
1573 }
1574
1575 // Append a pointer-sized uint to buf.
1576 func appendPtr(ctxt *obj.Link, buf []byte, word uint64) []byte {
1577         if cap(buf) < len(buf)+20 {
1578                 b := make([]byte, len(buf), 20+cap(buf)*2)
1579                 copy(b, buf)
1580                 buf = b
1581         }
1582         writeAt := len(buf)
1583         buf = buf[0 : len(buf)+ctxt.Arch.PtrSize]
1584         writePtr(ctxt, buf[writeAt:], word)
1585         return buf
1586 }
1587
1588 // Write a pointer-sized uint to the beginning of buf.
1589 func writePtr(ctxt *obj.Link, buf []byte, word uint64) {
1590         switch ctxt.Arch.PtrSize {
1591         case 4:
1592                 ctxt.Arch.ByteOrder.PutUint32(buf, uint32(word))
1593         case 8:
1594                 ctxt.Arch.ByteOrder.PutUint64(buf, word)
1595         default:
1596                 panic("unexpected pointer size")
1597         }
1598
1599 }
1600
1601 // Read a pointer-sized uint from the beginning of buf.
1602 func readPtr(ctxt *obj.Link, buf []byte) uint64 {
1603         switch ctxt.Arch.PtrSize {
1604         case 4:
1605                 return uint64(ctxt.Arch.ByteOrder.Uint32(buf))
1606         case 8:
1607                 return ctxt.Arch.ByteOrder.Uint64(buf)
1608         default:
1609                 panic("unexpected pointer size")
1610         }
1611
1612 }
1613
1614 // setupLocList creates the initial portion of a location list for a
1615 // user variable. It emits the encoded start/end of the range and a
1616 // placeholder for the size. Return value is the new list plus the
1617 // slot in the list holding the size (to be updated later).
1618 func setupLocList(ctxt *obj.Link, f *Func, list []byte, st, en ID) ([]byte, int) {
1619         start, startOK := encodeValue(ctxt, f.Entry.ID, st)
1620         end, endOK := encodeValue(ctxt, f.Entry.ID, en)
1621         if !startOK || !endOK {
1622                 // This could happen if someone writes a function that uses
1623                 // >65K values on a 32-bit platform. Hopefully a degraded debugging
1624                 // experience is ok in that case.
1625                 return nil, 0
1626         }
1627         list = appendPtr(ctxt, list, start)
1628         list = appendPtr(ctxt, list, end)
1629
1630         // Where to write the length of the location description once
1631         // we know how big it is.
1632         sizeIdx := len(list)
1633         list = list[:len(list)+2]
1634         return list, sizeIdx
1635 }
1636
1637 // locatePrologEnd walks the entry block of a function with incoming
1638 // register arguments and locates the last instruction in the prolog
1639 // that spills a register arg. It returns the ID of that instruction
1640 // Example:
1641 //
1642 //      b1:
1643 //          v3 = ArgIntReg <int> {p1+0} [0] : AX
1644 //          ... more arg regs ..
1645 //          v4 = ArgFloatReg <float32> {f1+0} [0] : X0
1646 //          v52 = MOVQstore <mem> {p1} v2 v3 v1
1647 //          ... more stores ...
1648 //          v68 = MOVSSstore <mem> {f4} v2 v67 v66
1649 //          v38 = MOVQstoreconst <mem> {blob} [val=0,off=0] v2 v32
1650 //
1651 // Important: locatePrologEnd is expected to work properly only with
1652 // optimization turned off (e.g. "-N"). If optimization is enabled
1653 // we can't be assured of finding all input arguments spilled in the
1654 // entry block prolog.
1655 func locatePrologEnd(f *Func) ID {
1656
1657         // returns true if this instruction looks like it moves an ABI
1658         // register to the stack, along with the value being stored.
1659         isRegMoveLike := func(v *Value) (bool, ID) {
1660                 n, ok := v.Aux.(*ir.Name)
1661                 var r ID
1662                 if !ok || n.Class != ir.PPARAM {
1663                         return false, r
1664                 }
1665                 regInputs, memInputs, spInputs := 0, 0, 0
1666                 for _, a := range v.Args {
1667                         if a.Op == OpArgIntReg || a.Op == OpArgFloatReg {
1668                                 regInputs++
1669                                 r = a.ID
1670                         } else if a.Type.IsMemory() {
1671                                 memInputs++
1672                         } else if a.Op == OpSP {
1673                                 spInputs++
1674                         } else {
1675                                 return false, r
1676                         }
1677                 }
1678                 return v.Type.IsMemory() && memInputs == 1 &&
1679                         regInputs == 1 && spInputs == 1, r
1680         }
1681
1682         // OpArg*Reg values we've seen so far on our forward walk,
1683         // for which we have not yet seen a corresponding spill.
1684         regArgs := make([]ID, 0, 32)
1685
1686         // removeReg tries to remove a value from regArgs, returning true
1687         // if found and removed, or false otherwise.
1688         removeReg := func(r ID) bool {
1689                 for i := 0; i < len(regArgs); i++ {
1690                         if regArgs[i] == r {
1691                                 regArgs = append(regArgs[:i], regArgs[i+1:]...)
1692                                 return true
1693                         }
1694                 }
1695                 return false
1696         }
1697
1698         // Walk forwards through the block. When we see OpArg*Reg, record
1699         // the value it produces in the regArgs list. When see a store that uses
1700         // the value, remove the entry. When we hit the last store (use)
1701         // then we've arrived at the end of the prolog.
1702         for k, v := range f.Entry.Values {
1703                 if v.Op == OpArgIntReg || v.Op == OpArgFloatReg {
1704                         regArgs = append(regArgs, v.ID)
1705                         continue
1706                 }
1707                 if ok, r := isRegMoveLike(v); ok {
1708                         if removed := removeReg(r); removed {
1709                                 if len(regArgs) == 0 {
1710                                         // Found our last spill; return the value after
1711                                         // it. Note that it is possible that this spill is
1712                                         // the last instruction in the block. If so, then
1713                                         // return the "end of block" sentinel.
1714                                         if k < len(f.Entry.Values)-1 {
1715                                                 return f.Entry.Values[k+1].ID
1716                                         }
1717                                         return BlockEnd.ID
1718                                 }
1719                         }
1720                 }
1721                 if v.Op.IsCall() {
1722                         // if we hit a call, we've gone too far.
1723                         return v.ID
1724                 }
1725         }
1726         // nothing found
1727         return ID(-1)
1728 }
1729
1730 // isNamedRegParam returns true if the param corresponding to "p"
1731 // is a named, non-blank input parameter assigned to one or more
1732 // registers.
1733 func isNamedRegParam(p abi.ABIParamAssignment) bool {
1734         if p.Name == nil {
1735                 return false
1736         }
1737         n := p.Name.(*ir.Name)
1738         if n.Sym() == nil || n.Sym().IsBlank() {
1739                 return false
1740         }
1741         if len(p.Registers) == 0 {
1742                 return false
1743         }
1744         return true
1745 }
1746
1747 // BuildFuncDebugNoOptimized populates a FuncDebug object "rval" with
1748 // entries corresponding to the register-resident input parameters for
1749 // the function "f"; it is used when we are compiling without
1750 // optimization but the register ABI is enabled. For each reg param,
1751 // it constructs a 2-element location list: the first element holds
1752 // the input register, and the second element holds the stack location
1753 // of the param (the assumption being that when optimization is off,
1754 // each input param reg will be spilled in the prolog.
1755 func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32, rval *FuncDebug) {
1756
1757         pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())
1758
1759         // Look to see if we have any named register-promoted parameters.
1760         // If there are none, bail early and let the caller sort things
1761         // out for the remainder of the params/locals.
1762         numRegParams := 0
1763         for _, inp := range pri.InParams() {
1764                 if isNamedRegParam(inp) {
1765                         numRegParams++
1766                 }
1767         }
1768         if numRegParams == 0 {
1769                 return
1770         }
1771
1772         state := debugState{f: f}
1773
1774         if loggingEnabled {
1775                 state.logf("generating -N reg param loc lists for func %q\n", f.Name)
1776         }
1777
1778         // Allocate location lists.
1779         rval.LocationLists = make([][]byte, numRegParams)
1780
1781         // Locate the value corresponding to the last spill of
1782         // an input register.
1783         afterPrologVal := locatePrologEnd(f)
1784
1785         // Walk the input params again and process the register-resident elements.
1786         pidx := 0
1787         for _, inp := range pri.InParams() {
1788                 if !isNamedRegParam(inp) {
1789                         // will be sorted out elsewhere
1790                         continue
1791                 }
1792
1793                 n := inp.Name.(*ir.Name)
1794                 sl := LocalSlot{N: n, Type: inp.Type, Off: 0}
1795                 rval.Vars = append(rval.Vars, n)
1796                 rval.Slots = append(rval.Slots, sl)
1797                 slid := len(rval.VarSlots)
1798                 rval.VarSlots = append(rval.VarSlots, []SlotID{SlotID(slid)})
1799
1800                 if afterPrologVal == ID(-1) {
1801                         // This can happen for degenerate functions with infinite
1802                         // loops such as that in issue 45948. In such cases, leave
1803                         // the var/slot set up for the param, but don't try to
1804                         // emit a location list.
1805                         if loggingEnabled {
1806                                 state.logf("locatePrologEnd failed, skipping %v\n", n)
1807                         }
1808                         pidx++
1809                         continue
1810                 }
1811
1812                 // Param is arriving in one or more registers. We need a 2-element
1813                 // location expression for it. First entry in location list
1814                 // will correspond to lifetime in input registers.
1815                 list, sizeIdx := setupLocList(ctxt, f, rval.LocationLists[pidx],
1816                         BlockStart.ID, afterPrologVal)
1817                 if list == nil {
1818                         pidx++
1819                         continue
1820                 }
1821                 if loggingEnabled {
1822                         state.logf("param %v:\n  [<entry>, %d]:\n", n, afterPrologVal)
1823                 }
1824                 rtypes, _ := inp.RegisterTypesAndOffsets()
1825                 padding := make([]uint64, 0, 32)
1826                 padding = inp.ComputePadding(padding)
1827                 for k, r := range inp.Registers {
1828                         reg := ObjRegForAbiReg(r, f.Config)
1829                         dwreg := ctxt.Arch.DWARFRegisters[reg]
1830                         if dwreg < 32 {
1831                                 list = append(list, dwarf.DW_OP_reg0+byte(dwreg))
1832                         } else {
1833                                 list = append(list, dwarf.DW_OP_regx)
1834                                 list = dwarf.AppendUleb128(list, uint64(dwreg))
1835                         }
1836                         if loggingEnabled {
1837                                 state.logf("    piece %d -> dwreg %d", k, dwreg)
1838                         }
1839                         if len(inp.Registers) > 1 {
1840                                 list = append(list, dwarf.DW_OP_piece)
1841                                 ts := rtypes[k].Size()
1842                                 list = dwarf.AppendUleb128(list, uint64(ts))
1843                                 if padding[k] > 0 {
1844                                         if loggingEnabled {
1845                                                 state.logf(" [pad %d bytes]", padding[k])
1846                                         }
1847                                         list = append(list, dwarf.DW_OP_piece)
1848                                         list = dwarf.AppendUleb128(list, padding[k])
1849                                 }
1850                         }
1851                         if loggingEnabled {
1852                                 state.logf("\n")
1853                         }
1854                 }
1855                 // fill in length of location expression element
1856                 ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
1857
1858                 // Second entry in the location list will be the stack home
1859                 // of the param, once it has been spilled.  Emit that now.
1860                 list, sizeIdx = setupLocList(ctxt, f, list,
1861                         afterPrologVal, FuncEnd.ID)
1862                 if list == nil {
1863                         pidx++
1864                         continue
1865                 }
1866                 soff := stackOffset(sl)
1867                 if soff == 0 {
1868                         list = append(list, dwarf.DW_OP_call_frame_cfa)
1869                 } else {
1870                         list = append(list, dwarf.DW_OP_fbreg)
1871                         list = dwarf.AppendSleb128(list, int64(soff))
1872                 }
1873                 if loggingEnabled {
1874                         state.logf("  [%d, <end>): stackOffset=%d\n", afterPrologVal, soff)
1875                 }
1876
1877                 // fill in size
1878                 ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
1879
1880                 rval.LocationLists[pidx] = list
1881                 pidx++
1882         }
1883 }