-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RemoveDIs] Read/write DbgRecords directly from/to bitcode #83251
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
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 |
---|---|---|
|
@@ -99,6 +99,9 @@ namespace llvm { | |
extern FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold; | ||
} | ||
|
||
extern bool WriteNewDbgInfoFormatToBitcode; | ||
extern llvm::cl::opt<bool> UseNewDbgInfoFormat; | ||
|
||
namespace { | ||
|
||
/// These are manifest constants used by the bitcode writer. They do not need to | ||
|
@@ -128,6 +131,7 @@ enum { | |
FUNCTION_INST_RET_VAL_ABBREV, | ||
FUNCTION_INST_UNREACHABLE_ABBREV, | ||
FUNCTION_INST_GEP_ABBREV, | ||
FUNCTION_DEBUG_RECORD_VALUE_ABBREV, | ||
}; | ||
|
||
/// Abstract class to manage the bitcode writing, subclassed for each bitcode | ||
|
@@ -3512,25 +3516,95 @@ void ModuleBitcodeWriter::writeFunction( | |
NeedsMetadataAttachment |= I.hasMetadataOtherThanDebugLoc(); | ||
|
||
// If the instruction has a debug location, emit it. | ||
DILocation *DL = I.getDebugLoc(); | ||
if (!DL) | ||
continue; | ||
|
||
if (DL == LastDL) { | ||
// Just repeat the same debug loc as last time. | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); | ||
continue; | ||
if (DILocation *DL = I.getDebugLoc()) { | ||
if (DL == LastDL) { | ||
// Just repeat the same debug loc as last time. | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); | ||
} else { | ||
Vals.push_back(DL->getLine()); | ||
Vals.push_back(DL->getColumn()); | ||
Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); | ||
Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); | ||
Vals.push_back(DL->isImplicitCode()); | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); | ||
Vals.clear(); | ||
LastDL = DL; | ||
} | ||
} | ||
|
||
Vals.push_back(DL->getLine()); | ||
Vals.push_back(DL->getColumn()); | ||
Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); | ||
Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); | ||
Vals.push_back(DL->isImplicitCode()); | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); | ||
Vals.clear(); | ||
|
||
LastDL = DL; | ||
// If the instruction has DbgRecords attached to it, emit them. Note that | ||
// they come after the instruction so that it's easy to attach them again | ||
// when reading the bitcode, even though conceptually the debug locations | ||
// start "before" the instruction. | ||
if (I.hasDbgRecords() && WriteNewDbgInfoFormatToBitcode) { | ||
/// Try to push the value only (unwrapped), otherwise push the | ||
/// metadata wrapped value. Returns true if the value was pushed | ||
/// without the ValueAsMetadata wrapper. | ||
auto PushValueOrMetadata = [&Vals, InstID, | ||
this](Metadata *RawLocation) { | ||
assert(RawLocation && "RawLocation unexpectedly null in DPValue"); | ||
if (ValueAsMetadata *VAM = dyn_cast<ValueAsMetadata>(RawLocation)) { | ||
SmallVector<unsigned, 2> ValAndType; | ||
// If the value is a fwd-ref the type is also pushed. We don't | ||
// want the type, so fwd-refs are kept wrapped (pushValueAndType | ||
// returns false if the value is pushed without type). | ||
if (!pushValueAndType(VAM->getValue(), InstID, ValAndType)) { | ||
Comment on lines
+3548
to
+3551
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. If I'm reading this right, we'll only encode a Value reference if it wouldn't have the type, and so isn't a fwd-dec? Seems alright to me; IMO we have the ability to choose how these things get encoded. 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. Yeah that's right. It saves us needing to encode the fwd-ref type, which would result in an extra field in the abbrev that is nonzero for < 1% of records. |
||
Vals.push_back(ValAndType[0]); | ||
return true; | ||
} | ||
} | ||
// The metadata is a DIArgList, or ValueAsMetadata wrapping a | ||
// fwd-ref. Push the metadata ID. | ||
Vals.push_back(VE.getMetadataID(RawLocation)); | ||
return false; | ||
}; | ||
|
||
// Write out non-instruction debug information attached to this | ||
// instruction. Write it after the instruction so that it's easy to | ||
// re-attach to the instruction reading the records in. | ||
for (DbgRecord &DR : I.DbgMarker->getDbgRecordRange()) { | ||
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { | ||
Vals.push_back(VE.getMetadataID(&*DPL->getDebugLoc())); | ||
Vals.push_back(VE.getMetadataID(DPL->getLabel())); | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_LABEL, Vals); | ||
Vals.clear(); | ||
continue; | ||
} | ||
|
||
// First 3 fields are common to all kinds: | ||
// DILocation, DILocalVariable, DIExpression | ||
// dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE) | ||
// ..., LocationMetadata | ||
// dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE - abbrev'd) | ||
// ..., Value | ||
// dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) | ||
// ..., LocationMetadata | ||
// dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) | ||
// ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata | ||
DPValue &DPV = cast<DPValue>(DR); | ||
Vals.push_back(VE.getMetadataID(&*DPV.getDebugLoc())); | ||
Vals.push_back(VE.getMetadataID(DPV.getVariable())); | ||
Vals.push_back(VE.getMetadataID(DPV.getExpression())); | ||
if (DPV.isDbgValue()) { | ||
if (PushValueOrMetadata(DPV.getRawLocation())) | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE, Vals, | ||
FUNCTION_DEBUG_RECORD_VALUE_ABBREV); | ||
else | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE, Vals); | ||
} else if (DPV.isDbgDeclare()) { | ||
Vals.push_back(VE.getMetadataID(DPV.getRawLocation())); | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals); | ||
} else { | ||
assert(DPV.isDbgAssign() && "Unexpected DbgRecord kind"); | ||
Vals.push_back(VE.getMetadataID(DPV.getRawLocation())); | ||
Vals.push_back(VE.getMetadataID(DPV.getAssignID())); | ||
Vals.push_back(VE.getMetadataID(DPV.getAddressExpression())); | ||
Vals.push_back(VE.getMetadataID(DPV.getRawAddress())); | ||
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN, Vals); | ||
} | ||
Vals.clear(); | ||
} | ||
} | ||
} | ||
|
||
if (BlockAddress *BA = BlockAddress::lookup(&BB)) { | ||
|
@@ -3771,7 +3845,17 @@ void ModuleBitcodeWriter::writeBlockInfo() { | |
FUNCTION_INST_GEP_ABBREV) | ||
llvm_unreachable("Unexpected abbrev ordering!"); | ||
} | ||
|
||
{ | ||
auto Abbv = std::make_shared<BitCodeAbbrev>(); | ||
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE)); | ||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // dbgloc | ||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // var | ||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // expr | ||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // val | ||
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != | ||
FUNCTION_DEBUG_RECORD_VALUE_ABBREV) | ||
llvm_unreachable("Unexpected abbrev ordering! 1"); | ||
} | ||
Stream.ExitBlock(); | ||
} | ||
|
||
|
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.
is it alright to feed intrinsic-mode code into the convert-from-removedis-mode utilities? I can see how it'd work.
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.
Yeah,
convertFromNewDbgValues
doesn't do any checking. It just converts DbgRecords to intrinsics. It doesn't do anything / doesn't care if it sees existing intrinsics.