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