175dfa58eSStephen Tozer //=====-- DebugProgramInstruction.cpp - Implement DbgRecords/DbgMarkers --====// 2f1b0a544SJeremy Morse // 3f1b0a544SJeremy Morse // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f1b0a544SJeremy Morse // See https://llvm.org/LICENSE.txt for license information. 5f1b0a544SJeremy Morse // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f1b0a544SJeremy Morse // 7f1b0a544SJeremy Morse //===----------------------------------------------------------------------===// 8f1b0a544SJeremy Morse 9b90cba10SJeremy Morse #include "llvm/IR/DebugInfoMetadata.h" 10f1b0a544SJeremy Morse #include "llvm/IR/DebugProgramInstruction.h" 11f1b0a544SJeremy Morse #include "llvm/IR/DIBuilder.h" 12f1b0a544SJeremy Morse #include "llvm/IR/IntrinsicInst.h" 13f1b0a544SJeremy Morse 14f1b0a544SJeremy Morse namespace llvm { 15f1b0a544SJeremy Morse 16b3c2c5a8SStephen Tozer template <typename T> 17b3c2c5a8SStephen Tozer DbgRecordParamRef<T>::DbgRecordParamRef(const T *Param) 18b3c2c5a8SStephen Tozer : Ref(const_cast<T *>(Param)) {} 19b3c2c5a8SStephen Tozer template <typename T> 20b3c2c5a8SStephen Tozer DbgRecordParamRef<T>::DbgRecordParamRef(const MDNode *Param) 21b3c2c5a8SStephen Tozer : Ref(const_cast<MDNode *>(Param)) {} 22b3c2c5a8SStephen Tozer 23b3c2c5a8SStephen Tozer template <typename T> T *DbgRecordParamRef<T>::get() const { 24b3c2c5a8SStephen Tozer return cast<T>(Ref); 25b3c2c5a8SStephen Tozer } 26b3c2c5a8SStephen Tozer 27b3c2c5a8SStephen Tozer template class DbgRecordParamRef<DIExpression>; 28b3c2c5a8SStephen Tozer template class DbgRecordParamRef<DILabel>; 29b3c2c5a8SStephen Tozer template class DbgRecordParamRef<DILocalVariable>; 30b3c2c5a8SStephen Tozer 31ffd08c77SStephen Tozer DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI) 32ababa964SOrlando Cazalet-Hyams : DbgRecord(ValueKind, DVI->getDebugLoc()), 33ababa964SOrlando Cazalet-Hyams DebugValueUser({DVI->getRawLocation(), nullptr, nullptr}), 34d499df02SStephen Tozer Variable(DVI->getVariable()), Expression(DVI->getExpression()), 35b3c2c5a8SStephen Tozer AddressExpression() { 36f1b0a544SJeremy Morse switch (DVI->getIntrinsicID()) { 37f1b0a544SJeremy Morse case Intrinsic::dbg_value: 38f1b0a544SJeremy Morse Type = LocationType::Value; 39f1b0a544SJeremy Morse break; 40f1b0a544SJeremy Morse case Intrinsic::dbg_declare: 41f1b0a544SJeremy Morse Type = LocationType::Declare; 42f1b0a544SJeremy Morse break; 43d499df02SStephen Tozer case Intrinsic::dbg_assign: { 44d499df02SStephen Tozer Type = LocationType::Assign; 45d499df02SStephen Tozer const DbgAssignIntrinsic *Assign = 46d499df02SStephen Tozer static_cast<const DbgAssignIntrinsic *>(DVI); 47d499df02SStephen Tozer resetDebugValue(1, Assign->getRawAddress()); 48d499df02SStephen Tozer AddressExpression = Assign->getAddressExpression(); 49d499df02SStephen Tozer setAssignId(Assign->getAssignID()); 50d499df02SStephen Tozer break; 51d499df02SStephen Tozer } 52f1b0a544SJeremy Morse default: 53f1b0a544SJeremy Morse llvm_unreachable( 54ffd08c77SStephen Tozer "Trying to create a DbgVariableRecord with an invalid intrinsic type!"); 55f1b0a544SJeremy Morse } 56f1b0a544SJeremy Morse } 57f1b0a544SJeremy Morse 58ffd08c77SStephen Tozer DbgVariableRecord::DbgVariableRecord(const DbgVariableRecord &DVR) 59ffd08c77SStephen Tozer : DbgRecord(ValueKind, DVR.getDebugLoc()), DebugValueUser(DVR.DebugValues), 60ffd08c77SStephen Tozer Type(DVR.getType()), Variable(DVR.getVariable()), 61ffd08c77SStephen Tozer Expression(DVR.getExpression()), 62ffd08c77SStephen Tozer AddressExpression(DVR.AddressExpression) {} 63f1b0a544SJeremy Morse 64ffd08c77SStephen Tozer DbgVariableRecord::DbgVariableRecord(Metadata *Location, DILocalVariable *DV, 65ffd08c77SStephen Tozer DIExpression *Expr, const DILocation *DI, 66ffd08c77SStephen Tozer LocationType Type) 67ababa964SOrlando Cazalet-Hyams : DbgRecord(ValueKind, DI), DebugValueUser({Location, nullptr, nullptr}), 68ababa964SOrlando Cazalet-Hyams Type(Type), Variable(DV), Expression(Expr) {} 69d499df02SStephen Tozer 70ffd08c77SStephen Tozer DbgVariableRecord::DbgVariableRecord(Metadata *Value, DILocalVariable *Variable, 71ffd08c77SStephen Tozer DIExpression *Expression, 72ffd08c77SStephen Tozer DIAssignID *AssignID, Metadata *Address, 73ffd08c77SStephen Tozer DIExpression *AddressExpression, 74d499df02SStephen Tozer const DILocation *DI) 75ababa964SOrlando Cazalet-Hyams : DbgRecord(ValueKind, DI), DebugValueUser({Value, Address, AssignID}), 76ababa964SOrlando Cazalet-Hyams Type(LocationType::Assign), Variable(Variable), Expression(Expression), 77ababa964SOrlando Cazalet-Hyams AddressExpression(AddressExpression) {} 78f1b0a544SJeremy Morse 79ababa964SOrlando Cazalet-Hyams void DbgRecord::deleteRecord() { 80ababa964SOrlando Cazalet-Hyams switch (RecordKind) { 81ababa964SOrlando Cazalet-Hyams case ValueKind: 82ffd08c77SStephen Tozer delete cast<DbgVariableRecord>(this); 834a23ab43SOrlando Cazalet-Hyams return; 8420434bf3SOrlando Cazalet-Hyams case LabelKind: 85bdc77d1eSStephen Tozer delete cast<DbgLabelRecord>(this); 8620434bf3SOrlando Cazalet-Hyams return; 87ababa964SOrlando Cazalet-Hyams } 884a23ab43SOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 89ababa964SOrlando Cazalet-Hyams } 90ababa964SOrlando Cazalet-Hyams 91ababa964SOrlando Cazalet-Hyams void DbgRecord::print(raw_ostream &O, bool IsForDebug) const { 92ababa964SOrlando Cazalet-Hyams switch (RecordKind) { 93ababa964SOrlando Cazalet-Hyams case ValueKind: 94ffd08c77SStephen Tozer cast<DbgVariableRecord>(this)->print(O, IsForDebug); 954a23ab43SOrlando Cazalet-Hyams return; 9620434bf3SOrlando Cazalet-Hyams case LabelKind: 97bdc77d1eSStephen Tozer cast<DbgLabelRecord>(this)->print(O, IsForDebug); 9820434bf3SOrlando Cazalet-Hyams return; 99ababa964SOrlando Cazalet-Hyams }; 1004a23ab43SOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 101ababa964SOrlando Cazalet-Hyams } 102ababa964SOrlando Cazalet-Hyams 103ababa964SOrlando Cazalet-Hyams void DbgRecord::print(raw_ostream &O, ModuleSlotTracker &MST, 104ababa964SOrlando Cazalet-Hyams bool IsForDebug) const { 105ababa964SOrlando Cazalet-Hyams switch (RecordKind) { 106ababa964SOrlando Cazalet-Hyams case ValueKind: 107ffd08c77SStephen Tozer cast<DbgVariableRecord>(this)->print(O, MST, IsForDebug); 1084a23ab43SOrlando Cazalet-Hyams return; 10920434bf3SOrlando Cazalet-Hyams case LabelKind: 110bdc77d1eSStephen Tozer cast<DbgLabelRecord>(this)->print(O, MST, IsForDebug); 11120434bf3SOrlando Cazalet-Hyams return; 112ababa964SOrlando Cazalet-Hyams }; 1134a23ab43SOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 114ababa964SOrlando Cazalet-Hyams } 115ababa964SOrlando Cazalet-Hyams 116ababa964SOrlando Cazalet-Hyams bool DbgRecord::isIdenticalToWhenDefined(const DbgRecord &R) const { 117ababa964SOrlando Cazalet-Hyams if (RecordKind != R.RecordKind) 118ababa964SOrlando Cazalet-Hyams return false; 119ababa964SOrlando Cazalet-Hyams switch (RecordKind) { 120ababa964SOrlando Cazalet-Hyams case ValueKind: 121ffd08c77SStephen Tozer return cast<DbgVariableRecord>(this)->isIdenticalToWhenDefined( 122ffd08c77SStephen Tozer *cast<DbgVariableRecord>(&R)); 12320434bf3SOrlando Cazalet-Hyams case LabelKind: 124bdc77d1eSStephen Tozer return cast<DbgLabelRecord>(this)->getLabel() == 125bdc77d1eSStephen Tozer cast<DbgLabelRecord>(R).getLabel(); 126ababa964SOrlando Cazalet-Hyams }; 1274a23ab43SOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 128ababa964SOrlando Cazalet-Hyams } 129ababa964SOrlando Cazalet-Hyams 130ababa964SOrlando Cazalet-Hyams bool DbgRecord::isEquivalentTo(const DbgRecord &R) const { 13120434bf3SOrlando Cazalet-Hyams return getDebugLoc() == R.getDebugLoc() && isIdenticalToWhenDefined(R); 132ababa964SOrlando Cazalet-Hyams } 133f1b0a544SJeremy Morse 1343356818eSOrlando Cazalet-Hyams DbgInfoIntrinsic * 1353356818eSOrlando Cazalet-Hyams DbgRecord::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { 1363356818eSOrlando Cazalet-Hyams switch (RecordKind) { 1373356818eSOrlando Cazalet-Hyams case ValueKind: 138ffd08c77SStephen Tozer return cast<DbgVariableRecord>(this)->createDebugIntrinsic(M, InsertBefore); 1393356818eSOrlando Cazalet-Hyams case LabelKind: 140bdc77d1eSStephen Tozer return cast<DbgLabelRecord>(this)->createDebugIntrinsic(M, InsertBefore); 1413356818eSOrlando Cazalet-Hyams }; 1423356818eSOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 1433356818eSOrlando Cazalet-Hyams } 1443356818eSOrlando Cazalet-Hyams 145bdc77d1eSStephen Tozer DbgLabelRecord::DbgLabelRecord(MDNode *Label, MDNode *DL) 146464d9d96SStephen Tozer : DbgRecord(LabelKind, DebugLoc(DL)), Label(Label) { 147464d9d96SStephen Tozer assert(Label && "Unexpected nullptr"); 148464d9d96SStephen Tozer assert((isa<DILabel>(Label) || Label->isTemporary()) && 149464d9d96SStephen Tozer "Label type must be or resolve to a DILabel"); 150464d9d96SStephen Tozer } 151bdc77d1eSStephen Tozer DbgLabelRecord::DbgLabelRecord(DILabel *Label, DebugLoc DL) 152b3c2c5a8SStephen Tozer : DbgRecord(LabelKind, DL), Label(Label) { 153b3c2c5a8SStephen Tozer assert(Label && "Unexpected nullptr"); 154b3c2c5a8SStephen Tozer } 155b3c2c5a8SStephen Tozer 156bdc77d1eSStephen Tozer DbgLabelRecord *DbgLabelRecord::createUnresolvedDbgLabelRecord(MDNode *Label, 157bdc77d1eSStephen Tozer MDNode *DL) { 158bdc77d1eSStephen Tozer return new DbgLabelRecord(Label, DL); 159464d9d96SStephen Tozer } 160464d9d96SStephen Tozer 161ffd08c77SStephen Tozer DbgVariableRecord::DbgVariableRecord(DbgVariableRecord::LocationType Type, 162ffd08c77SStephen Tozer Metadata *Val, MDNode *Variable, 163ffd08c77SStephen Tozer MDNode *Expression, MDNode *AssignID, 164ffd08c77SStephen Tozer Metadata *Address, 165464d9d96SStephen Tozer MDNode *AddressExpression, MDNode *DI) 166464d9d96SStephen Tozer : DbgRecord(ValueKind, DebugLoc(DI)), 167464d9d96SStephen Tozer DebugValueUser({Val, Address, AssignID}), Type(Type), Variable(Variable), 168464d9d96SStephen Tozer Expression(Expression), AddressExpression(AddressExpression) {} 169464d9d96SStephen Tozer 170ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::createUnresolvedDbgVariableRecord( 171ffd08c77SStephen Tozer DbgVariableRecord::LocationType Type, Metadata *Val, MDNode *Variable, 172ffd08c77SStephen Tozer MDNode *Expression, MDNode *AssignID, Metadata *Address, 173ffd08c77SStephen Tozer MDNode *AddressExpression, MDNode *DI) { 174ffd08c77SStephen Tozer return new DbgVariableRecord(Type, Val, Variable, Expression, AssignID, 175ffd08c77SStephen Tozer Address, AddressExpression, DI); 176464d9d96SStephen Tozer } 177464d9d96SStephen Tozer 178ffd08c77SStephen Tozer DbgVariableRecord * 179ffd08c77SStephen Tozer DbgVariableRecord::createDbgVariableRecord(Value *Location, DILocalVariable *DV, 180ffd08c77SStephen Tozer DIExpression *Expr, 181ffd08c77SStephen Tozer const DILocation *DI) { 182ffd08c77SStephen Tozer return new DbgVariableRecord(ValueAsMetadata::get(Location), DV, Expr, DI, 1832b08de43SStephen Tozer LocationType::Value); 1842b08de43SStephen Tozer } 1852b08de43SStephen Tozer 186ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::createDbgVariableRecord( 187ffd08c77SStephen Tozer Value *Location, DILocalVariable *DV, DIExpression *Expr, 188ffd08c77SStephen Tozer const DILocation *DI, DbgVariableRecord &InsertBefore) { 189ffd08c77SStephen Tozer auto *NewDbgVariableRecord = createDbgVariableRecord(Location, DV, Expr, DI); 190ffd08c77SStephen Tozer NewDbgVariableRecord->insertBefore(&InsertBefore); 191ffd08c77SStephen Tozer return NewDbgVariableRecord; 1922b08de43SStephen Tozer } 1932b08de43SStephen Tozer 194ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::createDVRDeclare(Value *Address, 195ffd08c77SStephen Tozer DILocalVariable *DV, 196ffd08c77SStephen Tozer DIExpression *Expr, 197ffd08c77SStephen Tozer const DILocation *DI) { 198ffd08c77SStephen Tozer return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI, 1992b08de43SStephen Tozer LocationType::Declare); 2002b08de43SStephen Tozer } 2012b08de43SStephen Tozer 202ffd08c77SStephen Tozer DbgVariableRecord * 203ffd08c77SStephen Tozer DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV, 2042b08de43SStephen Tozer DIExpression *Expr, const DILocation *DI, 205ffd08c77SStephen Tozer DbgVariableRecord &InsertBefore) { 206ffd08c77SStephen Tozer auto *NewDVRDeclare = createDVRDeclare(Address, DV, Expr, DI); 207ffd08c77SStephen Tozer NewDVRDeclare->insertBefore(&InsertBefore); 208ffd08c77SStephen Tozer return NewDVRDeclare; 2092b08de43SStephen Tozer } 2102b08de43SStephen Tozer 211ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::createDVRAssign( 212ffd08c77SStephen Tozer Value *Val, DILocalVariable *Variable, DIExpression *Expression, 213ffd08c77SStephen Tozer DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression, 214d499df02SStephen Tozer const DILocation *DI) { 215ffd08c77SStephen Tozer return new DbgVariableRecord(ValueAsMetadata::get(Val), Variable, Expression, 216ffd08c77SStephen Tozer AssignID, ValueAsMetadata::get(Address), 217ffd08c77SStephen Tozer AddressExpression, DI); 218d499df02SStephen Tozer } 219d499df02SStephen Tozer 220ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::createLinkedDVRAssign( 221ffd08c77SStephen Tozer Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, 222ffd08c77SStephen Tozer DIExpression *Expression, Value *Address, DIExpression *AddressExpression, 223d499df02SStephen Tozer const DILocation *DI) { 224d499df02SStephen Tozer auto *Link = LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID); 225d499df02SStephen Tozer assert(Link && "Linked instruction must have DIAssign metadata attached"); 226ffd08c77SStephen Tozer auto *NewDVRAssign = DbgVariableRecord::createDVRAssign( 227ffd08c77SStephen Tozer Val, Variable, Expression, cast<DIAssignID>(Link), Address, 228d499df02SStephen Tozer AddressExpression, DI); 229ffd08c77SStephen Tozer LinkedInstr->getParent()->insertDbgRecordAfter(NewDVRAssign, LinkedInstr); 230ffd08c77SStephen Tozer return NewDVRAssign; 231d499df02SStephen Tozer } 232d499df02SStephen Tozer 233ffd08c77SStephen Tozer iterator_range<DbgVariableRecord::location_op_iterator> 234ffd08c77SStephen Tozer DbgVariableRecord::location_ops() const { 235f1b0a544SJeremy Morse auto *MD = getRawLocation(); 236ffd08c77SStephen Tozer // If a Value has been deleted, the "location" for this DbgVariableRecord will 237ffd08c77SStephen Tozer // be replaced by nullptr. Return an empty range. 238f1b0a544SJeremy Morse if (!MD) 239f1b0a544SJeremy Morse return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), 240f1b0a544SJeremy Morse location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; 241f1b0a544SJeremy Morse 242f1b0a544SJeremy Morse // If operand is ValueAsMetadata, return a range over just that operand. 243f1b0a544SJeremy Morse if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) 244f1b0a544SJeremy Morse return {location_op_iterator(VAM), location_op_iterator(VAM + 1)}; 245f1b0a544SJeremy Morse 246f1b0a544SJeremy Morse // If operand is DIArgList, return a range over its args. 247f1b0a544SJeremy Morse if (auto *AL = dyn_cast<DIArgList>(MD)) 248f1b0a544SJeremy Morse return {location_op_iterator(AL->args_begin()), 249f1b0a544SJeremy Morse location_op_iterator(AL->args_end())}; 250f1b0a544SJeremy Morse 251f1b0a544SJeremy Morse // Operand is an empty metadata tuple, so return empty iterator. 252f1b0a544SJeremy Morse assert(cast<MDNode>(MD)->getNumOperands() == 0); 253f1b0a544SJeremy Morse return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), 254f1b0a544SJeremy Morse location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; 255f1b0a544SJeremy Morse } 256f1b0a544SJeremy Morse 257ffd08c77SStephen Tozer unsigned DbgVariableRecord::getNumVariableLocationOps() const { 258b90cba10SJeremy Morse if (hasArgList()) 259b90cba10SJeremy Morse return cast<DIArgList>(getRawLocation())->getArgs().size(); 260b90cba10SJeremy Morse return 1; 261b90cba10SJeremy Morse } 262b90cba10SJeremy Morse 263ffd08c77SStephen Tozer Value *DbgVariableRecord::getVariableLocationOp(unsigned OpIdx) const { 264f1b0a544SJeremy Morse auto *MD = getRawLocation(); 265f1b0a544SJeremy Morse if (!MD) 266f1b0a544SJeremy Morse return nullptr; 267f1b0a544SJeremy Morse 268f1b0a544SJeremy Morse if (auto *AL = dyn_cast<DIArgList>(MD)) 269f1b0a544SJeremy Morse return AL->getArgs()[OpIdx]->getValue(); 270f1b0a544SJeremy Morse if (isa<MDNode>(MD)) 271f1b0a544SJeremy Morse return nullptr; 272f1b0a544SJeremy Morse assert(isa<ValueAsMetadata>(MD) && 273ffd08c77SStephen Tozer "Attempted to get location operand from DbgVariableRecord with none."); 274f1b0a544SJeremy Morse auto *V = cast<ValueAsMetadata>(MD); 275f1b0a544SJeremy Morse assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a " 276f1b0a544SJeremy Morse "single location operand."); 277f1b0a544SJeremy Morse return V->getValue(); 278f1b0a544SJeremy Morse } 279f1b0a544SJeremy Morse 280f1b0a544SJeremy Morse static ValueAsMetadata *getAsMetadata(Value *V) { 281f1b0a544SJeremy Morse return isa<MetadataAsValue>(V) ? dyn_cast<ValueAsMetadata>( 282f1b0a544SJeremy Morse cast<MetadataAsValue>(V)->getMetadata()) 283f1b0a544SJeremy Morse : ValueAsMetadata::get(V); 284f1b0a544SJeremy Morse } 285f1b0a544SJeremy Morse 286ffd08c77SStephen Tozer void DbgVariableRecord::replaceVariableLocationOp(Value *OldValue, 287ffd08c77SStephen Tozer Value *NewValue, 288f1b0a544SJeremy Morse bool AllowEmpty) { 289f1b0a544SJeremy Morse assert(NewValue && "Values must be non-null"); 290d499df02SStephen Tozer 291d499df02SStephen Tozer bool DbgAssignAddrReplaced = isDbgAssign() && OldValue == getAddress(); 292d499df02SStephen Tozer if (DbgAssignAddrReplaced) 293d499df02SStephen Tozer setAddress(NewValue); 294d499df02SStephen Tozer 295f1b0a544SJeremy Morse auto Locations = location_ops(); 296f1b0a544SJeremy Morse auto OldIt = find(Locations, OldValue); 297f1b0a544SJeremy Morse if (OldIt == Locations.end()) { 298d499df02SStephen Tozer if (AllowEmpty || DbgAssignAddrReplaced) 299f1b0a544SJeremy Morse return; 300f1b0a544SJeremy Morse llvm_unreachable("OldValue must be a current location"); 301f1b0a544SJeremy Morse } 302f1b0a544SJeremy Morse 303f1b0a544SJeremy Morse if (!hasArgList()) { 304f1b0a544SJeremy Morse // Set our location to be the MAV wrapping the new Value. 305f1b0a544SJeremy Morse setRawLocation(isa<MetadataAsValue>(NewValue) 306f1b0a544SJeremy Morse ? cast<MetadataAsValue>(NewValue)->getMetadata() 307f1b0a544SJeremy Morse : ValueAsMetadata::get(NewValue)); 308f1b0a544SJeremy Morse return; 309f1b0a544SJeremy Morse } 310f1b0a544SJeremy Morse 311f1b0a544SJeremy Morse // We must be referring to a DIArgList, produce a new operands vector with the 312f1b0a544SJeremy Morse // old value replaced, generate a new DIArgList and set it as our location. 313f1b0a544SJeremy Morse SmallVector<ValueAsMetadata *, 4> MDs; 314f1b0a544SJeremy Morse ValueAsMetadata *NewOperand = getAsMetadata(NewValue); 315f1b0a544SJeremy Morse for (auto *VMD : Locations) 316f1b0a544SJeremy Morse MDs.push_back(VMD == *OldIt ? NewOperand : getAsMetadata(VMD)); 317f1b0a544SJeremy Morse setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); 318f1b0a544SJeremy Morse } 319f1b0a544SJeremy Morse 320ffd08c77SStephen Tozer void DbgVariableRecord::replaceVariableLocationOp(unsigned OpIdx, 321ffd08c77SStephen Tozer Value *NewValue) { 322f1b0a544SJeremy Morse assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index"); 323f1b0a544SJeremy Morse 324f1b0a544SJeremy Morse if (!hasArgList()) { 325f1b0a544SJeremy Morse setRawLocation(isa<MetadataAsValue>(NewValue) 326f1b0a544SJeremy Morse ? cast<MetadataAsValue>(NewValue)->getMetadata() 327f1b0a544SJeremy Morse : ValueAsMetadata::get(NewValue)); 328f1b0a544SJeremy Morse return; 329f1b0a544SJeremy Morse } 330f1b0a544SJeremy Morse 331f1b0a544SJeremy Morse SmallVector<ValueAsMetadata *, 4> MDs; 332f1b0a544SJeremy Morse ValueAsMetadata *NewOperand = getAsMetadata(NewValue); 333f1b0a544SJeremy Morse for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx) 334f1b0a544SJeremy Morse MDs.push_back(Idx == OpIdx ? NewOperand 335f1b0a544SJeremy Morse : getAsMetadata(getVariableLocationOp(Idx))); 336f1b0a544SJeremy Morse 337f1b0a544SJeremy Morse setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); 338f1b0a544SJeremy Morse } 339f1b0a544SJeremy Morse 340ffd08c77SStephen Tozer void DbgVariableRecord::addVariableLocationOps(ArrayRef<Value *> NewValues, 341f1b0a544SJeremy Morse DIExpression *NewExpr) { 342f1b0a544SJeremy Morse assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + 343f1b0a544SJeremy Morse NewValues.size()) && 344f1b0a544SJeremy Morse "NewExpr for debug variable intrinsic does not reference every " 345f1b0a544SJeremy Morse "location operand."); 346f1b0a544SJeremy Morse assert(!is_contained(NewValues, nullptr) && "New values must be non-null"); 347f1b0a544SJeremy Morse setExpression(NewExpr); 348f1b0a544SJeremy Morse SmallVector<ValueAsMetadata *, 4> MDs; 349f1b0a544SJeremy Morse for (auto *VMD : location_ops()) 350f1b0a544SJeremy Morse MDs.push_back(getAsMetadata(VMD)); 351f1b0a544SJeremy Morse for (auto *VMD : NewValues) 352f1b0a544SJeremy Morse MDs.push_back(getAsMetadata(VMD)); 353f1b0a544SJeremy Morse setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); 354f1b0a544SJeremy Morse } 355f1b0a544SJeremy Morse 356ffd08c77SStephen Tozer void DbgVariableRecord::setKillLocation() { 357b90cba10SJeremy Morse // TODO: When/if we remove duplicate values from DIArgLists, we don't need 358b90cba10SJeremy Morse // this set anymore. 359b90cba10SJeremy Morse SmallPtrSet<Value *, 4> RemovedValues; 360b90cba10SJeremy Morse for (Value *OldValue : location_ops()) { 361b90cba10SJeremy Morse if (!RemovedValues.insert(OldValue).second) 362b90cba10SJeremy Morse continue; 363b90cba10SJeremy Morse Value *Poison = PoisonValue::get(OldValue->getType()); 364b90cba10SJeremy Morse replaceVariableLocationOp(OldValue, Poison); 365b90cba10SJeremy Morse } 366b90cba10SJeremy Morse } 367b90cba10SJeremy Morse 368ffd08c77SStephen Tozer bool DbgVariableRecord::isKillLocation() const { 369dc726c34SStephen Tozer return (!hasArgList() && isa<MDNode>(getRawLocation())) || 370dc726c34SStephen Tozer (getNumVariableLocationOps() == 0 && !getExpression()->isComplex()) || 371b90cba10SJeremy Morse any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); }); 372b90cba10SJeremy Morse } 373b90cba10SJeremy Morse 374deb6b603SOrlando Cazalet-Hyams std::optional<DbgVariableFragmentInfo> DbgVariableRecord::getFragment() const { 375deb6b603SOrlando Cazalet-Hyams return getExpression()->getFragmentInfo(); 376deb6b603SOrlando Cazalet-Hyams } 377deb6b603SOrlando Cazalet-Hyams 378ffd08c77SStephen Tozer std::optional<uint64_t> DbgVariableRecord::getFragmentSizeInBits() const { 379f1b0a544SJeremy Morse if (auto Fragment = getExpression()->getFragmentInfo()) 380f1b0a544SJeremy Morse return Fragment->SizeInBits; 381f1b0a544SJeremy Morse return getVariable()->getSizeInBits(); 382f1b0a544SJeremy Morse } 383f1b0a544SJeremy Morse 384ababa964SOrlando Cazalet-Hyams DbgRecord *DbgRecord::clone() const { 385ababa964SOrlando Cazalet-Hyams switch (RecordKind) { 386ababa964SOrlando Cazalet-Hyams case ValueKind: 387ffd08c77SStephen Tozer return cast<DbgVariableRecord>(this)->clone(); 38820434bf3SOrlando Cazalet-Hyams case LabelKind: 389bdc77d1eSStephen Tozer return cast<DbgLabelRecord>(this)->clone(); 390ababa964SOrlando Cazalet-Hyams }; 3914a23ab43SOrlando Cazalet-Hyams llvm_unreachable("unsupported DbgRecord kind"); 392ababa964SOrlando Cazalet-Hyams } 393ababa964SOrlando Cazalet-Hyams 394ffd08c77SStephen Tozer DbgVariableRecord *DbgVariableRecord::clone() const { 395ffd08c77SStephen Tozer return new DbgVariableRecord(*this); 396ffd08c77SStephen Tozer } 397f1b0a544SJeremy Morse 398bdc77d1eSStephen Tozer DbgLabelRecord *DbgLabelRecord::clone() const { 399bdc77d1eSStephen Tozer return new DbgLabelRecord(getLabel(), getDebugLoc()); 400b3c2c5a8SStephen Tozer } 40120434bf3SOrlando Cazalet-Hyams 402f1b0a544SJeremy Morse DbgVariableIntrinsic * 403ffd08c77SStephen Tozer DbgVariableRecord::createDebugIntrinsic(Module *M, 404ffd08c77SStephen Tozer Instruction *InsertBefore) const { 405f1b0a544SJeremy Morse [[maybe_unused]] DICompileUnit *Unit = 40675bc20ffSKazu Hirata getDebugLoc()->getScope()->getSubprogram()->getUnit(); 407f1b0a544SJeremy Morse assert(M && Unit && 408f1b0a544SJeremy Morse "Cannot clone from BasicBlock that is not part of a Module or " 409f1b0a544SJeremy Morse "DICompileUnit!"); 410f1b0a544SJeremy Morse LLVMContext &Context = getDebugLoc()->getContext(); 411f1b0a544SJeremy Morse Function *IntrinsicFn; 412f1b0a544SJeremy Morse 413f1b0a544SJeremy Morse // Work out what sort of intrinsic we're going to produce. 414f1b0a544SJeremy Morse switch (getType()) { 415ffd08c77SStephen Tozer case DbgVariableRecord::LocationType::Declare: 416fa789dffSRahul Joshi IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare); 417f1b0a544SJeremy Morse break; 418ffd08c77SStephen Tozer case DbgVariableRecord::LocationType::Value: 419fa789dffSRahul Joshi IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_value); 420f1b0a544SJeremy Morse break; 421ffd08c77SStephen Tozer case DbgVariableRecord::LocationType::Assign: 422fa789dffSRahul Joshi IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_assign); 423d499df02SStephen Tozer break; 424ffd08c77SStephen Tozer case DbgVariableRecord::LocationType::End: 425ffd08c77SStephen Tozer case DbgVariableRecord::LocationType::Any: 4265457fab1SOCHyams llvm_unreachable("Invalid LocationType"); 427f1b0a544SJeremy Morse } 428f1b0a544SJeremy Morse 429ffd08c77SStephen Tozer // Create the intrinsic from this DbgVariableRecord's information, optionally 430ffd08c77SStephen Tozer // insert into the target location. 431d499df02SStephen Tozer DbgVariableIntrinsic *DVI; 432ffd08c77SStephen Tozer assert(getRawLocation() && 433ffd08c77SStephen Tozer "DbgVariableRecord's RawLocation should be non-null."); 434d499df02SStephen Tozer if (isDbgAssign()) { 435d499df02SStephen Tozer Value *AssignArgs[] = { 436d499df02SStephen Tozer MetadataAsValue::get(Context, getRawLocation()), 437d499df02SStephen Tozer MetadataAsValue::get(Context, getVariable()), 438d499df02SStephen Tozer MetadataAsValue::get(Context, getExpression()), 439d499df02SStephen Tozer MetadataAsValue::get(Context, getAssignID()), 440d499df02SStephen Tozer MetadataAsValue::get(Context, getRawAddress()), 441d499df02SStephen Tozer MetadataAsValue::get(Context, getAddressExpression())}; 442d499df02SStephen Tozer DVI = cast<DbgVariableIntrinsic>(CallInst::Create( 443d499df02SStephen Tozer IntrinsicFn->getFunctionType(), IntrinsicFn, AssignArgs)); 444d499df02SStephen Tozer } else { 445d499df02SStephen Tozer Value *Args[] = {MetadataAsValue::get(Context, getRawLocation()), 446d499df02SStephen Tozer MetadataAsValue::get(Context, getVariable()), 447d499df02SStephen Tozer MetadataAsValue::get(Context, getExpression())}; 448d499df02SStephen Tozer DVI = cast<DbgVariableIntrinsic>( 449f1b0a544SJeremy Morse CallInst::Create(IntrinsicFn->getFunctionType(), IntrinsicFn, Args)); 450d499df02SStephen Tozer } 451f1b0a544SJeremy Morse DVI->setTailCall(); 452f1b0a544SJeremy Morse DVI->setDebugLoc(getDebugLoc()); 453f1b0a544SJeremy Morse if (InsertBefore) 454*8e702735SJeremy Morse DVI->insertBefore(InsertBefore->getIterator()); 455f1b0a544SJeremy Morse 456f1b0a544SJeremy Morse return DVI; 457f1b0a544SJeremy Morse } 458f1b0a544SJeremy Morse 459bdc77d1eSStephen Tozer DbgLabelInst * 460bdc77d1eSStephen Tozer DbgLabelRecord::createDebugIntrinsic(Module *M, 4613356818eSOrlando Cazalet-Hyams Instruction *InsertBefore) const { 462fa789dffSRahul Joshi auto *LabelFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_label); 4633356818eSOrlando Cazalet-Hyams Value *Args[] = { 4643356818eSOrlando Cazalet-Hyams MetadataAsValue::get(getDebugLoc()->getContext(), getLabel())}; 4653356818eSOrlando Cazalet-Hyams DbgLabelInst *DbgLabel = cast<DbgLabelInst>( 4663356818eSOrlando Cazalet-Hyams CallInst::Create(LabelFn->getFunctionType(), LabelFn, Args)); 4673356818eSOrlando Cazalet-Hyams DbgLabel->setTailCall(); 4683356818eSOrlando Cazalet-Hyams DbgLabel->setDebugLoc(getDebugLoc()); 4693356818eSOrlando Cazalet-Hyams if (InsertBefore) 470*8e702735SJeremy Morse DbgLabel->insertBefore(InsertBefore->getIterator()); 4713356818eSOrlando Cazalet-Hyams return DbgLabel; 4723356818eSOrlando Cazalet-Hyams } 4733356818eSOrlando Cazalet-Hyams 474ffd08c77SStephen Tozer Value *DbgVariableRecord::getAddress() const { 475d499df02SStephen Tozer auto *MD = getRawAddress(); 47625f87f2dSJeremy Morse if (auto *V = dyn_cast_or_null<ValueAsMetadata>(MD)) 477d499df02SStephen Tozer return V->getValue(); 478d499df02SStephen Tozer 479d499df02SStephen Tozer // When the value goes to null, it gets replaced by an empty MDNode. 480851bacb7SSimon Pilgrim assert((!MD || !cast<MDNode>(MD)->getNumOperands()) && 481851bacb7SSimon Pilgrim "Expected an empty MDNode"); 482d499df02SStephen Tozer return nullptr; 483d499df02SStephen Tozer } 484d499df02SStephen Tozer 485ffd08c77SStephen Tozer DIAssignID *DbgVariableRecord::getAssignID() const { 486d499df02SStephen Tozer return cast<DIAssignID>(DebugValues[2]); 487d499df02SStephen Tozer } 488d499df02SStephen Tozer 489ffd08c77SStephen Tozer void DbgVariableRecord::setAssignId(DIAssignID *New) { 490ffd08c77SStephen Tozer resetDebugValue(2, New); 491ffd08c77SStephen Tozer } 492d499df02SStephen Tozer 493ffd08c77SStephen Tozer void DbgVariableRecord::setKillAddress() { 494d499df02SStephen Tozer resetDebugValue( 4952499978aSNuno Lopes 1, ValueAsMetadata::get(PoisonValue::get(getAddress()->getType()))); 496d499df02SStephen Tozer } 497d499df02SStephen Tozer 498ffd08c77SStephen Tozer bool DbgVariableRecord::isKillAddress() const { 499d499df02SStephen Tozer Value *Addr = getAddress(); 500d499df02SStephen Tozer return !Addr || isa<UndefValue>(Addr); 501f1b0a544SJeremy Morse } 502f1b0a544SJeremy Morse 503ababa964SOrlando Cazalet-Hyams const Instruction *DbgRecord::getInstruction() const { 50419b65a9cSJeremy Morse return Marker->MarkedInstr; 50519b65a9cSJeremy Morse } 50619b65a9cSJeremy Morse 507ababa964SOrlando Cazalet-Hyams const BasicBlock *DbgRecord::getParent() const { 508f1b0a544SJeremy Morse return Marker->MarkedInstr->getParent(); 509f1b0a544SJeremy Morse } 510f1b0a544SJeremy Morse 511ababa964SOrlando Cazalet-Hyams BasicBlock *DbgRecord::getParent() { return Marker->MarkedInstr->getParent(); } 512f1b0a544SJeremy Morse 513ababa964SOrlando Cazalet-Hyams BasicBlock *DbgRecord::getBlock() { return Marker->getParent(); } 514f1b0a544SJeremy Morse 515ababa964SOrlando Cazalet-Hyams const BasicBlock *DbgRecord::getBlock() const { return Marker->getParent(); } 516f1b0a544SJeremy Morse 517ababa964SOrlando Cazalet-Hyams Function *DbgRecord::getFunction() { return getBlock()->getParent(); } 518f1b0a544SJeremy Morse 519ababa964SOrlando Cazalet-Hyams const Function *DbgRecord::getFunction() const { 520ababa964SOrlando Cazalet-Hyams return getBlock()->getParent(); 521ababa964SOrlando Cazalet-Hyams } 522f1b0a544SJeremy Morse 523ababa964SOrlando Cazalet-Hyams Module *DbgRecord::getModule() { return getFunction()->getParent(); } 524f1b0a544SJeremy Morse 525ababa964SOrlando Cazalet-Hyams const Module *DbgRecord::getModule() const { 526ababa964SOrlando Cazalet-Hyams return getFunction()->getParent(); 527ababa964SOrlando Cazalet-Hyams } 528f1b0a544SJeremy Morse 529ababa964SOrlando Cazalet-Hyams LLVMContext &DbgRecord::getContext() { return getBlock()->getContext(); } 530f1b0a544SJeremy Morse 531ababa964SOrlando Cazalet-Hyams const LLVMContext &DbgRecord::getContext() const { 532f1b0a544SJeremy Morse return getBlock()->getContext(); 533f1b0a544SJeremy Morse } 534f1b0a544SJeremy Morse 535ababa964SOrlando Cazalet-Hyams void DbgRecord::insertBefore(DbgRecord *InsertBefore) { 5362b08de43SStephen Tozer assert(!getMarker() && 53775dfa58eSStephen Tozer "Cannot insert a DbgRecord that is already has a DbgMarker!"); 5382b08de43SStephen Tozer assert(InsertBefore->getMarker() && 539ababa964SOrlando Cazalet-Hyams "Cannot insert a DbgRecord before a DbgRecord that does not have a " 54075dfa58eSStephen Tozer "DbgMarker!"); 54115f3f446SStephen Tozer InsertBefore->getMarker()->insertDbgRecord(this, InsertBefore); 5422b08de43SStephen Tozer } 543ababa964SOrlando Cazalet-Hyams void DbgRecord::insertAfter(DbgRecord *InsertAfter) { 5442b08de43SStephen Tozer assert(!getMarker() && 54575dfa58eSStephen Tozer "Cannot insert a DbgRecord that is already has a DbgMarker!"); 5462b08de43SStephen Tozer assert(InsertAfter->getMarker() && 547ababa964SOrlando Cazalet-Hyams "Cannot insert a DbgRecord after a DbgRecord that does not have a " 54875dfa58eSStephen Tozer "DbgMarker!"); 54915f3f446SStephen Tozer InsertAfter->getMarker()->insertDbgRecordAfter(this, InsertAfter); 5502b08de43SStephen Tozer } 551*8e702735SJeremy Morse 552*8e702735SJeremy Morse void DbgRecord::insertBefore(self_iterator InsertBefore) { 553*8e702735SJeremy Morse assert(!getMarker() && 554*8e702735SJeremy Morse "Cannot insert a DbgRecord that is already has a DbgMarker!"); 555*8e702735SJeremy Morse assert(InsertBefore->getMarker() && 556*8e702735SJeremy Morse "Cannot insert a DbgRecord before a DbgRecord that does not have a " 557*8e702735SJeremy Morse "DbgMarker!"); 558*8e702735SJeremy Morse InsertBefore->getMarker()->insertDbgRecord(this, &*InsertBefore); 559*8e702735SJeremy Morse } 560*8e702735SJeremy Morse void DbgRecord::insertAfter(self_iterator InsertAfter) { 561*8e702735SJeremy Morse assert(!getMarker() && 562*8e702735SJeremy Morse "Cannot insert a DbgRecord that is already has a DbgMarker!"); 563*8e702735SJeremy Morse assert(InsertAfter->getMarker() && 564*8e702735SJeremy Morse "Cannot insert a DbgRecord after a DbgRecord that does not have a " 565*8e702735SJeremy Morse "DbgMarker!"); 566*8e702735SJeremy Morse InsertAfter->getMarker()->insertDbgRecordAfter(this, &*InsertAfter); 567*8e702735SJeremy Morse } 568*8e702735SJeremy Morse 569ababa964SOrlando Cazalet-Hyams void DbgRecord::moveBefore(DbgRecord *MoveBefore) { 5702b08de43SStephen Tozer assert(getMarker() && 57175dfa58eSStephen Tozer "Canot move a DbgRecord that does not currently have a DbgMarker!"); 5722b08de43SStephen Tozer removeFromParent(); 5732b08de43SStephen Tozer insertBefore(MoveBefore); 5742b08de43SStephen Tozer } 575ababa964SOrlando Cazalet-Hyams void DbgRecord::moveAfter(DbgRecord *MoveAfter) { 5762b08de43SStephen Tozer assert(getMarker() && 57775dfa58eSStephen Tozer "Canot move a DbgRecord that does not currently have a DbgMarker!"); 5782b08de43SStephen Tozer removeFromParent(); 5792b08de43SStephen Tozer insertAfter(MoveAfter); 5802b08de43SStephen Tozer } 5812b08de43SStephen Tozer 582*8e702735SJeremy Morse void DbgRecord::moveBefore(self_iterator MoveBefore) { 583*8e702735SJeremy Morse assert(getMarker() && 584*8e702735SJeremy Morse "Canot move a DbgRecord that does not currently have a DbgMarker!"); 585*8e702735SJeremy Morse removeFromParent(); 586*8e702735SJeremy Morse insertBefore(MoveBefore); 587*8e702735SJeremy Morse } 588*8e702735SJeremy Morse void DbgRecord::moveAfter(self_iterator MoveAfter) { 589*8e702735SJeremy Morse assert(getMarker() && 590*8e702735SJeremy Morse "Canot move a DbgRecord that does not currently have a DbgMarker!"); 591*8e702735SJeremy Morse removeFromParent(); 592*8e702735SJeremy Morse insertAfter(MoveAfter); 593*8e702735SJeremy Morse } 594*8e702735SJeremy Morse 595f1b0a544SJeremy Morse /////////////////////////////////////////////////////////////////////////////// 596f1b0a544SJeremy Morse 59775dfa58eSStephen Tozer // An empty, global, DbgMarker for the purpose of describing empty ranges of 598360da838SStephen Tozer // DbgRecords. 59975dfa58eSStephen Tozer DbgMarker DbgMarker::EmptyDbgMarker; 600f1b0a544SJeremy Morse 60175dfa58eSStephen Tozer void DbgMarker::dropDbgRecords() { 602360da838SStephen Tozer while (!StoredDbgRecords.empty()) { 603360da838SStephen Tozer auto It = StoredDbgRecords.begin(); 604ababa964SOrlando Cazalet-Hyams DbgRecord *DR = &*It; 605360da838SStephen Tozer StoredDbgRecords.erase(It); 606ababa964SOrlando Cazalet-Hyams DR->deleteRecord(); 607f1b0a544SJeremy Morse } 608f1b0a544SJeremy Morse } 609f1b0a544SJeremy Morse 61075dfa58eSStephen Tozer void DbgMarker::dropOneDbgRecord(DbgRecord *DR) { 611ababa964SOrlando Cazalet-Hyams assert(DR->getMarker() == this); 612360da838SStephen Tozer StoredDbgRecords.erase(DR->getIterator()); 613ababa964SOrlando Cazalet-Hyams DR->deleteRecord(); 614f1b0a544SJeremy Morse } 615f1b0a544SJeremy Morse 61675dfa58eSStephen Tozer const BasicBlock *DbgMarker::getParent() const { 617f1b0a544SJeremy Morse return MarkedInstr->getParent(); 618f1b0a544SJeremy Morse } 619f1b0a544SJeremy Morse 62075dfa58eSStephen Tozer BasicBlock *DbgMarker::getParent() { return MarkedInstr->getParent(); } 621f1b0a544SJeremy Morse 62275dfa58eSStephen Tozer void DbgMarker::removeMarker() { 62375dfa58eSStephen Tozer // Are there any DbgRecords in this DbgMarker? If not, nothing to preserve. 624f1b0a544SJeremy Morse Instruction *Owner = MarkedInstr; 625360da838SStephen Tozer if (StoredDbgRecords.empty()) { 626f1b0a544SJeremy Morse eraseFromParent(); 62775dfa58eSStephen Tozer Owner->DebugMarker = nullptr; 628f1b0a544SJeremy Morse return; 629f1b0a544SJeremy Morse } 630f1b0a544SJeremy Morse 631360da838SStephen Tozer // The attached DbgRecords need to be preserved; attach them to the next 632f1b0a544SJeremy Morse // instruction. If there isn't a next instruction, put them on the 633f1b0a544SJeremy Morse // "trailing" list. 63475dfa58eSStephen Tozer DbgMarker *NextMarker = Owner->getParent()->getNextMarker(Owner); 635ddc49357SJeremy Morse if (NextMarker) { 636f1b0a544SJeremy Morse NextMarker->absorbDebugValues(*this, true); 637f1b0a544SJeremy Morse eraseFromParent(); 638ddc49357SJeremy Morse } else { 639ddc49357SJeremy Morse // We can avoid a deallocation -- just store this marker onto the next 640ddc49357SJeremy Morse // instruction. Unless we're at the end of the block, in which case this 641ddc49357SJeremy Morse // marker becomes the trailing marker of a degenerate block. 642ddc49357SJeremy Morse BasicBlock::iterator NextIt = std::next(Owner->getIterator()); 643ddc49357SJeremy Morse if (NextIt == getParent()->end()) { 64415f3f446SStephen Tozer getParent()->setTrailingDbgRecords(this); 645ddc49357SJeremy Morse MarkedInstr = nullptr; 646ddc49357SJeremy Morse } else { 64775dfa58eSStephen Tozer NextIt->DebugMarker = this; 648ddc49357SJeremy Morse MarkedInstr = &*NextIt; 649ddc49357SJeremy Morse } 650ddc49357SJeremy Morse } 65175dfa58eSStephen Tozer Owner->DebugMarker = nullptr; 652f1b0a544SJeremy Morse } 653f1b0a544SJeremy Morse 65475dfa58eSStephen Tozer void DbgMarker::removeFromParent() { 65575dfa58eSStephen Tozer MarkedInstr->DebugMarker = nullptr; 656f1b0a544SJeremy Morse MarkedInstr = nullptr; 657f1b0a544SJeremy Morse } 658f1b0a544SJeremy Morse 65975dfa58eSStephen Tozer void DbgMarker::eraseFromParent() { 660f1b0a544SJeremy Morse if (MarkedInstr) 661f1b0a544SJeremy Morse removeFromParent(); 66215f3f446SStephen Tozer dropDbgRecords(); 663f1b0a544SJeremy Morse delete this; 664f1b0a544SJeremy Morse } 665f1b0a544SJeremy Morse 66675dfa58eSStephen Tozer iterator_range<DbgRecord::self_iterator> DbgMarker::getDbgRecordRange() { 667360da838SStephen Tozer return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); 668f1b0a544SJeremy Morse } 669ababa964SOrlando Cazalet-Hyams iterator_range<DbgRecord::const_self_iterator> 67075dfa58eSStephen Tozer DbgMarker::getDbgRecordRange() const { 671360da838SStephen Tozer return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); 6722b08de43SStephen Tozer } 673f1b0a544SJeremy Morse 674ababa964SOrlando Cazalet-Hyams void DbgRecord::removeFromParent() { 675360da838SStephen Tozer getMarker()->StoredDbgRecords.erase(getIterator()); 6762b08de43SStephen Tozer Marker = nullptr; 677f1b0a544SJeremy Morse } 678f1b0a544SJeremy Morse 679ababa964SOrlando Cazalet-Hyams void DbgRecord::eraseFromParent() { 680f1b0a544SJeremy Morse removeFromParent(); 681ababa964SOrlando Cazalet-Hyams deleteRecord(); 682f1b0a544SJeremy Morse } 683f1b0a544SJeremy Morse 68475dfa58eSStephen Tozer void DbgMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { 685360da838SStephen Tozer auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); 686360da838SStephen Tozer StoredDbgRecords.insert(It, *New); 687f1b0a544SJeremy Morse New->setMarker(this); 688f1b0a544SJeremy Morse } 68975dfa58eSStephen Tozer void DbgMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { 6902b08de43SStephen Tozer assert(InsertBefore->getMarker() == this && 69175dfa58eSStephen Tozer "DbgRecord 'InsertBefore' must be contained in this DbgMarker!"); 692360da838SStephen Tozer StoredDbgRecords.insert(InsertBefore->getIterator(), *New); 6932b08de43SStephen Tozer New->setMarker(this); 6942b08de43SStephen Tozer } 69575dfa58eSStephen Tozer void DbgMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { 6962b08de43SStephen Tozer assert(InsertAfter->getMarker() == this && 69775dfa58eSStephen Tozer "DbgRecord 'InsertAfter' must be contained in this DbgMarker!"); 698360da838SStephen Tozer StoredDbgRecords.insert(++(InsertAfter->getIterator()), *New); 6992b08de43SStephen Tozer New->setMarker(this); 7002b08de43SStephen Tozer } 701f1b0a544SJeremy Morse 70275dfa58eSStephen Tozer void DbgMarker::absorbDebugValues(DbgMarker &Src, bool InsertAtHead) { 703360da838SStephen Tozer auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); 704ffd08c77SStephen Tozer for (DbgRecord &DVR : Src.StoredDbgRecords) 705ffd08c77SStephen Tozer DVR.setMarker(this); 706f1b0a544SJeremy Morse 707360da838SStephen Tozer StoredDbgRecords.splice(It, Src.StoredDbgRecords); 708f1b0a544SJeremy Morse } 709f1b0a544SJeremy Morse 71075dfa58eSStephen Tozer void DbgMarker::absorbDebugValues( 71175dfa58eSStephen Tozer iterator_range<DbgRecord::self_iterator> Range, DbgMarker &Src, 71275dfa58eSStephen Tozer bool InsertAtHead) { 713ababa964SOrlando Cazalet-Hyams for (DbgRecord &DR : Range) 714ababa964SOrlando Cazalet-Hyams DR.setMarker(this); 7152ec0283cSJeremy Morse 7162ec0283cSJeremy Morse auto InsertPos = 717360da838SStephen Tozer (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); 7182ec0283cSJeremy Morse 719360da838SStephen Tozer StoredDbgRecords.splice(InsertPos, Src.StoredDbgRecords, Range.begin(), 7202ec0283cSJeremy Morse Range.end()); 7212ec0283cSJeremy Morse } 7222ec0283cSJeremy Morse 72375dfa58eSStephen Tozer iterator_range<simple_ilist<DbgRecord>::iterator> DbgMarker::cloneDebugInfoFrom( 72475dfa58eSStephen Tozer DbgMarker *From, std::optional<simple_ilist<DbgRecord>::iterator> from_here, 725f1b0a544SJeremy Morse bool InsertAtHead) { 726ababa964SOrlando Cazalet-Hyams DbgRecord *First = nullptr; 727360da838SStephen Tozer // Work out what range of DbgRecords to clone: normally all the contents of 728360da838SStephen Tozer // the "From" marker, optionally we can start from the from_here position down 729360da838SStephen Tozer // to end(). 730f1b0a544SJeremy Morse auto Range = 731360da838SStephen Tozer make_range(From->StoredDbgRecords.begin(), From->StoredDbgRecords.end()); 732f1b0a544SJeremy Morse if (from_here.has_value()) 733360da838SStephen Tozer Range = make_range(*from_here, From->StoredDbgRecords.end()); 734f1b0a544SJeremy Morse 735ffd08c77SStephen Tozer // Clone each DbgVariableRecord and insert into StoreDbgVariableRecords; 736ffd08c77SStephen Tozer // optionally place them at the start or the end of the list. 737360da838SStephen Tozer auto Pos = (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); 738ababa964SOrlando Cazalet-Hyams for (DbgRecord &DR : Range) { 739ababa964SOrlando Cazalet-Hyams DbgRecord *New = DR.clone(); 740f1b0a544SJeremy Morse New->setMarker(this); 741360da838SStephen Tozer StoredDbgRecords.insert(Pos, *New); 742f1b0a544SJeremy Morse if (!First) 743f1b0a544SJeremy Morse First = New; 744f1b0a544SJeremy Morse } 745f1b0a544SJeremy Morse 746f1b0a544SJeremy Morse if (!First) 747360da838SStephen Tozer return {StoredDbgRecords.end(), StoredDbgRecords.end()}; 748f1b0a544SJeremy Morse 749f1b0a544SJeremy Morse if (InsertAtHead) 750f1b0a544SJeremy Morse // If InsertAtHead is set, we cloned a range onto the front of of the 751360da838SStephen Tozer // StoredDbgRecords collection, return that range. 752360da838SStephen Tozer return {StoredDbgRecords.begin(), Pos}; 753f1b0a544SJeremy Morse else 754f1b0a544SJeremy Morse // We inserted a block at the end, return that range. 755360da838SStephen Tozer return {First->getIterator(), StoredDbgRecords.end()}; 756f1b0a544SJeremy Morse } 757f1b0a544SJeremy Morse 758f1b0a544SJeremy Morse } // end namespace llvm 759