[llvm] Create llvm.dbg.declare_value and add it to the CoroSplitter Pass (PR #164953)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 24 03:38:17 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-coroutines

Author: Shubham Sandeep Rastogi (rastogishubham)

<details>
<summary>Changes</summary>

With RFC: https://discourse.llvm.org/t/rfc-introduce-new-llvm-dbg-coroframe-entry-intrinsic/88269, we introduced the concept for a new debug intrinsic called llvm.dbg.declare_value.

This is necessary because, instead of using a stack frame, Coroutines store local variables in a heap data structure called the coroutine frame. To describe variables in a coroutine frame we would want the semantics of #dbg_declares instead of #dbg_values, because of the guarantee that there should only be one #dbg_declare for a variable in a function. However, because it is meant to refer to stack frames, the location of a #dbg_declare must be a pointer. That is typically true after the CoroSplitter pass runs, but not before.

However, with commit [20507a9e95a08069863e9910a688a38370d58952](https://github.com/llvm/llvm-project/commit/20507a9e95a08069863e9910a688a38370d58952) there is a new check in the verifier that ensures that #dbg_declare always have a location that is a pointer. This causes an immediate crash in the compiler when swift hands off the generated IR to LLVM.

To fix this, we propose a new intrinsic called llvm.dbg.declare_value or #dbg_declare_value. This intrinsic will behave exactly like a #dbg_declare, however, it will not have the restriction of a ptr only location as a #dbg_declare.

The CoroSplit pass will transform any #dbg_declare_value intrinsics just like it did with #dbg_declares, however, crucially, after fixing up the location type, it will also re-emit them as #dbg_declares, so that we don’t have to teach subsequent passes, such as InstCombine, about what a #dbg_declare_value is.

This patch implements the new #dbg_declare_value intrinsic and adds support for it in the corosplitter pass.

---

Patch is 22.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/164953.diff


18 Files Affected:

- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+2) 
- (modified) llvm/include/llvm/IR/DIBuilder.h (+12) 
- (modified) llvm/include/llvm/IR/DebugInfo.h (+2) 
- (modified) llvm/include/llvm/IR/DebugProgramInstruction.h (+9) 
- (modified) llvm/include/llvm/IR/IntrinsicInst.h (+21) 
- (modified) llvm/include/llvm/IR/Intrinsics.td (+4) 
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+1) 
- (modified) llvm/lib/AsmParser/LLParser.cpp (+4-2) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp (+1) 
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+8) 
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+3) 
- (modified) llvm/lib/IR/AsmWriter.cpp (+3) 
- (modified) llvm/lib/IR/AutoUpgrade.cpp (+5) 
- (modified) llvm/lib/IR/DIBuilder.cpp (+18) 
- (modified) llvm/lib/IR/DebugInfo.cpp (+17) 
- (modified) llvm/lib/IR/DebugProgramInstruction.cpp (+23) 
- (modified) llvm/lib/IR/Verifier.cpp (+4) 
- (modified) llvm/lib/Transforms/Coroutines/CoroFrame.cpp (+61-5) 


``````````diff
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 464f475098ec5..1fb8f8f779322 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -688,6 +688,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 f3839c9694f34..e56c74c20a029 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -1151,6 +1151,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 220e4c1cad4f7..d75820add7254 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -44,6 +44,8 @@ class Module;
 LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V);
 /// As above, for DVRValues.
 LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRValues(Value *V);
+/// As above, for DVRCoroFrameEntrys.
+LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclareValues(Value *V);
 
 /// Finds the debug info records describing a value.
 LLVM_ABI void
diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h
index 457c60e3bc929..186e8f312c4c9 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
diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 0622bfae2c845..589e2a65a6908 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -428,6 +428,7 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
     case Intrinsic::dbg_declare:
     case Intrinsic::dbg_value:
     case Intrinsic::dbg_assign:
+    case Intrinsic::dbg_declare_value:
       return true;
     default:
       return false;
@@ -464,6 +465,26 @@ class DbgDeclareInst : public DbgVariableIntrinsic {
   /// @}
 };
 
+/// This represents the llvm.dbg.declare_value instruction.
+class DbgDeclareValueInst : public DbgVariableIntrinsic {
+public:
+  Value *getAddress() const {
+    assert(getNumVariableLocationOps() == 1 &&
+           "dbg.declare_value must have exactly 1 location operand.");
+    return getVariableLocationOp(0);
+  }
+
+  /// \name Casting methods
+  /// @{
+  static bool classof(const IntrinsicInst *I) {
+    return I->getIntrinsicID() == Intrinsic::dbg_declare_value;
+  }
+  static bool classof(const Value *V) {
+    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(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 4d59ee8676b9e..ca43df41b8ecc 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1447,6 +1447,10 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
                                         llvm_metadata_ty]>;
   def int_dbg_label        : DefaultAttrsIntrinsic<[],
                                        [llvm_metadata_ty]>;
+  def int_dbg_declare_value : DefaultAttrsIntrinsic<[],
+                                       [llvm_metadata_ty,
+                                        llvm_metadata_ty,
+                                        llvm_metadata_ty]>;
 }
 
 //===------------------ Exception Handling Intrinsics----------------------===//
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 7a6c19ece92ac..940f7b53c8243 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -1005,6 +1005,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 5164cec33e6f5..64cda950c7858 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -7148,7 +7148,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.
@@ -7173,7 +7174,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) {
   LocType ValueType = StringSwitch<LocType>(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 466dcb02696f4..5a2bc86d80a55 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -6653,6 +6653,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.
@@ -6669,6 +6670,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;
@@ -6710,6 +6713,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<DIAssignID>(getFnMetadataByID(Record[Slot++]));
         DIExpression *AddrExpr =
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 61aa7c2f5af53..c71fd7ad11dde 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -3841,6 +3841,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 488b078ab6caf..eb89b663da084 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -4841,6 +4841,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/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index b838e36c8824f..513baeee13443 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4623,6 +4623,11 @@ 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 == "declare_value") {
+    DR = DbgVariableRecord::createUnresolvedDbgVariableRecord(
+        DbgVariableRecord::LocationType::DeclareValue,
+        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 07a870f0630a5..fdce3aaf35342 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -1145,6 +1145,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 58836068a4929..abf18be60a9bb 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -63,6 +63,23 @@ TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
   return Declares;
 }
 
+TinyPtrVector<DbgVariableRecord *> 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<DbgVariableRecord *> Coros;
+  for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers())
+    if (DVR->getType() == DbgVariableRecord::LocationType::DeclareValue)
+      Coros.push_back(DVR);
+
+  return Coros;
+}
+
 TinyPtrVector<DbgVariableRecord *> 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..0ab526b263911 100644
--- a/llvm/lib/IR/DebugProgramInstruction.cpp
+++ b/llvm/lib/IR/DebugProgramInstruction.cpp
@@ -41,6 +41,9 @@ DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI)
   case Intrinsic::dbg_declare:
     Type = LocationType::Declare;
     break;
+  case Intrinsic::dbg_declare_value:
+    Type = LocationType::DeclareValue;
+    break;
   case Intrinsic::dbg_assign: {
     Type = LocationType::Assign;
     const DbgAssignIntrinsic *Assign =
@@ -209,6 +212,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,
@@ -416,6 +435,10 @@ DbgVariableRecord::createDebugIntrinsic(Module *M,
   case DbgVariableRecord::LocationType::Declare:
     IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare);
     break;
+  case DbgVariableRecord::LocationType::DeclareValue:
+    IntrinsicFn =
+        Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare_value);
+    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 7917712846990..604e7613f0532 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -192,6 +192,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;
@@ -7024,6 +7027,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/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index c89af688a69ca..b07fa644baa10 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -554,6 +554,7 @@ static void cacheDIVar(FrameDataInfo &FrameData,
         DIVarCache.insert({V, (*I)->getVariable()});
     };
     CacheIt(findDVRDeclares(V));
+    CacheIt(findDVRDeclareValues(V));
   }
 }
 
@@ -1142,6 +1143,47 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
         for_each(DVRs, SalvageOne);
       }
 
+      TinyPtrVector<DbgVariableRecord *> 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<LoadInst>(CurDef)) {
+          auto *LdInst = cast<LoadInst>(CurDef);
+          // Only consider ptr to ptr same type load.
+          if (LdInst->getPointerOperandType() != LdInst->getType())
+            break;
+          CurDef = LdInst->getPointerOperand();
+          if (!isa<AllocaInst, LoadInst>(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::Locati...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/164953


More information about the llvm-commits mailing list