-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Create llvm.dbg.declare_value and add it to the CoroSplitter Pass #164953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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.
Make sure the CoroSplitter pass correctly handles llvm.dbg.declare_value intrinsics. Also, convert them to llvm.dbg.declares so that any subsquent passes do not need to be amended to support the llvm.dbg.declare_value intrinsic.
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-coroutines Author: Shubham Sandeep Rastogi (rastogishubham) ChangesWith 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 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:
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]
|
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 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.