1*f6aab3d8Srobert //===-- TraceHTR.h --------------------------------------------------------===// 2*f6aab3d8Srobert // 3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information. 5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*f6aab3d8Srobert // 7*f6aab3d8Srobert //===----------------------------------------------------------------------===// 8*f6aab3d8Srobert 9*f6aab3d8Srobert #ifndef LLDB_TARGET_TRACE_HTR_H 10*f6aab3d8Srobert #define LLDB_TARGET_TRACE_HTR_H 11*f6aab3d8Srobert 12*f6aab3d8Srobert #include "lldb/Target/Thread.h" 13*f6aab3d8Srobert #include "lldb/Target/Trace.h" 14*f6aab3d8Srobert 15*f6aab3d8Srobert #include <optional> 16*f6aab3d8Srobert #include <unordered_map> 17*f6aab3d8Srobert #include <unordered_set> 18*f6aab3d8Srobert 19*f6aab3d8Srobert namespace lldb_private { 20*f6aab3d8Srobert 21*f6aab3d8Srobert /// Metadata associated with an HTR block 22*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 23*f6aab3d8Srobert class HTRBlockMetadata { 24*f6aab3d8Srobert public: 25*f6aab3d8Srobert /// Constructor for a block's metadata. 26*f6aab3d8Srobert /// 27*f6aab3d8Srobert /// \param[in] first_instruction_load_address 28*f6aab3d8Srobert /// The load address of the block's first instruction. 29*f6aab3d8Srobert /// 30*f6aab3d8Srobert /// \param[in] num_instructions 31*f6aab3d8Srobert /// The total number of instructions in the block. 32*f6aab3d8Srobert /// 33*f6aab3d8Srobert /// \param[in] func_calls 34*f6aab3d8Srobert /// The map of a function name to the number of times it is called from 35*f6aab3d8Srobert /// the block. HTRBlockMetadata(lldb::addr_t first_instruction_load_address,size_t num_instructions,llvm::DenseMap<ConstString,size_t> && func_calls)36*f6aab3d8Srobert HTRBlockMetadata(lldb::addr_t first_instruction_load_address, 37*f6aab3d8Srobert size_t num_instructions, 38*f6aab3d8Srobert llvm::DenseMap<ConstString, size_t> &&func_calls) 39*f6aab3d8Srobert : m_first_instruction_load_address(first_instruction_load_address), 40*f6aab3d8Srobert m_num_instructions(num_instructions), m_func_calls(func_calls) {} 41*f6aab3d8Srobert 42*f6aab3d8Srobert /// Merge two \a HTRBlockMetadata in place. 43*f6aab3d8Srobert /// 44*f6aab3d8Srobert /// \param[in][out] merged_metadata 45*f6aab3d8Srobert /// Metadata that metadata_to_merge will be merged into. 46*f6aab3d8Srobert /// 47*f6aab3d8Srobert /// \param[in] metadata_to_merge 48*f6aab3d8Srobert /// Metadata to merge into merged_metadata. 49*f6aab3d8Srobert static void MergeMetadata(HTRBlockMetadata &merged_metadata, 50*f6aab3d8Srobert HTRBlockMetadata const &metadata_to_merge); 51*f6aab3d8Srobert /// Get the number of instructions in the block. 52*f6aab3d8Srobert /// 53*f6aab3d8Srobert /// \return 54*f6aab3d8Srobert /// The number of instructions in the block. 55*f6aab3d8Srobert size_t GetNumInstructions() const; 56*f6aab3d8Srobert 57*f6aab3d8Srobert /// Get the name of the most frequently called function from the block. 58*f6aab3d8Srobert /// 59*f6aab3d8Srobert /// \return 60*f6aab3d8Srobert /// The name of the function that is called the most from this block or 61*f6aab3d8Srobert /// std::nullopt if no function is called from this block. 62*f6aab3d8Srobert std::optional<llvm::StringRef> GetMostFrequentlyCalledFunction() const; 63*f6aab3d8Srobert 64*f6aab3d8Srobert /// Get the load address of the first instruction in the block. 65*f6aab3d8Srobert /// 66*f6aab3d8Srobert /// \return 67*f6aab3d8Srobert /// The load address of the first instruction in the block. 68*f6aab3d8Srobert lldb::addr_t GetFirstInstructionLoadAddress() const; 69*f6aab3d8Srobert 70*f6aab3d8Srobert /// Get the function calls map for the block. 71*f6aab3d8Srobert /// Function calls are identified in the instruction layer by finding 'call' 72*f6aab3d8Srobert /// instructions and determining the function they are calling. As these 73*f6aab3d8Srobert /// instructions are merged into blocks, we merge these different function 74*f6aab3d8Srobert /// calls into a single map containing the function names to the number of 75*f6aab3d8Srobert /// times it is called from this block. 76*f6aab3d8Srobert /// 77*f6aab3d8Srobert /// \return 78*f6aab3d8Srobert /// The mapping of function name to the number of times it is called from 79*f6aab3d8Srobert /// this block. 80*f6aab3d8Srobert llvm::DenseMap<ConstString, size_t> const &GetFunctionCalls() const; 81*f6aab3d8Srobert 82*f6aab3d8Srobert private: 83*f6aab3d8Srobert lldb::addr_t m_first_instruction_load_address; 84*f6aab3d8Srobert size_t m_num_instructions; 85*f6aab3d8Srobert llvm::DenseMap<ConstString, size_t> m_func_calls; 86*f6aab3d8Srobert }; 87*f6aab3d8Srobert 88*f6aab3d8Srobert /// Block structure representing a sequence of trace "units" (ie instructions). 89*f6aab3d8Srobert /// Sequences of blocks are merged to create a new, single block 90*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 91*f6aab3d8Srobert class HTRBlock { 92*f6aab3d8Srobert public: 93*f6aab3d8Srobert /// Constructor for a block of an HTR layer. 94*f6aab3d8Srobert /// 95*f6aab3d8Srobert /// \param[in] offset 96*f6aab3d8Srobert /// The offset of the start of this block in the previous layer. 97*f6aab3d8Srobert /// 98*f6aab3d8Srobert /// \param[in] size 99*f6aab3d8Srobert /// Number of blocks/instructions that make up this block in the previous 100*f6aab3d8Srobert /// layer. 101*f6aab3d8Srobert /// 102*f6aab3d8Srobert /// \param[in] metadata 103*f6aab3d8Srobert /// General metadata for this block. HTRBlock(size_t offset,size_t size,HTRBlockMetadata metadata)104*f6aab3d8Srobert HTRBlock(size_t offset, size_t size, HTRBlockMetadata metadata) 105*f6aab3d8Srobert : m_offset(offset), m_size(size), m_metadata(metadata) {} 106*f6aab3d8Srobert 107*f6aab3d8Srobert /// Get the offset of the start of this block in the previous layer. 108*f6aab3d8Srobert /// 109*f6aab3d8Srobert /// \return 110*f6aab3d8Srobert /// The offset of the block. 111*f6aab3d8Srobert size_t GetOffset() const; 112*f6aab3d8Srobert 113*f6aab3d8Srobert /// Get the number of blocks/instructions that make up this block in the 114*f6aab3d8Srobert /// previous layer. 115*f6aab3d8Srobert /// 116*f6aab3d8Srobert /// \return 117*f6aab3d8Srobert /// The size of the block. 118*f6aab3d8Srobert size_t GetSize() const; 119*f6aab3d8Srobert 120*f6aab3d8Srobert /// Get the metadata for this block. 121*f6aab3d8Srobert /// 122*f6aab3d8Srobert /// \return 123*f6aab3d8Srobert /// The metadata of the block. 124*f6aab3d8Srobert HTRBlockMetadata const &GetMetadata() const; 125*f6aab3d8Srobert 126*f6aab3d8Srobert private: 127*f6aab3d8Srobert /// Offset in the previous layer 128*f6aab3d8Srobert size_t m_offset; 129*f6aab3d8Srobert /// Number of blocks/instructions that make up this block in the previous 130*f6aab3d8Srobert /// layer 131*f6aab3d8Srobert size_t m_size; 132*f6aab3d8Srobert /// General metadata for this block 133*f6aab3d8Srobert HTRBlockMetadata m_metadata; 134*f6aab3d8Srobert }; 135*f6aab3d8Srobert 136*f6aab3d8Srobert /// HTR layer interface 137*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 138*f6aab3d8Srobert class IHTRLayer { 139*f6aab3d8Srobert public: 140*f6aab3d8Srobert /// Construct new HTR layer. 141*f6aab3d8Srobert // 142*f6aab3d8Srobert /// \param[in] id 143*f6aab3d8Srobert /// The layer's id. IHTRLayer(size_t id)144*f6aab3d8Srobert IHTRLayer(size_t id) : m_layer_id(id) {} 145*f6aab3d8Srobert 146*f6aab3d8Srobert /// Get the ID of the layer. 147*f6aab3d8Srobert /// 148*f6aab3d8Srobert /// \return 149*f6aab3d8Srobert /// The layer ID of this layer. 150*f6aab3d8Srobert size_t GetLayerId() const; 151*f6aab3d8Srobert 152*f6aab3d8Srobert /// Get the metadata of a unit (instruction or block) in the layer. 153*f6aab3d8Srobert /// 154*f6aab3d8Srobert /// \param[in] index 155*f6aab3d8Srobert /// The position of the unit in the layer. 156*f6aab3d8Srobert /// 157*f6aab3d8Srobert /// \return 158*f6aab3d8Srobert /// The metadata of the unit in the layer. 159*f6aab3d8Srobert virtual HTRBlockMetadata GetMetadataByIndex(size_t index) const = 0; 160*f6aab3d8Srobert 161*f6aab3d8Srobert /// Get the total number of units (instruction or block) in this layer. 162*f6aab3d8Srobert /// 163*f6aab3d8Srobert /// \return 164*f6aab3d8Srobert /// The total number of units in the layer. 165*f6aab3d8Srobert virtual size_t GetNumUnits() const = 0; 166*f6aab3d8Srobert 167*f6aab3d8Srobert /// Creates a new block from the result of merging a contiguous sequence of 168*f6aab3d8Srobert /// "units" (instructions or blocks depending on layer type) in this layer 169*f6aab3d8Srobert /// This allows the implementation class to decide how to store/generate this 170*f6aab3d8Srobert /// metadata. For example, in the case of the instruction layer we want to 171*f6aab3d8Srobert /// lazily generate this metadata instead of storing it for each instruction. 172*f6aab3d8Srobert /// 173*f6aab3d8Srobert /// \param[in] start_unit_index 174*f6aab3d8Srobert /// The index of the first unit to be merged. 175*f6aab3d8Srobert /// 176*f6aab3d8Srobert /// \param[in] num_units 177*f6aab3d8Srobert /// The number of units to be merged. Must be >= 1, since merging 0 blocks 178*f6aab3d8Srobert /// does not make sense. 179*f6aab3d8Srobert /// 180*f6aab3d8Srobert /// \return 181*f6aab3d8Srobert /// A new block instance representing the merge of the specified units. 182*f6aab3d8Srobert HTRBlock MergeUnits(size_t start_unit_index, size_t num_units); 183*f6aab3d8Srobert 184*f6aab3d8Srobert virtual ~IHTRLayer() = default; 185*f6aab3d8Srobert 186*f6aab3d8Srobert protected: 187*f6aab3d8Srobert /// ID of the layer. 188*f6aab3d8Srobert size_t m_layer_id; 189*f6aab3d8Srobert }; 190*f6aab3d8Srobert 191*f6aab3d8Srobert /// "Base" layer of HTR representing the dynamic instructions of the trace. 192*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 193*f6aab3d8Srobert class HTRInstructionLayer : public IHTRLayer { 194*f6aab3d8Srobert public: 195*f6aab3d8Srobert /// Construct new instruction layer. 196*f6aab3d8Srobert // 197*f6aab3d8Srobert /// \param[in] id 198*f6aab3d8Srobert /// The layer's id. HTRInstructionLayer(size_t id)199*f6aab3d8Srobert HTRInstructionLayer(size_t id) : IHTRLayer(id) {} 200*f6aab3d8Srobert 201*f6aab3d8Srobert size_t GetNumUnits() const override; 202*f6aab3d8Srobert 203*f6aab3d8Srobert HTRBlockMetadata GetMetadataByIndex(size_t index) const override; 204*f6aab3d8Srobert 205*f6aab3d8Srobert /// Get the dynamic instruction trace. 206*f6aab3d8Srobert /// 207*f6aab3d8Srobert /// \return 208*f6aab3d8Srobert /// The dynamic instruction trace. 209*f6aab3d8Srobert llvm::ArrayRef<lldb::addr_t> GetInstructionTrace() const; 210*f6aab3d8Srobert 211*f6aab3d8Srobert /// Add metadata for a 'call' instruction of the trace. 212*f6aab3d8Srobert /// 213*f6aab3d8Srobert /// \param[in] load_addr 214*f6aab3d8Srobert /// The load address of the 'call' instruction. 215*f6aab3d8Srobert /// 216*f6aab3d8Srobert /// \param[in] func_name 217*f6aab3d8Srobert /// The name of the function the 'call' instruction is calling if it can 218*f6aab3d8Srobert /// be determined, None otherwise. 219*f6aab3d8Srobert void AddCallInstructionMetadata(lldb::addr_t load_addr, 220*f6aab3d8Srobert std::optional<ConstString> func_name); 221*f6aab3d8Srobert 222*f6aab3d8Srobert /// Append the load address of an instruction to the dynamic instruction 223*f6aab3d8Srobert /// trace. 224*f6aab3d8Srobert /// 225*f6aab3d8Srobert /// \param[in] load_addr 226*f6aab3d8Srobert /// The load address of the instruction. 227*f6aab3d8Srobert void AppendInstruction(lldb::addr_t load_addr); 228*f6aab3d8Srobert 229*f6aab3d8Srobert private: 230*f6aab3d8Srobert // Dynamic instructions of trace are stored in chronological order. 231*f6aab3d8Srobert std::vector<lldb::addr_t> m_instruction_trace; 232*f6aab3d8Srobert // Only store metadata for instructions of interest (call instructions) 233*f6aab3d8Srobert // If we stored metadata for each instruction this would be wasteful since 234*f6aab3d8Srobert // most instructions don't contain useful metadata 235*f6aab3d8Srobert 236*f6aab3d8Srobert // This map contains the load address of all the call instructions. 237*f6aab3d8Srobert // load address maps to the name of the function it calls (std::nullopt if 238*f6aab3d8Srobert // function name can't be determined) 239*f6aab3d8Srobert std::unordered_map<lldb::addr_t, std::optional<ConstString>> m_call_isns; 240*f6aab3d8Srobert }; 241*f6aab3d8Srobert 242*f6aab3d8Srobert /// HTR layer composed of blocks of the trace. 243*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 244*f6aab3d8Srobert class HTRBlockLayer : public IHTRLayer { 245*f6aab3d8Srobert public: 246*f6aab3d8Srobert /// Construct new block layer. 247*f6aab3d8Srobert // 248*f6aab3d8Srobert /// \param[in] id 249*f6aab3d8Srobert /// The layer's id. HTRBlockLayer(size_t id)250*f6aab3d8Srobert HTRBlockLayer(size_t id) : IHTRLayer(id) {} 251*f6aab3d8Srobert 252*f6aab3d8Srobert size_t GetNumUnits() const override; 253*f6aab3d8Srobert 254*f6aab3d8Srobert HTRBlockMetadata GetMetadataByIndex(size_t index) const override; 255*f6aab3d8Srobert 256*f6aab3d8Srobert /// Get an \a HTRBlock from its block id. 257*f6aab3d8Srobert /// 258*f6aab3d8Srobert /// \param[in] block_id 259*f6aab3d8Srobert /// The id of the block to retrieve. 260*f6aab3d8Srobert /// 261*f6aab3d8Srobert /// \return 262*f6aab3d8Srobert /// The \a HTRBlock with the specified id, nullptr if no there is no block 263*f6aab3d8Srobert /// in the layer with the specified block id. 264*f6aab3d8Srobert HTRBlock const *GetBlockById(size_t block_id) const; 265*f6aab3d8Srobert 266*f6aab3d8Srobert /// Get the block ID trace for this layer. 267*f6aab3d8Srobert /// This block ID trace stores the block ID of each block that occured in the 268*f6aab3d8Srobert /// trace and the block defs map maps block ID to the corresponding \a 269*f6aab3d8Srobert /// HTRBlock. 270*f6aab3d8Srobert /// 271*f6aab3d8Srobert /// \return 272*f6aab3d8Srobert /// The block ID trace for this layer. 273*f6aab3d8Srobert llvm::ArrayRef<size_t> GetBlockIdTrace() const; 274*f6aab3d8Srobert 275*f6aab3d8Srobert /// Appends a new block to the layer. 276*f6aab3d8Srobert /// 277*f6aab3d8Srobert /// \param[in] block_id 278*f6aab3d8Srobert /// The block id of the new block. 279*f6aab3d8Srobert /// 280*f6aab3d8Srobert /// \param[in] block 281*f6aab3d8Srobert /// The new \a HTRBlock to be appended to the layer. This block is moved 282*f6aab3d8Srobert /// into the layer. 283*f6aab3d8Srobert void AppendNewBlock(size_t block_id, HTRBlock &&block); 284*f6aab3d8Srobert 285*f6aab3d8Srobert /// Appends a repeated block to the layer. 286*f6aab3d8Srobert /// 287*f6aab3d8Srobert /// \param[in] block_id 288*f6aab3d8Srobert /// The block id of the repeated block. 289*f6aab3d8Srobert void AppendRepeatedBlock(size_t block_id); 290*f6aab3d8Srobert 291*f6aab3d8Srobert private: 292*f6aab3d8Srobert /// Maps a unique Block ID to the corresponding HTRBlock 293*f6aab3d8Srobert std::unordered_map<size_t, HTRBlock> m_block_defs; 294*f6aab3d8Srobert /// Reduce memory footprint by just storing a trace of block IDs and use 295*f6aab3d8Srobert /// m_block_defs to map a block_id to its corresponding HTRBlock 296*f6aab3d8Srobert std::vector<size_t> m_block_id_trace; 297*f6aab3d8Srobert }; 298*f6aab3d8Srobert 299*f6aab3d8Srobert typedef std::unique_ptr<lldb_private::HTRBlockLayer> HTRBlockLayerUP; 300*f6aab3d8Srobert typedef std::unique_ptr<lldb_private::HTRInstructionLayer> 301*f6aab3d8Srobert HTRInstructionLayerUP; 302*f6aab3d8Srobert 303*f6aab3d8Srobert /// Top-level HTR class 304*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 305*f6aab3d8Srobert class TraceHTR { 306*f6aab3d8Srobert 307*f6aab3d8Srobert public: 308*f6aab3d8Srobert /// Constructor for a trace's HTR. 309*f6aab3d8Srobert /// 310*f6aab3d8Srobert /// \param[in] thread 311*f6aab3d8Srobert /// The thread the trace belongs to. 312*f6aab3d8Srobert /// 313*f6aab3d8Srobert /// \param[in] cursor 314*f6aab3d8Srobert /// The trace cursor that gives access to the trace's contents. 315*f6aab3d8Srobert TraceHTR(Thread &thread, TraceCursor &cursor); 316*f6aab3d8Srobert 317*f6aab3d8Srobert /// Executes passes on the HTR layers until no further 318*f6aab3d8Srobert /// summarization/compression is achieved 319*f6aab3d8Srobert void ExecutePasses(); 320*f6aab3d8Srobert 321*f6aab3d8Srobert /// Export HTR layers to the specified format and outfile. 322*f6aab3d8Srobert /// 323*f6aab3d8Srobert /// \param[in] outfile 324*f6aab3d8Srobert /// The file that the exported HTR data will be written to. 325*f6aab3d8Srobert /// 326*f6aab3d8Srobert /// \return 327*f6aab3d8Srobert /// Success if the export is successful, Error otherwise. 328*f6aab3d8Srobert llvm::Error Export(std::string outfile); 329*f6aab3d8Srobert 330*f6aab3d8Srobert /// Get the block layers of this HTR. 331*f6aab3d8Srobert /// 332*f6aab3d8Srobert /// \return 333*f6aab3d8Srobert /// The block layers of this HTR. 334*f6aab3d8Srobert llvm::ArrayRef<HTRBlockLayerUP> GetBlockLayers() const; 335*f6aab3d8Srobert 336*f6aab3d8Srobert /// Get the instruction layer of this HTR. 337*f6aab3d8Srobert /// 338*f6aab3d8Srobert /// \return 339*f6aab3d8Srobert /// The instruction layer of this HTR. 340*f6aab3d8Srobert HTRInstructionLayer const &GetInstructionLayer() const; 341*f6aab3d8Srobert 342*f6aab3d8Srobert /// Add a new block layer to this HTR. 343*f6aab3d8Srobert /// 344*f6aab3d8Srobert /// \param[in] 345*f6aab3d8Srobert /// The new block layer to be added. 346*f6aab3d8Srobert void AddNewBlockLayer(HTRBlockLayerUP &&block_layer); 347*f6aab3d8Srobert 348*f6aab3d8Srobert private: 349*f6aab3d8Srobert // There is a single instruction layer per HTR 350*f6aab3d8Srobert HTRInstructionLayerUP m_instruction_layer_up; 351*f6aab3d8Srobert // There are one or more block layers per HTR 352*f6aab3d8Srobert std::vector<HTRBlockLayerUP> m_block_layer_ups; 353*f6aab3d8Srobert }; 354*f6aab3d8Srobert 355*f6aab3d8Srobert // Serialization functions for exporting HTR to Chrome Trace Format 356*f6aab3d8Srobert llvm::json::Value toJSON(const TraceHTR &htr); 357*f6aab3d8Srobert llvm::json::Value toJSON(const HTRBlock &block); 358*f6aab3d8Srobert llvm::json::Value toJSON(const HTRBlockMetadata &metadata); 359*f6aab3d8Srobert 360*f6aab3d8Srobert /// The HTR passes are defined below: 361*f6aab3d8Srobert 362*f6aab3d8Srobert /// Creates a new layer by merging the "basic super blocks" in the current layer 363*f6aab3d8Srobert /// 364*f6aab3d8Srobert /// A "basic super block" is the longest sequence of blocks that always occur in 365*f6aab3d8Srobert /// the same order. (The concept is akin to “Basic Block" in compiler theory, 366*f6aab3d8Srobert /// but refers to dynamic occurrences rather than CFG nodes) 367*f6aab3d8Srobert /// 368*f6aab3d8Srobert /// Procedure to find all basic super blocks: 369*f6aab3d8Srobert // 370*f6aab3d8Srobert /// - For each block, compute the number of distinct predecessor and 371*f6aab3d8Srobert /// successor blocks. 372*f6aab3d8Srobert /// Predecessor - the block that occurs directly before (to the left of) 373*f6aab3d8Srobert /// the current block Successor - the block that occurs directly after 374*f6aab3d8Srobert /// (to the right of) the current block 375*f6aab3d8Srobert /// - A block with more than one distinct successor is always the start of a 376*f6aab3d8Srobert /// super block, the super block will continue until the next block with 377*f6aab3d8Srobert /// more than one distinct predecessor or successor. 378*f6aab3d8Srobert /// 379*f6aab3d8Srobert /// The implementation makes use of two terms - 'heads' and 'tails' known as 380*f6aab3d8Srobert /// the 'endpoints' of a basic super block: 381*f6aab3d8Srobert /// A 'head' is defined to be a block in the trace that doesn't have a 382*f6aab3d8Srobert /// unique predecessor 383*f6aab3d8Srobert /// A 'tail' is defined to be a block in the trace that doesn't have a 384*f6aab3d8Srobert /// unique successor 385*f6aab3d8Srobert /// 386*f6aab3d8Srobert /// A basic super block is defined to be a sequence of blocks between two 387*f6aab3d8Srobert /// endpoints 388*f6aab3d8Srobert /// 389*f6aab3d8Srobert /// A head represents the start of the next group, so the current group 390*f6aab3d8Srobert /// ends at the block preceding the head and the next group begins with 391*f6aab3d8Srobert /// this head block 392*f6aab3d8Srobert /// 393*f6aab3d8Srobert /// A tail represents the end of the current group, so the current group 394*f6aab3d8Srobert /// ends with the tail block and the next group begins with the 395*f6aab3d8Srobert /// following block. 396*f6aab3d8Srobert /// 397*f6aab3d8Srobert /// See lldb/docs/htr.rst for comprehensive HTR documentation 398*f6aab3d8Srobert /// 399*f6aab3d8Srobert /// \param[in] layer 400*f6aab3d8Srobert /// The layer to execute the pass on. 401*f6aab3d8Srobert /// 402*f6aab3d8Srobert /// \return 403*f6aab3d8Srobert /// A new layer instance representing the merge of blocks in the 404*f6aab3d8Srobert /// previous layer 405*f6aab3d8Srobert HTRBlockLayerUP BasicSuperBlockMerge(IHTRLayer &layer); 406*f6aab3d8Srobert 407*f6aab3d8Srobert } // namespace lldb_private 408*f6aab3d8Srobert 409*f6aab3d8Srobert #endif // LLDB_TARGET_TRACE_HTR_H 410