-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RemoveDIs][DebugInfo][IR] Add parsing for non-intrinsic debug values #79818
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
Changes from all commits
df8fa60
617b529
c6e5aff
ac969d3
2e929cb
f1903e0
3bee366
ea2a924
b56190d
5702fea
758ef7c
d87a9aa
6e90f7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,13 +62,24 @@ static cl::opt<bool> AllowIncompleteIR( | |
"Allow incomplete IR on a best effort basis (references to unknown " | ||
"metadata will be dropped)")); | ||
|
||
extern llvm::cl::opt<bool> UseNewDbgInfoFormat; | ||
|
||
static std::string getTypeString(Type *T) { | ||
std::string Result; | ||
raw_string_ostream Tmp(Result); | ||
Tmp << *T; | ||
return Tmp.str(); | ||
} | ||
|
||
// Currently, we should always process modules in the old debug info format by | ||
// default regardless of the module's format in IR; convert it to the old format | ||
// here. | ||
bool finalizeDebugInfoFormat(Module *M) { | ||
if (M) | ||
M->setIsNewDbgInfoFormat(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't it use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just due to an awkward combination of factors at the moment: not all LLVM features internally support the new debug info format yet, so we use In short, the declaration is the mistake here - I'll remove it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok! |
||
return false; | ||
} | ||
|
||
/// Run: module ::= toplevelentity* | ||
bool LLParser::Run(bool UpgradeDebugInfo, | ||
DataLayoutCallbackTy DataLayoutCallback) { | ||
|
@@ -86,7 +97,7 @@ bool LLParser::Run(bool UpgradeDebugInfo, | |
} | ||
|
||
return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || | ||
validateEndOfIndex(); | ||
validateEndOfIndex() || finalizeDebugInfoFormat(M); | ||
} | ||
|
||
bool LLParser::parseStandaloneConstantValue(Constant *&C, | ||
|
@@ -6041,6 +6052,17 @@ bool LLParser::parseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, | |
return false; | ||
} | ||
|
||
bool isOldDbgFormatIntrinsic(StringRef Name) { | ||
// Exit early for the common (non-debug-intrinsic) case. | ||
// We can make this the only check when we begin supporting all "llvm.dbg" | ||
// intrinsics in the new debug info format. | ||
if (!Name.starts_with("llvm.dbg.")) | ||
return false; | ||
Intrinsic::ID FnID = Function::lookupIntrinsicID(Name); | ||
return FnID == Intrinsic::dbg_declare || FnID == Intrinsic::dbg_value || | ||
FnID == Intrinsic::dbg_assign; | ||
} | ||
|
||
/// FunctionHeader | ||
/// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility | ||
/// OptionalCallingConv OptRetAttrs OptUnnamedAddr Type GlobalName | ||
|
@@ -6390,9 +6412,31 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { | |
|
||
std::string NameStr; | ||
|
||
// parse the instructions in this block until we get a terminator. | ||
// Parse the instructions and debug values in this block until we get a | ||
// terminator. | ||
Instruction *Inst; | ||
auto DeleteDbgRecord = [](DbgRecord *DR) { DR->deleteRecord(); }; | ||
using DbgRecordPtr = std::unique_ptr<DbgRecord, decltype(DeleteDbgRecord)>; | ||
SmallVector<DbgRecordPtr> TrailingDbgRecord; | ||
do { | ||
// Handle debug records first - there should always be an instruction | ||
// following the debug records, i.e. they cannot appear after the block | ||
// terminator. | ||
while (Lex.getKind() == lltok::hash) { | ||
if (SeenOldDbgInfoFormat) | ||
return error(Lex.getLoc(), "debug record should not appear in a module " | ||
"containing debug info intrinsics"); | ||
SeenNewDbgInfoFormat = true; | ||
Lex.Lex(); | ||
if (!M->IsNewDbgInfoFormat) | ||
M->convertToNewDbgValues(); | ||
|
||
DbgRecord *DR; | ||
if (parseDebugRecord(DR, PFS)) | ||
return true; | ||
TrailingDbgRecord.emplace_back(DR, DeleteDbgRecord); | ||
} | ||
|
||
// This instruction may have three possibilities for a name: a) none | ||
// specified, b) name specified "%foo =", c) number specified: "%4 =". | ||
LocTy NameLoc = Lex.getLoc(); | ||
|
@@ -6437,11 +6481,121 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { | |
// Set the name on the instruction. | ||
if (PFS.setInstName(NameID, NameStr, NameLoc, Inst)) | ||
return true; | ||
|
||
// Attach any preceding debug values to this instruction. | ||
for (DbgRecordPtr &DR : TrailingDbgRecord) | ||
BB->insertDPValueBefore(DR.release(), Inst->getIterator()); | ||
TrailingDbgRecord.clear(); | ||
} while (!Inst->isTerminator()); | ||
|
||
assert(TrailingDbgRecord.empty() && | ||
"All debug values should have been attached to an instruction."); | ||
|
||
return false; | ||
} | ||
|
||
/// parseDebugRecord | ||
/// ::= #dbg_label '(' MDNode ')' | ||
/// ::= #dbg_type '(' Metadata ',' MDNode ',' Metadata ',' | ||
/// (MDNode ',' Metadata ',' Metadata ',')? MDNode ')' | ||
bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { | ||
using RecordKind = DbgRecord::Kind; | ||
using LocType = DPValue::LocationType; | ||
LocTy DPVLoc = Lex.getLoc(); | ||
if (Lex.getKind() != lltok::DbgRecordType) | ||
return error(DPVLoc, "expected debug record type here"); | ||
RecordKind RecordType = StringSwitch<RecordKind>(Lex.getStrVal()) | ||
.Case("declare", RecordKind::ValueKind) | ||
.Case("value", RecordKind::ValueKind) | ||
.Case("assign", RecordKind::ValueKind) | ||
.Case("label", RecordKind::LabelKind); | ||
|
||
// Parsing labels is trivial; parse here and early exit, otherwise go into the | ||
// full DPValue processing stage. | ||
if (RecordType == RecordKind::LabelKind) { | ||
Lex.Lex(); | ||
if (parseToken(lltok::lparen, "Expected '(' here")) | ||
return true; | ||
MDNode *Label; | ||
if (parseMDNode(Label)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
MDNode *DbgLoc; | ||
if (parseMDNode(DbgLoc)) | ||
return true; | ||
if (parseToken(lltok::rparen, "Expected ')' here")) | ||
return true; | ||
DR = DPLabel::createUnresolvedDPLabel(Label, DbgLoc); | ||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: braces |
||
|
||
LocType ValueType = StringSwitch<LocType>(Lex.getStrVal()) | ||
.Case("declare", LocType::Declare) | ||
.Case("value", LocType::Value) | ||
.Case("assign", LocType::Assign); | ||
|
||
Lex.Lex(); | ||
if (parseToken(lltok::lparen, "Expected '(' here")) | ||
return true; | ||
|
||
// Parse Value field. | ||
Metadata *ValLocMD; | ||
if (parseMetadata(ValLocMD, &PFS)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
|
||
// Parse Variable field. | ||
MDNode *Variable; | ||
if (parseMDNode(Variable)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
|
||
// Parse Expression field. | ||
MDNode *Expression; | ||
if (parseMDNode(Expression)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
|
||
// Parse additional fields for #dbg_assign. | ||
MDNode *AssignID = nullptr; | ||
Metadata *AddressLocation = nullptr; | ||
MDNode *AddressExpression = nullptr; | ||
if (ValueType == LocType::Assign) { | ||
// Parse DIAssignID. | ||
if (parseMDNode(AssignID)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
|
||
// Parse address ValueAsMetadata. | ||
if (parseMetadata(AddressLocation, &PFS)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
|
||
// Parse address DIExpression. | ||
if (parseMDNode(AddressExpression)) | ||
return true; | ||
if (parseToken(lltok::comma, "Expected ',' here")) | ||
return true; | ||
} | ||
|
||
/// Parse DILocation. | ||
MDNode *DebugLoc; | ||
if (parseMDNode(DebugLoc)) | ||
return true; | ||
|
||
if (parseToken(lltok::rparen, "Expected ')' here")) | ||
return true; | ||
DR = DPValue::createUnresolvedDPValue(ValueType, ValLocMD, Variable, | ||
Expression, AssignID, AddressLocation, | ||
AddressExpression, DebugLoc); | ||
return false; | ||
} | ||
//===----------------------------------------------------------------------===// | ||
// Instruction Parsing. | ||
//===----------------------------------------------------------------------===// | ||
|
@@ -7669,6 +7823,16 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, | |
} | ||
CI->setFastMathFlags(FMF); | ||
} | ||
|
||
if (CalleeID.Kind == ValID::t_GlobalName && | ||
isOldDbgFormatIntrinsic(CalleeID.StrVal)) { | ||
if (SeenNewDbgInfoFormat) { | ||
CI->deleteValue(); | ||
return error(CallLoc, "llvm.dbg intrinsic should not appear in a module " | ||
"using non-intrinsic debug info"); | ||
} | ||
SeenOldDbgInfoFormat = true; | ||
} | ||
CI->setAttributes(PAL); | ||
ForwardRefAttrGroups[CI] = FwdRefAttrGrps; | ||
Inst = CI; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be updating these BNF descriptions too? (probably just a case of adding '#'?