From 761f4efe0de381e9de6377329fb98679d9442873 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 1 Dec 2025 08:20:26 +0000 Subject: [PATCH 1/5] Revert "Convert #dbg_coroframe_entry to #dbg_value if location is not a pointer." This reverts commit 97327447d9c6ad494994d84424bc7d4ac98cec36. --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 9226c160301b9..9f781628e2d1c 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1185,13 +1185,10 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { // processed by coro::salvageDebugInfo() by the Cloner. However, convert // it to a dbg.declare to make sure future passes don't have to deal // with a dbg.coroframe_entry. - auto *VAM = ValueAsMetadata::get(CurrentReload); - Type *Ty = VAM->getValue()->getType(); DbgVariableRecord *NewDVR = new DbgVariableRecord( ValueAsMetadata::get(CurrentReload), DDI->getVariable(), DDI->getExpression(), DDI->getDebugLoc(), - Ty->isPointerTy() ? DbgVariableRecord::LocationType::Declare - : DbgVariableRecord::LocationType::Value); + DbgVariableRecord::LocationType::Declare); Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore( NewDVR, Builder.GetInsertPoint()); // This dbg.coroframe_entry is for the main function entry point. It @@ -2063,16 +2060,8 @@ void coro::salvageDebugInfo( // If there is a dbg.coroframe_entry being reinserted, insert it as a // dbg.declare instead, so that subsequent passes don't have to deal with // a dbg.coroframe_entry. - if (DVR.getType() == DbgVariableRecord::LocationType::CoroFrameEntry) { - auto *MD = DVR.getRawLocation(); - if (auto *VAM = dyn_cast(MD)) { - Type *Ty = VAM->getValue()->getType(); - if (Ty->isPointerTy()) - DVR.Type = DbgVariableRecord::LocationType::Declare; - else - DVR.Type = DbgVariableRecord::LocationType::Value; - } - } + if (DVR.getType() == DbgVariableRecord::LocationType::CoroFrameEntry) + DVR.Type = DbgVariableRecord::LocationType::Declare; (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt); } } From 26af861b19f530576bc259261bdf4a4eb38b5898 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 1 Dec 2025 08:20:39 +0000 Subject: [PATCH 2/5] Revert "Add support for llvm.dbg.coroframe_entry in the CoroSplitter pass." This reverts commit e5b3fa307ec516a0cb99e82e9b7516a7ed0ce270. --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 66 +++----------------- 1 file changed, 9 insertions(+), 57 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 9f781628e2d1c..68ce06637b277 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -555,8 +555,6 @@ static void cacheDIVar(FrameDataInfo &FrameData, }; CacheIt(findDbgDeclares(V)); CacheIt(findDVRDeclares(V)); - CacheIt(findDbgCoroFrameEntrys(V)); - CacheIt(findDVRCoroFrameEntrys(V)); } } @@ -1158,46 +1156,6 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { for_each(DVRs, SalvageOne); } - TinyPtrVector DICoros = - findDbgCoroFrameEntrys(Def); - TinyPtrVector DVRCoros = findDVRCoroFrameEntrys(Def); - // Try best to find dbg.coroframe_entry. If the spill is a temp, there may - // not be a direct dbg.coroframe_entry. Walk up the load chain to find one - // from an alias. - if (F->getSubprogram()) { - auto *CurDef = Def; - while (DICoros.empty() && DVRCoros.empty() && isa(CurDef)) { - auto *LdInst = cast(CurDef); - // Only consider ptr to ptr same type load. - if (LdInst->getPointerOperandType() != LdInst->getType()) - break; - CurDef = LdInst->getPointerOperand(); - if (!isa(CurDef)) - break; - DICoros = findDbgCoroFrameEntrys(CurDef); - DVRCoros = findDVRCoroFrameEntrys(CurDef); - } - } - - auto SalvageOneCoro = [&](auto *DDI) { - // This dbg.coroframe_entry is preserved for all coro-split function - // fragments. It will be unreachable in the main function, and - // processed by coro::salvageDebugInfo() by the Cloner. However, convert - // it to a dbg.declare to make sure future passes don't have to deal - // with a dbg.coroframe_entry. - DbgVariableRecord *NewDVR = new DbgVariableRecord( - ValueAsMetadata::get(CurrentReload), DDI->getVariable(), - DDI->getExpression(), DDI->getDebugLoc(), - DbgVariableRecord::LocationType::Declare); - Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore( - NewDVR, Builder.GetInsertPoint()); - // This dbg.coroframe_entry is for the main function entry point. It - // will be deleted in all coro-split functions. - coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/); - }; - for_each(DICoros, SalvageOneCoro); - for_each(DVRCoros, SalvageOneCoro); - // If we have a single edge PHINode, remove it and replace it with a // reload from the coroutine frame. (We already took care of multi edge // PHINodes by normalizing them in the rewritePHIs function). @@ -1996,10 +1954,10 @@ void coro::salvageDebugInfo( DVI.replaceVariableLocationOp(OriginalStorage, Storage); DVI.setExpression(Expr); - // We only hoist dbg.declare and dbg.coroframe_entry today since it doesn't - // make sense to hoist dbg.value since it does not have the same function wide - // guarantees that dbg.declare and dbg.coroframe_entry do. - if (isa(DVI) || isa(DVI)) { + // We only hoist dbg.declare today since it doesn't make sense to hoist + // dbg.value since it does not have the same function wide guarantees that + // dbg.declare does. + if (isa(DVI)) { std::optional InsertPt; if (auto *I = dyn_cast(Storage)) { InsertPt = I->getInsertionPointAfterDef(); @@ -2024,7 +1982,7 @@ void coro::salvageDebugInfo( Function *F = DVR.getFunction(); // Follow the pointer arithmetic all the way to the incoming // function argument and convert into a DIExpression. - bool SkipOutermostLoad = DVR.isDbgDeclare() || DVR.isDbgCoroFrameEntry(); + bool SkipOutermostLoad = DVR.isDbgDeclare(); Value *OriginalStorage = DVR.getVariableLocationOp(0); auto SalvagedInfo = @@ -2038,11 +1996,10 @@ void coro::salvageDebugInfo( DVR.replaceVariableLocationOp(OriginalStorage, Storage); DVR.setExpression(Expr); - // We only hoist dbg.declare and dbg.coroframe_entry today since it doesn't - // make sense to hoist dbg.value since it does not have the same function wide - // guarantees that dbg.declare and dbg.coroframe_entry do. - if (DVR.getType() == DbgVariableRecord::LocationType::Declare || - DVR.getType() == DbgVariableRecord::LocationType::CoroFrameEntry) { + // We only hoist dbg.declare today since it doesn't make sense to hoist + // dbg.value since it does not have the same function wide guarantees that + // dbg.declare does. + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) { std::optional InsertPt; if (auto *I = dyn_cast(Storage)) { InsertPt = I->getInsertionPointAfterDef(); @@ -2057,11 +2014,6 @@ void coro::salvageDebugInfo( InsertPt = F->getEntryBlock().begin(); if (InsertPt) { DVR.removeFromParent(); - // If there is a dbg.coroframe_entry being reinserted, insert it as a - // dbg.declare instead, so that subsequent passes don't have to deal with - // a dbg.coroframe_entry. - if (DVR.getType() == DbgVariableRecord::LocationType::CoroFrameEntry) - DVR.Type = DbgVariableRecord::LocationType::Declare; (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt); } } From 994fe3242b3518cb63bc6c20e4a8190431f80cb8 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Mon, 1 Dec 2025 08:20:41 +0000 Subject: [PATCH 3/5] Revert "Add new llvm.dbg.coroframe_entry intrinsic." This reverts commit e88254be3f0af9d2a5aaab74d843dd47a0fb0b38. --- llvm/docs/SourceLevelDebugging.rst | 15 -------- llvm/include/llvm/Bitcode/LLVMBitCodes.h | 2 - llvm/include/llvm/IR/DIBuilder.h | 12 ------ llvm/include/llvm/IR/DebugInfo.h | 9 ----- .../include/llvm/IR/DebugProgramInstruction.h | 12 ------ llvm/include/llvm/IR/IntrinsicInst.h | 21 ----------- llvm/include/llvm/IR/Intrinsics.td | 4 -- llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp | 1 - llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 8 ---- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 4 -- llvm/lib/IR/AsmWriter.cpp | 3 -- llvm/lib/IR/AutoUpgrade.cpp | 5 --- llvm/lib/IR/DIBuilder.cpp | 18 --------- llvm/lib/IR/DebugInfo.cpp | 37 ------------------- llvm/lib/IR/DebugProgramInstruction.cpp | 23 ------------ llvm/lib/IR/Verifier.cpp | 5 --- 16 files changed, 179 deletions(-) diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst index 00f548f197f46..dfc8c53edbb8e 100644 --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -401,21 +401,6 @@ This intrinsic is equivalent to ``#dbg_assign``: metadata ptr %i.addr, metadata !DIExpression(), metadata !3), !dbg !3 -``llvm.dbg.coroframe_entry`` -^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: llvm - - void @llvm.dbg.coroframe_entry(metadata, metadata, metadata) - -This intrinsic is equivalent to ``#dbg_coroframe_entry``: - -.. code-block:: llvm - - #dbg_coroframe_entry(i32 %i., !1, !DIExpression(), !2) - call void @llvm.dbg.coroframe_entry(metadata i32 %i., metadata !1, - metadata !DIExpression()), !dbg !2 - Object lifetimes and scoping ============================ diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 04377cd774993..172cb71286d0b 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -687,8 +687,6 @@ enum FunctionCodes { FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE = 64, // [DILocation, DILocalVariable, DIExpression, Value] FUNC_CODE_DEBUG_RECORD_LABEL = 65, // [DILocation, DILabel] - FUNC_CODE_DEBUG_RECORD_COROFRAME_ENTRY = - 66, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata] }; enum UseListCodes { diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index d79efdbddef16..e64cc0bff7068 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -1155,18 +1155,6 @@ namespace llvm { DIExpression *Expr, const DILocation *DL, InsertPosition InsertPt); - /// Insert a new llvm.dbg.coroframe_entry intrinsic call. - /// \param Storage llvm::Value of the variable - /// \param VarInfo Variable's debug info descriptor. - /// \param Expr A complex location expression. - /// \param DL Debug info location. - /// \param InsertPt Location for the new intrinsic. - LLVM_ABI DbgInstPtr insertCoroFrameEntry(llvm::Value *Storage, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - InsertPosition InsertPt); - /// Insert a new llvm.dbg.label intrinsic call. /// \param LabelInfo Label's debug info descriptor. /// \param DL Debug info location. diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index db0e28bb983a7..77cee875f16e7 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -44,15 +44,6 @@ class Module; LLVM_ABI TinyPtrVector findDbgDeclares(Value *V); /// As above, for DVRDeclares. LLVM_ABI TinyPtrVector findDVRDeclares(Value *V); -/// Finds dbg.coroframe_entry intrinsics declaring local variables as living in -/// the memory that 'V' points to. -// FIXME: Combine the findDbgCoroFrameEntrys and findDbgDeclares APIs into one -// that can take a 'kind' parameter, do the same for findDVRCoroFrameEntrys and -// findDVRCoroFrameEntrys -LLVM_ABI TinyPtrVector -findDbgCoroFrameEntrys(Value *V); -/// As above, for DVRCoroFrameEntrys. -LLVM_ABI TinyPtrVector findDVRCoroFrameEntrys(Value *V); /// As above, for DVRValues. LLVM_ABI TinyPtrVector findDVRValues(Value *V); diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 822e27140ed3e..e0292c2b8d2d2 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -282,7 +282,6 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { Declare, Value, Assign, - CoroFrameEntry, End, ///< Marks the end of the concrete types. Any, ///< To indicate all LocationTypes in searches. @@ -365,14 +364,6 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI, DbgVariableRecord &InsertBefore); - LLVM_ABI static DbgVariableRecord * - createDVRCoroFrameEntry(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI); - LLVM_ABI static DbgVariableRecord * - createDVRCoroFrameEntry(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI, - DbgVariableRecord &InsertBefore); - /// Iterator for ValueAsMetadata that internally uses direct pointer iteration /// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the /// ValueAsMetadata . @@ -423,9 +414,6 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { bool isDbgDeclare() const { return Type == LocationType::Declare; } bool isDbgValue() const { return Type == LocationType::Value; } - bool isDbgCoroFrameEntry() const { - return Type == LocationType::CoroFrameEntry; - } /// Get the locations corresponding to the variable referenced by the debug /// info intrinsic. Depending on the intrinsic, this could be the diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index fba729e2b8b9c..0318427bf8a1c 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -428,7 +428,6 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: case Intrinsic::dbg_assign: - case Intrinsic::dbg_coroframe_entry: return true; default: return false; @@ -465,26 +464,6 @@ class DbgDeclareInst : public DbgVariableIntrinsic { /// @} }; -/// This represents the llvm.dbg.coro instruction. -class DbgCoroFrameEntryInst : public DbgVariableIntrinsic { -public: - Value *getAddress() const { - assert(getNumVariableLocationOps() == 1 && - "dbg.coro must have exactly 1 location operand."); - return getVariableLocationOp(0); - } - - /// \name Casting methods - /// @{ - static bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::dbg_coroframe_entry; - } - static bool classof(const Value *V) { - return isa(V) && classof(cast(V)); - } - /// @} -}; - /// This represents the llvm.dbg.value instruction. class DbgValueInst : public DbgVariableIntrinsic { public: diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 24b2636eba1be..7218fe0b0fe98 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1474,10 +1474,6 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { llvm_metadata_ty]>; def int_dbg_label : DefaultAttrsIntrinsic<[], [llvm_metadata_ty]>; - def int_dbg_coroframe_entry : DefaultAttrsIntrinsic<[], - [llvm_metadata_ty, - llvm_metadata_ty, - llvm_metadata_ty]>; } //===------------------ Exception Handling Intrinsics----------------------===// diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp index 969830a2f1456..fe9e0ddca7091 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp @@ -272,7 +272,6 @@ GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(FUNC_CODE, INST_CALLBR) STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE) - STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_COROFRAME_ENTRY) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index ee29e6922bff8..d3a84ef5a3d07 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -6644,7 +6644,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) { case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE: case bitc::FUNC_CODE_DEBUG_RECORD_VALUE: case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE: - case bitc::FUNC_CODE_DEBUG_RECORD_COROFRAME_ENTRY: case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { // DbgVariableRecords are placed after the Instructions that they are // attached to. @@ -6661,8 +6660,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // ..., Value // dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) // ..., LocationMetadata - // dbg_coroframe_entry (FUNC_CODE_DEBUG_RECORD_COROFRAME_ENTRY) - // ..., LocationMetadata // dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) // ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata unsigned Slot = 0; @@ -6704,11 +6701,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) { DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL, DbgVariableRecord::LocationType::Declare); break; - case bitc::FUNC_CODE_DEBUG_RECORD_COROFRAME_ENTRY: - DVR = new DbgVariableRecord( - RawLocation, Var, Expr, DIL, - DbgVariableRecord::LocationType::CoroFrameEntry); - break; case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { DIAssignID *ID = cast(getFnMetadataByID(Record[Slot++])); DIExpression *AddrExpr = diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 9394887e1e029..7d9be3b910364 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3828,10 +3828,6 @@ void ModuleBitcodeWriter::writeFunction( } else if (DVR.isDbgDeclare()) { Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals); - } else if (DVR.isDbgCoroFrameEntry()) { - Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_COROFRAME_ENTRY, - Vals); } else { assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind"); Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 88b5c7ffab3d6..72f0b754baf85 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4877,9 +4877,6 @@ void AssemblyWriter::printDbgVariableRecord(const DbgVariableRecord &DVR) { case DbgVariableRecord::LocationType::Declare: Out << "declare"; break; - case DbgVariableRecord::LocationType::CoroFrameEntry: - Out << "coroframe_entry"; - break; case DbgVariableRecord::LocationType::Assign: Out << "assign"; break; diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index e3d4cb155b394..dad71785c699d 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -4507,11 +4507,6 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) { DbgVariableRecord::LocationType::Declare, unwrapMAVMetadataOp(CI, 0), unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2), nullptr, nullptr, nullptr, getDebugLocSafe(CI)); - } else if (Name == "coroframe_entry") { - DR = DbgVariableRecord::createUnresolvedDbgVariableRecord( - DbgVariableRecord::LocationType::CoroFrameEntry, - unwrapMAVMetadataOp(CI, 0), unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2), - nullptr, nullptr, nullptr, getDebugLocSafe(CI)); } else if (Name == "addr") { // Upgrade dbg.addr to dbg.value with DW_OP_deref. MDNode *ExprNode = unwrapMAVOp(CI, 2); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index e93fac0e7987e..fe767a21ccd36 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -1142,24 +1142,6 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, return DVR; } -DbgInstPtr DIBuilder::insertCoroFrameEntry(Value *Storage, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - InsertPosition InsertPt) { - assert(VarInfo && - "empty or invalid DILocalVariable* passed to dbg.corofame_entry"); - assert(DL && "Expected debug loc"); - assert(DL->getScope()->getSubprogram() == - VarInfo->getScope()->getSubprogram() && - "Expected matching subprograms"); - - DbgVariableRecord *DVR = - DbgVariableRecord::createDVRCoroFrameEntry(Storage, VarInfo, Expr, DL); - insertDbgVariableRecord(DVR, InsertPt); - return DVR; -} - void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR, InsertPosition InsertPt) { assert(InsertPt.isValid()); diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 66e385a7e7a94..84a56058de834 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -81,43 +81,6 @@ TinyPtrVector llvm::findDVRDeclares(Value *V) { return Declares; } -TinyPtrVector llvm::findDbgCoroFrameEntrys(Value *V) { - // This function is hot. Check whether the value has any metadata to avoid a - // DenseMap lookup. This check is a bitfield datamember lookup. - if (!V->isUsedByMetadata()) - return {}; - auto *L = ValueAsMetadata::getIfExists(V); - if (!L) - return {}; - auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L); - if (!MDV) - return {}; - - TinyPtrVector Coros; - for (User *U : MDV->users()) - if (auto *DDI = dyn_cast(U)) - Coros.push_back(DDI); - - return Coros; -} - -TinyPtrVector llvm::findDVRCoroFrameEntrys(Value *V) { - // This function is hot. Check whether the value has any metadata to avoid a - // DenseMap lookup. This check is a bitfield datamember lookup. - if (!V->isUsedByMetadata()) - return {}; - auto *L = ValueAsMetadata::getIfExists(V); - if (!L) - return {}; - - TinyPtrVector Coros; - for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers()) - if (DVR->getType() == DbgVariableRecord::LocationType::CoroFrameEntry) - Coros.push_back(DVR); - - return Coros; -} - TinyPtrVector llvm::findDVRValues(Value *V) { // This function is hot. Check whether the value has any metadata to avoid a // DenseMap lookup. This check is a bitfield datamember lookup. diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 39cecb6fa4445..2b9b0f958a171 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -41,9 +41,6 @@ DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI) case Intrinsic::dbg_declare: Type = LocationType::Declare; break; - case Intrinsic::dbg_coroframe_entry: - Type = LocationType::CoroFrameEntry; - break; case Intrinsic::dbg_assign: { Type = LocationType::Assign; const DbgAssignIntrinsic *Assign = @@ -212,22 +209,6 @@ DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV, return NewDVRDeclare; } -DbgVariableRecord * -DbgVariableRecord::createDVRCoroFrameEntry(Value *Address, DILocalVariable *DV, - DIExpression *Expr, - const DILocation *DI) { - return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI, - LocationType::CoroFrameEntry); -} - -DbgVariableRecord *DbgVariableRecord::createDVRCoroFrameEntry( - Value *Address, DILocalVariable *DV, DIExpression *Expr, - const DILocation *DI, DbgVariableRecord &InsertBefore) { - auto *NewDVRCoro = createDVRCoroFrameEntry(Address, DV, Expr, DI); - NewDVRCoro->insertBefore(&InsertBefore); - return NewDVRCoro; -} - DbgVariableRecord *DbgVariableRecord::createDVRAssign( Value *Val, DILocalVariable *Variable, DIExpression *Expression, DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression, @@ -435,10 +416,6 @@ DbgVariableRecord::createDebugIntrinsic(Module *M, case DbgVariableRecord::LocationType::Declare: IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare); break; - case DbgVariableRecord::LocationType::CoroFrameEntry: - IntrinsicFn = - Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_coroframe_entry); - break; case DbgVariableRecord::LocationType::Value: IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_value); break; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index ad9cb7a0b7987..781139628f0eb 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -193,9 +193,6 @@ struct VerifierSupport { case DbgVariableRecord::LocationType::Declare: *OS << "declare"; break; - case DbgVariableRecord::LocationType::CoroFrameEntry: - *OS << "coroframe_entry"; - break; case DbgVariableRecord::LocationType::Assign: *OS << "assign"; break; @@ -6888,8 +6885,6 @@ void Verifier::visit(DbgVariableRecord &DVR) { CheckDI(DVR.getType() == DbgVariableRecord::LocationType::Value || DVR.getType() == DbgVariableRecord::LocationType::Declare || - DVR.getType() == - DbgVariableRecord::LocationType::CoroFrameEntry || DVR.getType() == DbgVariableRecord::LocationType::Assign, "invalid #dbg record type", &DVR, DVR.getType(), BB, F); From 8ca72aee0bccc867ad592c95e7b1ed5c906b220e Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Sat, 22 Nov 2025 00:49:35 -0800 Subject: [PATCH 4/5] Add new llvm.dbg.declare_value intrinsic. (#168132) For swift async code, we need to use a debug intrinsic that behaves like an llvm.dbg.declare but can take any location type rather than just a pointer or integer. To solve this, a new debug instrinsic called llvm.dbg.declare_value has been created, which behaves exactly like an llvm.dbg.declare but can take non pointer and integer location types. More information here: https://discourse.llvm.org/t/rfc-introduce-new-llvm-dbg-coroframe-entry-intrinsic/88269 This is the first patch as part of a stack of patches, with the one succeeding it being: https://github.com/llvm/llvm-project/pull/168134 (cherry picked from commit 20ebc7ea8209cb8f1ff3916706b6e7d8232c9f3f) --- llvm/docs/SourceLevelDebugging.rst | 22 +++++++++++ llvm/include/llvm/Bitcode/LLVMBitCodes.h | 2 + llvm/include/llvm/IR/DIBuilder.h | 12 ++++++ llvm/include/llvm/IR/DebugInfo.h | 2 + .../include/llvm/IR/DebugProgramInstruction.h | 19 ++++++++-- llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 6 ++- llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp | 1 + llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 8 ++++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 ++ llvm/lib/IR/AsmWriter.cpp | 3 ++ llvm/lib/IR/DIBuilder.cpp | 18 +++++++++ llvm/lib/IR/DebugInfo.cpp | 17 +++++++++ llvm/lib/IR/DebugProgramInstruction.cpp | 20 ++++++++++ llvm/lib/IR/Verifier.cpp | 4 ++ llvm/test/Assembler/dbg_declare_value.ll | 37 +++++++++++++++++++ 16 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Assembler/dbg_declare_value.ll diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst index dfc8c53edbb8e..9353e6cfbb28d 100644 --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -310,6 +310,28 @@ directly, not its address. Note that the value operand of this intrinsic may be indirect (i.e, a pointer to the source variable), provided that interpreting the complex expression derives the direct value. + +``#dbg_declare_value`` +^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: llvm + + #dbg_declare_value([Value|MDNode], DILocalVariable, DIExpression, DILocation) + +This record provides information about a local element (e.g., variable). The +first argument is used to compute the value of the variable throughout the +entire function. The second argument is a +:ref:`local variable ` containing a description of the +variable. The third argument is a :ref:`complex expression `. The +foruth argument is a :ref:`source location `. A +``#dbg_declare_value`` record describes describes the *value* of a source +variable directly, not its address. The difference between a ``#dbg_value`` and +a ``#dbg_declare_value`` is that, just like a ``#dbg_declare``, a frontend +should generate exactly one ``#dbg_declare_value`` record. The idea is to have +``#dbg_declare`` guarantees but be able to describe a value rather than the +address of a value. + + ``#dbg_assign`` ^^^^^^^^^^^^^^^^^^^ .. toctree:: diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 172cb71286d0b..aead919f93a61 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -687,6 +687,8 @@ enum FunctionCodes { FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE = 64, // [DILocation, DILocalVariable, DIExpression, Value] FUNC_CODE_DEBUG_RECORD_LABEL = 65, // [DILocation, DILabel] + FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE = + 66, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata] }; enum UseListCodes { diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index e64cc0bff7068..1facf317dbb47 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -1155,6 +1155,18 @@ namespace llvm { DIExpression *Expr, const DILocation *DL, InsertPosition InsertPt); + /// Insert a new llvm.dbg.declare_value intrinsic call. + /// \param Storage llvm::Value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertPt Location for the new intrinsic. + LLVM_ABI DbgInstPtr insertDeclareValue(llvm::Value *Storage, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + InsertPosition InsertPt); + /// Insert a new llvm.dbg.label intrinsic call. /// \param LabelInfo Label's debug info descriptor. /// \param DL Debug info location. diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index 77cee875f16e7..7297dccf80a9d 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -46,6 +46,8 @@ LLVM_ABI TinyPtrVector findDbgDeclares(Value *V); LLVM_ABI TinyPtrVector findDVRDeclares(Value *V); /// As above, for DVRValues. LLVM_ABI TinyPtrVector findDVRValues(Value *V); +/// As above, for DVRDeclareValues. +LLVM_ABI TinyPtrVector findDVRDeclareValues(Value *V); /// Finds the llvm.dbg.value intrinsics describing a value. LLVM_ABI void findDbgValues( diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index e0292c2b8d2d2..1d5e52d3be9b0 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -282,6 +282,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { Declare, Value, Assign, + DeclareValue, End, ///< Marks the end of the concrete types. Any, ///< To indicate all LocationTypes in searches. @@ -364,6 +365,13 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI, DbgVariableRecord &InsertBefore); + LLVM_ABI static DbgVariableRecord * + createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI); + LLVM_ABI static DbgVariableRecord * + createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI, DbgVariableRecord &InsertBefore); + /// Iterator for ValueAsMetadata that internally uses direct pointer iteration /// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the /// ValueAsMetadata . @@ -414,6 +422,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { bool isDbgDeclare() const { return Type == LocationType::Declare; } bool isDbgValue() const { return Type == LocationType::Value; } + bool isDbgDeclareValue() const { return Type == LocationType::DeclareValue; } /// Get the locations corresponding to the variable referenced by the debug /// info intrinsic. Depending on the intrinsic, this could be the @@ -439,12 +448,16 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { bool hasValidLocation() const { return getVariableLocationOp(0) != nullptr; } /// Does this describe the address of a local variable. True for dbg.addr - /// and dbg.declare, but not dbg.value, which describes its value. + /// and dbg.declare, but not dbg.value or dbg.declare_value, which describes + /// its value. bool isAddressOfVariable() const { return Type == LocationType::Declare; } /// Determine if this describes the value of a local variable. It is false for - /// dbg.declare, but true for dbg.value, which describes its value. - bool isValueOfVariable() const { return Type == LocationType::Value; } + /// dbg.declare, but true for dbg.value and dbg.declare_value, which describes + /// its value. + bool isValueOfVariable() const { + return Type == LocationType::Value || Type == LocationType::DeclareValue; + } LocationType getType() const { return Type; } diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 5bdc29d03fbb1..2f71e99d9d98e 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -998,6 +998,7 @@ lltok::Kind LLLexer::LexIdentifier() { DBGRECORDTYPEKEYWORD(declare); DBGRECORDTYPEKEYWORD(assign); DBGRECORDTYPEKEYWORD(label); + DBGRECORDTYPEKEYWORD(declare_value); #undef DBGRECORDTYPEKEYWORD if (Keyword.starts_with("DIFlag")) { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 567a44741d9f8..381cc1ff9105e 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -7053,7 +7053,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { .Case("declare", RecordKind::ValueKind) .Case("value", RecordKind::ValueKind) .Case("assign", RecordKind::ValueKind) - .Case("label", RecordKind::LabelKind); + .Case("label", RecordKind::LabelKind) + .Case("declare_value", RecordKind::ValueKind); // Parsing labels is trivial; parse here and early exit, otherwise go into the // full DbgVariableRecord processing stage. @@ -7078,7 +7079,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { LocType ValueType = StringSwitch(Lex.getStrVal()) .Case("declare", LocType::Declare) .Case("value", LocType::Value) - .Case("assign", LocType::Assign); + .Case("assign", LocType::Assign) + .Case("declare_value", LocType::DeclareValue); Lex.Lex(); if (parseToken(lltok::lparen, "Expected '(' here")) diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp index fe9e0ddca7091..911ec7501eb8b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp @@ -272,6 +272,7 @@ GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(FUNC_CODE, INST_CALLBR) STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE_VALUE) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN) STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index d3a84ef5a3d07..cdac6504f99a3 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -6644,6 +6644,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE: case bitc::FUNC_CODE_DEBUG_RECORD_VALUE: case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE: + case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE: case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { // DbgVariableRecords are placed after the Instructions that they are // attached to. @@ -6660,6 +6661,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // ..., Value // dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) // ..., LocationMetadata + // dbg_declare_value (FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE) + // ..., LocationMetadata // dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) // ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata unsigned Slot = 0; @@ -6701,6 +6704,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) { DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL, DbgVariableRecord::LocationType::Declare); break; + case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE: + DVR = new DbgVariableRecord( + RawLocation, Var, Expr, DIL, + DbgVariableRecord::LocationType::DeclareValue); + break; case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { DIAssignID *ID = cast(getFnMetadataByID(Record[Slot++])); DIExpression *AddrExpr = diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 7d9be3b910364..3d758197c5853 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3828,6 +3828,9 @@ void ModuleBitcodeWriter::writeFunction( } else if (DVR.isDbgDeclare()) { Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals); + } else if (DVR.isDbgDeclareValue()) { + Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE, Vals); } else { assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind"); Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 72f0b754baf85..47bedc3d0735a 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4877,6 +4877,9 @@ void AssemblyWriter::printDbgVariableRecord(const DbgVariableRecord &DVR) { case DbgVariableRecord::LocationType::Declare: Out << "declare"; break; + case DbgVariableRecord::LocationType::DeclareValue: + Out << "declare_value"; + break; case DbgVariableRecord::LocationType::Assign: Out << "assign"; break; diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index fe767a21ccd36..2933a9ed2f24b 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -1142,6 +1142,24 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, return DVR; } +DbgInstPtr DIBuilder::insertDeclareValue(Value *Storage, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + InsertPosition InsertPt) { + assert(VarInfo && + "empty or invalid DILocalVariable* passed to dbg.declare_value"); + assert(DL && "Expected debug loc"); + assert(DL->getScope()->getSubprogram() == + VarInfo->getScope()->getSubprogram() && + "Expected matching subprograms"); + + DbgVariableRecord *DVR = + DbgVariableRecord::createDVRDeclareValue(Storage, VarInfo, Expr, DL); + insertDbgVariableRecord(DVR, InsertPt); + return DVR; +} + void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR, InsertPosition InsertPt) { assert(InsertPt.isValid()); diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 84a56058de834..c3fa35afa1098 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -81,6 +81,23 @@ TinyPtrVector llvm::findDVRDeclares(Value *V) { return Declares; } +TinyPtrVector llvm::findDVRDeclareValues(Value *V) { + // This function is hot. Check whether the value has any metadata to avoid a + // DenseMap lookup. This check is a bitfield datamember lookup. + if (!V->isUsedByMetadata()) + return {}; + auto *L = ValueAsMetadata::getIfExists(V); + if (!L) + return {}; + + TinyPtrVector DEclareValues; + for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers()) + if (DVR->getType() == DbgVariableRecord::LocationType::DeclareValue) + DEclareValues.push_back(DVR); + + return DEclareValues; +} + TinyPtrVector llvm::findDVRValues(Value *V) { // This function is hot. Check whether the value has any metadata to avoid a // DenseMap lookup. This check is a bitfield datamember lookup. diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 2b9b0f958a171..b5d88c8a4de9c 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -209,6 +209,22 @@ DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV, return NewDVRDeclare; } +DbgVariableRecord * +DbgVariableRecord::createDVRDeclareValue(Value *Address, DILocalVariable *DV, + DIExpression *Expr, + const DILocation *DI) { + return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI, + LocationType::DeclareValue); +} + +DbgVariableRecord *DbgVariableRecord::createDVRDeclareValue( + Value *Address, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI, DbgVariableRecord &InsertBefore) { + auto *NewDVRCoro = createDVRDeclareValue(Address, DV, Expr, DI); + NewDVRCoro->insertBefore(&InsertBefore); + return NewDVRCoro; +} + DbgVariableRecord *DbgVariableRecord::createDVRAssign( Value *Val, DILocalVariable *Variable, DIExpression *Expression, DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression, @@ -425,6 +441,10 @@ DbgVariableRecord::createDebugIntrinsic(Module *M, case DbgVariableRecord::LocationType::End: case DbgVariableRecord::LocationType::Any: llvm_unreachable("Invalid LocationType"); + break; + case DbgVariableRecord::LocationType::DeclareValue: + llvm_unreachable( + "#dbg_declare_value should never be converted to an intrinsic"); } // Create the intrinsic from this DbgVariableRecord's information, optionally diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 781139628f0eb..971b319adfe4e 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -193,6 +193,9 @@ struct VerifierSupport { case DbgVariableRecord::LocationType::Declare: *OS << "declare"; break; + case DbgVariableRecord::LocationType::DeclareValue: + *OS << "declare_value"; + break; case DbgVariableRecord::LocationType::Assign: *OS << "assign"; break; @@ -6885,6 +6888,7 @@ void Verifier::visit(DbgVariableRecord &DVR) { CheckDI(DVR.getType() == DbgVariableRecord::LocationType::Value || DVR.getType() == DbgVariableRecord::LocationType::Declare || + DVR.getType() == DbgVariableRecord::LocationType::DeclareValue || DVR.getType() == DbgVariableRecord::LocationType::Assign, "invalid #dbg record type", &DVR, DVR.getType(), BB, F); diff --git a/llvm/test/Assembler/dbg_declare_value.ll b/llvm/test/Assembler/dbg_declare_value.ll new file mode 100644 index 0000000000000..cacbfc6b0e6b0 --- /dev/null +++ b/llvm/test/Assembler/dbg_declare_value.ll @@ -0,0 +1,37 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +; CHECK: #dbg_declare_value(double %{{[0-9]+}}, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}}) + +; ModuleID = '/tmp/test.c' +source_filename = "/tmp/test.c" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "arm64-apple-macosx26.0.0" + +; Function Attrs: noinline nounwind optnone ssp uwtable(sync) +define void @foo(double noundef %0) #0 !dbg !9 { + #dbg_declare_value(double %0, !15, !DIExpression(), !16) + ret void, !dbg !21 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 22.0.0git (git@github.com:rastogishubham/llvm-project.git bacf99969b2f3e6db4cfcf536cce8b01ffd20aa0)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/") +!1 = !DIFile(filename: "/tmp/test.c", directory: "/Users/srastogi/Development/llvm-project-2/build_ninja", checksumkind: CSK_MD5, checksum: "fa15cf45ed4f9d805aab17eb7856a442") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{i32 7, !"frame-pointer", i32 4} +!8 = !{!"clang version 22.0.0git (git@github.com:rastogishubham/llvm-project.git bacf99969b2f3e6db4cfcf536cce8b01ffd20aa0)"} +!9 = distinct !DISubprogram(name: "foo", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14) +!10 = !DIFile(filename: "/tmp/test.c", directory: "", checksumkind: CSK_MD5, checksum: "fa15cf45ed4f9d805aab17eb7856a442") +!11 = !DISubroutineType(types: !12) +!12 = !{null, !13} +!13 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!14 = !{} +!15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13) +!16 = !DILocation(line: 1, column: 17, scope: !9) +!21 = !DILocation(line: 3, column: 1, scope: !9) From acd26d1a4200f662912509a00d037805b7914238 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Mon, 24 Nov 2025 09:37:41 -0800 Subject: [PATCH 5/5] Add support for llvm.dbg.declare_value in the CoroSplitter pass. (#168134) Make sure the CoroSplitter pass correctly handles `#dbg_declare_value` intrinsics. Which means, it should identify them, and convert them to `#dbg_declares` so that any subsequent passes do not need to be amended to support the `#dbg_declare_value` intrinsic. More information here: https://discourse.llvm.org/t/rfc-introduce-new-llvm-dbg-coroframe-entry-intrinsic/88269 This patch is the second and last in a stack of patches, with the one preceding it being: https://github.com/llvm/llvm-project/pull/168132 (cherry picked from commit 79c56e8f335b231d00b06c8031d5d4c31ceb7d96) --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 66 ++++++++++++++++-- .../Transforms/Coroutines/declare-value.ll | 68 +++++++++++++++++++ 2 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Transforms/Coroutines/declare-value.ll diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 68ce06637b277..bb85fb9e91a4d 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -555,6 +555,7 @@ static void cacheDIVar(FrameDataInfo &FrameData, }; CacheIt(findDbgDeclares(V)); CacheIt(findDVRDeclares(V)); + CacheIt(findDVRDeclareValues(V)); } } @@ -1156,6 +1157,47 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { for_each(DVRs, SalvageOne); } + TinyPtrVector DVRDeclareValues = + findDVRDeclareValues(Def); + // Try best to find dbg.declare_value. If the spill is a temp, there may + // not be a direct dbg.declare_value. Walk up the load chain to find one + // from an alias. + if (F->getSubprogram()) { + auto *CurDef = Def; + while (DVRDeclareValues.empty() && isa(CurDef)) { + auto *LdInst = cast(CurDef); + // Only consider ptr to ptr same type load. + if (LdInst->getPointerOperandType() != LdInst->getType()) + break; + CurDef = LdInst->getPointerOperand(); + if (!isa(CurDef)) + break; + DVRDeclareValues = findDVRDeclareValues(CurDef); + } + } + + auto SalvageOneCoro = [&](auto *DDI) { + // This dbg.declare_value is preserved for all coro-split function + // fragments. It will be unreachable in the main function, and + // processed by coro::salvageDebugInfo() by the Cloner. However, convert + // it to a dbg.declare to make sure future passes don't have to deal + // with a dbg.declare_value. + auto *VAM = ValueAsMetadata::get(CurrentReload); + Type *Ty = VAM->getValue()->getType(); + // If the metadata type is not a pointer, emit a dbg.value instead. + DbgVariableRecord *NewDVR = new DbgVariableRecord( + ValueAsMetadata::get(CurrentReload), DDI->getVariable(), + DDI->getExpression(), DDI->getDebugLoc(), + Ty->isPointerTy() ? DbgVariableRecord::LocationType::Declare + : DbgVariableRecord::LocationType::Value); + Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore( + NewDVR, Builder.GetInsertPoint()); + // This dbg.declare_value is for the main function entry point. It + // will be deleted in all coro-split functions. + coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/); + }; + for_each(DVRDeclareValues, SalvageOneCoro); + // If we have a single edge PHINode, remove it and replace it with a // reload from the coroutine frame. (We already took care of multi edge // PHINodes by normalizing them in the rewritePHIs function). @@ -1982,7 +2024,7 @@ void coro::salvageDebugInfo( Function *F = DVR.getFunction(); // Follow the pointer arithmetic all the way to the incoming // function argument and convert into a DIExpression. - bool SkipOutermostLoad = DVR.isDbgDeclare(); + bool SkipOutermostLoad = DVR.isDbgDeclare() || DVR.isDbgDeclareValue(); Value *OriginalStorage = DVR.getVariableLocationOp(0); auto SalvagedInfo = @@ -1996,10 +2038,11 @@ void coro::salvageDebugInfo( DVR.replaceVariableLocationOp(OriginalStorage, Storage); DVR.setExpression(Expr); - // We only hoist dbg.declare today since it doesn't make sense to hoist - // dbg.value since it does not have the same function wide guarantees that - // dbg.declare does. - if (DVR.getType() == DbgVariableRecord::LocationType::Declare) { + // We only hoist dbg.declare and dbg.declare_value today since it doesn't make + // sense to hoist dbg.value since it does not have the same function wide + // guarantees that dbg.declare does. + if (DVR.getType() == DbgVariableRecord::LocationType::Declare || + DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) { std::optional InsertPt; if (auto *I = dyn_cast(Storage)) { InsertPt = I->getInsertionPointAfterDef(); @@ -2014,6 +2057,19 @@ void coro::salvageDebugInfo( InsertPt = F->getEntryBlock().begin(); if (InsertPt) { DVR.removeFromParent(); + // If there is a dbg.declare_value being reinserted, insert it as a + // dbg.declare instead, so that subsequent passes don't have to deal with + // a dbg.declare_value. + if (DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) { + auto *MD = DVR.getRawLocation(); + if (auto *VAM = dyn_cast(MD)) { + Type *Ty = VAM->getValue()->getType(); + if (Ty->isPointerTy()) + DVR.Type = DbgVariableRecord::LocationType::Declare; + else + DVR.Type = DbgVariableRecord::LocationType::Value; + } + } (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt); } } diff --git a/llvm/test/Transforms/Coroutines/declare-value.ll b/llvm/test/Transforms/Coroutines/declare-value.ll new file mode 100644 index 0000000000000..94049c28169b9 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/declare-value.ll @@ -0,0 +1,68 @@ +;RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s + +; CHECK: %.debug = alloca double, align 8 +; CHECK-NEXT: #dbg_declare(ptr %{{.*}}, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}}) +; CHECK-NEXT: store double %{{[0-9]+}}, ptr %{{.*}}, align 8 +; CHECK-NEXT: #dbg_declare(ptr %arg, !{{[0-9]+}}, !DIExpression(DW_OP_plus_uconst, 24), !{{[0-9]+}}) + +; ModuleID = '/Users/srastogi/Development/llvm-project-2/llvm/test/Transforms/Coroutines/declare-value.ll' +source_filename = "/Users/srastogi/Development/llvm-project-2/llvm/test/Transforms/Coroutines/declare-value.ll" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" +target triple = "arm64-unknown" + +@coroutineATu = global <{ i32, i32 }> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @coroutineA to i64), i64 ptrtoint (ptr @coroutineATu to i64)) to i32), i32 16 }>, align 8 + +; Function Attrs: presplitcoroutine +define swifttailcc void @coroutineA(ptr swiftasync %arg, double %0) #0 !dbg !1 { + %var_with_dbg_value = alloca ptr, align 8 + %var_with_dbg_declare = alloca ptr, align 8 + #dbg_declare(ptr %var_with_dbg_declare, !5, !DIExpression(), !7) + #dbg_declare_value(double %0, !5, !DIExpression(), !7) + %i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineATu) + %i3 = call ptr @llvm.coro.begin(token %i2, ptr null) + %i7 = call ptr @llvm.coro.async.resume(), !dbg !7 + %i10 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %i7, ptr nonnull @__swift_async_resume_get_context, ptr nonnull @coroutineA.1, ptr %i7, i64 0, i64 0, ptr %arg), !dbg !7 + call void @dont_optimize(ptr %var_with_dbg_value, ptr %var_with_dbg_declare), !dbg !7 + unreachable, !dbg !7 +} + +define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) !dbg !8 { + ret ptr %arg, !dbg !9 +} + +define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) !dbg !10 { + ret void, !dbg !11 +} + +declare void @dont_optimize(ptr, ptr) + +; Function Attrs: nomerge nounwind +declare ptr @llvm.coro.async.resume() #1 + +; Function Attrs: nounwind +declare ptr @llvm.coro.begin(token, ptr writeonly) #2 + +; Function Attrs: nounwind +declare token @llvm.coro.id.async(i32, i32, i32, ptr) #2 + +; Function Attrs: nomerge nounwind +declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #1 + +attributes #0 = { presplitcoroutine } +attributes #1 = { nomerge nounwind } +attributes #2 = { nounwind } + +!llvm.module.flags = !{!0} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4) +!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +!3 = !DIFile(filename: "blah", directory: "") +!4 = !{} +!5 = !DILocalVariable(scope: !1, type: !6) +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Klass") +!7 = !DILocation(line: 0, scope: !1) +!8 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2) +!9 = !DILocation(line: 0, scope: !8) +!10 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2) +!11 = !DILocation(line: 0, scope: !10) \ No newline at end of file