github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/compile/internal/ssa/debug.go (about)

     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  	"github.com/shogo82148/std/cmd/compile/internal/abt"
     9  	"github.com/shogo82148/std/cmd/compile/internal/ir"
    10  	"github.com/shogo82148/std/cmd/internal/obj"
    11  )
    12  
    13  type SlotID int32
    14  type VarID int32
    15  
    16  // A FuncDebug contains all the debug information for the variables in a
    17  // function. Variables are identified by their LocalSlot, which may be
    18  // the result of decomposing a larger variable.
    19  type FuncDebug struct {
    20  	// Slots is all the slots used in the debug info, indexed by their SlotID.
    21  	Slots []LocalSlot
    22  	// The user variables, indexed by VarID.
    23  	Vars []*ir.Name
    24  	// The slots that make up each variable, indexed by VarID.
    25  	VarSlots [][]SlotID
    26  	// The location list data, indexed by VarID. Must be processed by PutLocationList.
    27  	LocationLists [][]byte
    28  	// Register-resident output parameters for the function. This is filled in at
    29  	// SSA generation time.
    30  	RegOutputParams []*ir.Name
    31  	// Variable declarations that were removed during optimization
    32  	OptDcl []*ir.Name
    33  
    34  	// Filled in by the user. Translates Block and Value ID to PC.
    35  	//
    36  	// NOTE: block is only used if value is BlockStart.ID or BlockEnd.ID.
    37  	// Otherwise, it is ignored.
    38  	GetPC func(block, value ID) int64
    39  }
    40  
    41  type BlockDebug struct {
    42  	// State at the start and end of the block. These are initialized,
    43  	// and updated from new information that flows on back edges.
    44  	startState, endState abt.T
    45  	// Use these to avoid excess work in the merge. If none of the
    46  	// predecessors has changed since the last check, the old answer is
    47  	// still good.
    48  	lastCheckedTime, lastChangedTime int32
    49  	// Whether the block had any changes to user variables at all.
    50  	relevant bool
    51  	// false until the block has been processed at least once. This
    52  	// affects how the merge is done; the goal is to maximize sharing
    53  	// and avoid allocation.
    54  	everProcessed bool
    55  }
    56  
    57  // StackOffset encodes whether a value is on the stack and if so, where.
    58  // It is a 31-bit integer followed by a presence flag at the low-order
    59  // bit.
    60  type StackOffset int32
    61  
    62  // A VarLoc describes the storage for part of a user variable.
    63  type VarLoc struct {
    64  	// The registers this variable is available in. There can be more than
    65  	// one in various situations, e.g. it's being moved between registers.
    66  	Registers RegisterSet
    67  
    68  	StackOffset
    69  }
    70  
    71  var BlockStart = &Value{
    72  	ID:  -10000,
    73  	Op:  OpInvalid,
    74  	Aux: StringToAux("BlockStart"),
    75  }
    76  
    77  var BlockEnd = &Value{
    78  	ID:  -20000,
    79  	Op:  OpInvalid,
    80  	Aux: StringToAux("BlockEnd"),
    81  }
    82  
    83  var FuncEnd = &Value{
    84  	ID:  -30000,
    85  	Op:  OpInvalid,
    86  	Aux: StringToAux("FuncEnd"),
    87  }
    88  
    89  // RegisterSet is a bitmap of registers, indexed by Register.num.
    90  type RegisterSet uint64
    91  
    92  type SlKeyIdx uint32
    93  
    94  // PopulateABIInRegArgOps examines the entry block of the function
    95  // and looks for incoming parameters that have missing or partial
    96  // OpArg{Int,Float}Reg values, inserting additional values in
    97  // cases where they are missing. Example:
    98  //
    99  //	func foo(s string, used int, notused int) int {
   100  //	  return len(s) + used
   101  //	}
   102  //
   103  // In the function above, the incoming parameter "used" is fully live,
   104  // "notused" is not live, and "s" is partially live (only the length
   105  // field of the string is used). At the point where debug value
   106  // analysis runs, we might expect to see an entry block with:
   107  //
   108  //	b1:
   109  //	  v4 = ArgIntReg <uintptr> {s+8} [0] : BX
   110  //	  v5 = ArgIntReg <int> {used} [0] : CX
   111  //
   112  // While this is an accurate picture of the live incoming params,
   113  // we also want to have debug locations for non-live params (or
   114  // their non-live pieces), e.g. something like
   115  //
   116  //	b1:
   117  //	  v9 = ArgIntReg <*uint8> {s+0} [0] : AX
   118  //	  v4 = ArgIntReg <uintptr> {s+8} [0] : BX
   119  //	  v5 = ArgIntReg <int> {used} [0] : CX
   120  //	  v10 = ArgIntReg <int> {unused} [0] : DI
   121  //
   122  // This function examines the live OpArg{Int,Float}Reg values and
   123  // synthesizes new (dead) values for the non-live params or the
   124  // non-live pieces of partially live params.
   125  func PopulateABIInRegArgOps(f *Func)
   126  
   127  // BuildFuncDebug debug information for f, placing the results
   128  // in "rval". f must be fully processed, so that each Value is where it
   129  // will be when machine code is emitted.
   130  func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func(LocalSlot) int32, rval *FuncDebug)
   131  
   132  // PutLocationList adds list (a location list in its intermediate representation) to listSym.
   133  func (debugInfo *FuncDebug) PutLocationList(list []byte, ctxt *obj.Link, listSym, startPC *obj.LSym)
   134  
   135  // BuildFuncDebugNoOptimized populates a FuncDebug object "rval" with
   136  // entries corresponding to the register-resident input parameters for
   137  // the function "f"; it is used when we are compiling without
   138  // optimization but the register ABI is enabled. For each reg param,
   139  // it constructs a 2-element location list: the first element holds
   140  // the input register, and the second element holds the stack location
   141  // of the param (the assumption being that when optimization is off,
   142  // each input param reg will be spilled in the prolog).
   143  func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset func(LocalSlot) int32, rval *FuncDebug)