Skip to content

Commit

Permalink
Reland "[DebugMetadata][DwarfDebug] Fix DWARF emisson of function-loc…
Browse files Browse the repository at this point in the history
…al imported entities (3/7)"

Run split-dwarf-local-impor3.ll only on x86_64-linux.
  • Loading branch information
dzhidzhoev committed Jun 15, 2023
1 parent 9b08c8a commit fcc3981
Show file tree
Hide file tree
Showing 35 changed files with 768 additions and 278 deletions.
41 changes: 20 additions & 21 deletions clang/test/CodeGenCXX/debug-info-namespace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,44 +81,43 @@ void C::c() {}
// CHECK: !DINamespace(scope: null)
// CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit(
// CHECK-SAME: imports: [[MODULES:![0-9]*]]
// CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]], [[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]
// CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]]}
// CHECK: [[M1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CTXT]], entity: [[NS]], file: [[FOOCPP]], line: 15)

// CHECK: [[M2]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[CTXT]],
// CHECK: [[M3]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "E", scope: [[CU]], entity: [[CTXT]], file: [[FOOCPP]], line: 19)
// CHECK: [[M4]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[LEX2:![0-9]+]], entity: [[NS]], file: [[FOOCPP]], line: 23)
// CHECK: [[M4]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]]
// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4
// CHECK-SAME: DISPFlagDefinition
// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition
// CHECK-SAME: retainedNodes: [[FUNC_NODES:![0-9]*]]
// CHECK: [[FUNC_NODES]] = !{[[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]}
// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[LEX2:![0-9]+]], entity: [[NS]], file: [[FOOCPP]], line: 23)
// CHECK: [[LEX2]] = distinct !DILexicalBlock(scope: [[LEX1:![0-9]+]], file: [[FOOCPP]],
// CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC:![0-9]+]], file: [[FOOCPP]],

// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition
// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT:![0-9]+]],
// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27)
// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT]],
// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27)
// CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo",
// CHECK-SAME: line: 5
// CHECK-SAME: DIFlagFwdDecl
// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:![0-9]+]]
// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:![0-9]+]]
// CHECK: [[BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar",
// CHECK-SAME: line: 6
// CHECK-SAME: DIFlagFwdDecl

// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1:![0-9]+]]
// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4
// CHECK-SAME: DISPFlagDefinition
// CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]]
// CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]]
// CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1]]
// CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]]
// CHECK: [[M11]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]]
// CHECK: [[BAZ]] = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", scope: [[NS]], file: [[FOOCPP]],
// CHECK-SAME: baseType: [[BAR]]
// CHECK: [[M11]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "X", scope: [[FUNC]], entity: [[CTXT]]
// CHECK: [[M12]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "Y", scope: [[FUNC]], entity: [[M11]]
// CHECK: [[M13]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_DECL:![0-9]+]]
// CHECK: [[M12]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "X", scope: [[FUNC]], entity: [[CTXT]]
// CHECK: [[M13]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "Y", scope: [[FUNC]], entity: [[M12]]
// CHECK: [[M14]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_DECL:![0-9]+]]
// CHECK: [[VAR_DECL]] = !DIGlobalVariable(name: "var_decl", linkageName: "{{[^"]*var_decl[^"]*}}", scope: [[NS]],{{.*}} line: 8,
// CHECK: [[M14]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_DECL:![0-9]+]]
// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_DECL:![0-9]+]]
// CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func_decl",
// CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9
// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]]
// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]]
// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]]
// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]]
// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} DISPFlagDefinition
// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]]
// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} DISPFlagDefinition
// CHECK: ![[C]] = !DINamespace(name: "C",

Expand Down
11 changes: 9 additions & 2 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace llvm {
SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
SmallVector<DISubprogram *, 4> AllSubprograms;
SmallVector<Metadata *, 4> AllGVs;
SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
SmallVector<TrackingMDNodeRef, 4> ImportedModules;
/// Map Macro parent (which can be DIMacroFile or nullptr) to a list of
/// Metadata all of type DIMacroNode.
/// DIMacroNode's with nullptr parent are DICompileUnit direct children.
Expand All @@ -64,14 +64,21 @@ namespace llvm {
SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
bool AllowUnresolvedNodes;

/// Each subprogram's preserved local variables and labels.
/// Each subprogram's preserved local variables, labels and imported
/// entities.
///
/// Do not use a std::vector. Some versions of libc++ apparently copy
/// instead of move on grow operations, and TrackingMDRef is expensive to
/// copy.
DenseMap<DISubprogram *, SmallVector<TrackingMDNodeRef, 4>>
SubprogramTrackedNodes;

SmallVectorImpl<TrackingMDNodeRef> &
getImportTrackingVector(const DIScope *S) {
return isa_and_nonnull<DILocalScope>(S)
? getSubprogramNodesTrackingVector(S)
: ImportedModules;
}
SmallVectorImpl<TrackingMDNodeRef> &
getSubprogramNodesTrackingVector(const DIScope *S) {
return SubprogramTrackedNodes[cast<DILocalScope>(S)->getSubprogram()];
Expand Down
84 changes: 84 additions & 0 deletions llvm/lib/Bitcode/Reader/MetadataLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
Expand Down Expand Up @@ -53,6 +54,7 @@
#include <deque>
#include <iterator>
#include <limits>
#include <map>
#include <optional>
#include <string>
#include <tuple>
Expand Down Expand Up @@ -463,6 +465,9 @@ class MetadataLoader::MetadataLoaderImpl {
bool NeedUpgradeToDIGlobalVariableExpression = false;
bool NeedDeclareExpressionUpgrade = false;

/// Map DILocalScope to the enclosing DISubprogram, if any.
DenseMap<DILocalScope *, DISubprogram *> ParentSubprogram;

/// True if metadata is being parsed for a module being ThinLTO imported.
bool IsImporting = false;

Expand Down Expand Up @@ -521,6 +526,84 @@ class MetadataLoader::MetadataLoaderImpl {
}
}

DISubprogram *findEnclosingSubprogram(DILocalScope *S) {
if (!S)
return nullptr;
if (auto *SP = ParentSubprogram[S]) {
return SP;
}

DILocalScope *InitialScope = S;
DenseSet<DILocalScope *> Visited;
while (S && !isa<DISubprogram>(S)) {
S = dyn_cast_or_null<DILocalScope>(S->getScope());
if (Visited.contains(S))
break;
Visited.insert(S);
}
ParentSubprogram[InitialScope] = llvm::dyn_cast_or_null<DISubprogram>(S);

return ParentSubprogram[InitialScope];
}

/// Move local imports from DICompileUnit's 'imports' field to
/// DISubprogram's retainedNodes.
void upgradeCULocals() {
if (NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu")) {
for (unsigned I = 0, E = CUNodes->getNumOperands(); I != E; ++I) {
auto *CU = dyn_cast<DICompileUnit>(CUNodes->getOperand(I));
if (!CU)
continue;

if (auto *RawImported = CU->getRawImportedEntities()) {
// Collect a set of imported entities to be moved.
SmallPtrSet<Metadata *, 8> EntitiesToRemove;
for (Metadata *Op : CU->getImportedEntities()->operands()) {
auto *IE = cast<DIImportedEntity>(Op);
if (auto *S = dyn_cast_or_null<DILocalScope>(IE->getScope())) {
EntitiesToRemove.insert(IE);
}
}

if (!EntitiesToRemove.empty()) {
// Make a new list of CU's 'imports'.
SmallVector<Metadata *> NewImports;
for (Metadata *Op : CU->getImportedEntities()->operands()) {
if (!EntitiesToRemove.contains(cast<DIImportedEntity>(Op))) {
NewImports.push_back(Op);
}
}

// Find DISubprogram corresponding to each entity.
std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities;
for (auto *I : EntitiesToRemove) {
auto *Entity = cast<DIImportedEntity>(I);
if (auto *SP = findEnclosingSubprogram(
cast<DILocalScope>(Entity->getScope()))) {
SPToEntities[SP].push_back(Entity);
}
}

// Update DISubprograms' retainedNodes.
for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) {
auto *SP = I->first;
auto RetainedNodes = SP->getRetainedNodes();
SmallVector<Metadata *> MDs(RetainedNodes.begin(),
RetainedNodes.end());
MDs.append(I->second);
SP->replaceRetainedNodes(MDNode::get(Context, MDs));
}

// Remove entities with local scope from CU.
CU->replaceImportedEntities(MDTuple::get(Context, NewImports));
}
}
}
}

ParentSubprogram.clear();
}

/// Remove a leading DW_OP_deref from DIExpressions in a dbg.declare that
/// describes a function argument.
void upgradeDeclareExpressions(Function &F) {
Expand Down Expand Up @@ -625,6 +708,7 @@ class MetadataLoader::MetadataLoaderImpl {
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
upgradeCULocals();
}

void callMDTypeCallback(Metadata **Val, unsigned TypeID);
Expand Down

0 comments on commit fcc3981

Please sign in to comment.