[DebugMetadata][DwarfDebug] Fix DWARF emisson of function-local imported entities (3/7)

RFC https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544

Fixed PR51501 (tests from D112337).

1. Reuse of DISubprogram's 'retainedNodes' to track other function-local
   entities together with local variables and labels (this patch cares about
   function-local import while D144006 and D144008 use the same approach for
   local types and static variables). So, effectively this patch moves ownership
   of tracking local import from DICompileUnit's 'imports' field to DISubprogram's
   'retainedNodes' and adjusts DWARF emitter for the new layout. The old layout
   is considered unsupported (DwarfDebug would assert on such debug metadata).

   DICompileUnit's 'imports' field is supposed to track global imported
   declarations as it does before.

   This addresses various FIXMEs and simplifies the next part of the patch.

2. Postpone emission of function-local imported entities from
   `DwarfDebug::endFunctionImpl()` to `DwarfDebug::endModule()`.
   While in `DwarfDebug::endFunctionImpl()` we do not have all the
   information about a parent subprogram or a referring subprogram
   (whether a subprogram inlined or not), so we can't guarantee we emit
   an imported entity correctly and place it in a proper subprogram tree.
   So now, we just gather needed details about the import itself and its
   parent entity (either a Subprogram or a LexicalBlock) during
   processing in `DwarfDebug::endFunctionImpl()`, but all the real work is
   done in `DwarfDebug::endModule()` when we have all the required
   information to make proper emission.

Authored-by: Kristina Bessonova <kbessonova@accesssoftek.com>

Differential Revision: https://reviews.llvm.org/D144004
This commit is contained in:
Vladislav Dzhidzhoev 2023-06-15 12:22:16 +02:00
parent aee3a9f5bc
commit d80fdc6fc1
35 changed files with 769 additions and 278 deletions

View File

@ -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",

View File

@ -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.
@ -64,7 +64,8 @@ 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
@ -72,6 +73,12 @@ namespace llvm {
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()];

View File

@ -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"
@ -53,6 +54,7 @@
#include <deque>
#include <iterator>
#include <limits>
#include <map>
#include <optional>
#include <string>
#include <tuple>
@ -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;
@ -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) {
@ -625,6 +708,7 @@ class MetadataLoader::MetadataLoaderImpl {
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
upgradeCULocals();
}
void callMDTypeCallback(Metadata **Val, unsigned TypeID);

View File

@ -694,7 +694,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope,
auto *InlinedSP = getDISubprogram(DS);
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
// was inlined from another compile unit.
DIE *OriginDIE = getAbstractSPDies()[InlinedSP];
DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP];
assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");
auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine);
@ -726,10 +726,20 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope,
DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
if (DD->isLexicalScopeDIENull(Scope))
return nullptr;
const auto *DS = Scope->getScopeNode();
auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
if (Scope->isAbstractScope()) {
assert(!getAbstractScopeDIEs().count(DS) &&
"Abstract DIE for this scope exists!");
getAbstractScopeDIEs()[DS] = ScopeDIE;
return ScopeDIE;
}
if (!Scope->getInlinedAt()) {
assert(!LexicalBlockDIEs.count(DS) &&
"Concrete out-of-line DIE for this scope exists!");
LexicalBlockDIEs[DS] = ScopeDIE;
}
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
@ -1097,35 +1107,35 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
for (DbgVariable *DV : Locals)
ScopeDIE.addChild(constructVariableDIE(*DV, *Scope, ObjectPointer));
// Emit imported entities (skipped in gmlt-like data).
if (!includeMinimalInlineScopes()) {
for (const auto *IE : ImportedEntities[Scope->getScopeNode()])
ScopeDIE.addChild(constructImportedEntityDIE(cast<DIImportedEntity>(IE)));
}
// Emit labels.
for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope))
ScopeDIE.addChild(constructLabelDIE(*DL, *Scope));
// Track other local entities (skipped in gmlt-like data).
// This creates mapping between CU and a set of local declarations that
// should be emitted for subprograms in this CU.
if (!includeMinimalInlineScopes() && !Scope->getInlinedAt()) {
auto &LocalDecls = DD->getLocalDeclsForScope(Scope->getScopeNode());
DeferredLocalDecls.insert(LocalDecls.begin(), LocalDecls.end());
}
// Emit inner lexical scopes.
auto needToEmitLexicalScope = [this](LexicalScope *LS) {
if (isa<DISubprogram>(LS->getScopeNode()))
return true;
auto Vars = DU->getScopeVariables().lookup(LS);
auto skipLexicalScope = [this](LexicalScope *S) -> bool {
if (isa<DISubprogram>(S->getScopeNode()))
return false;
auto Vars = DU->getScopeVariables().lookup(S);
if (!Vars.Args.empty() || !Vars.Locals.empty())
return true;
if (!includeMinimalInlineScopes() &&
!ImportedEntities[LS->getScopeNode()].empty())
return true;
return false;
return false;
return includeMinimalInlineScopes() ||
DD->getLocalDeclsForScope(S->getScopeNode()).empty();
};
for (LexicalScope *LS : Scope->getChildren()) {
// If the lexical block doesn't have non-scope children, skip
// its emission and put its children directly to the parent scope.
if (needToEmitLexicalScope(LS))
constructScopeDIE(LS, ScopeDIE);
else
if (skipLexicalScope(LS))
createAndAddScopeChildren(LS, ScopeDIE);
else
constructScopeDIE(LS, ScopeDIE);
}
return ObjectPointer;
@ -1133,11 +1143,9 @@ DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
LexicalScope *Scope) {
DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()];
if (AbsDef)
return;
auto *SP = cast<DISubprogram>(Scope->getScopeNode());
if (getAbstractScopeDIEs().count(SP))
return;
DIE *ContextDIE;
DwarfCompileUnit *ContextCU = this;
@ -1161,14 +1169,19 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
// Passing null as the associated node because the abstract definition
// shouldn't be found by lookup.
AbsDef = &ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr);
ContextCU->applySubprogramAttributesToDefinition(SP, *AbsDef);
ContextCU->addSInt(*AbsDef, dwarf::DW_AT_inline,
DIE &AbsDef = ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
*ContextDIE, nullptr);
// Store the DIE before creating children.
ContextCU->getAbstractScopeDIEs()[SP] = &AbsDef;
ContextCU->applySubprogramAttributesToDefinition(SP, AbsDef);
ContextCU->addSInt(AbsDef, dwarf::DW_AT_inline,
DD->getDwarfVersion() <= 4 ? std::optional<dwarf::Form>()
: dwarf::DW_FORM_implicit_const,
dwarf::DW_INL_inlined);
if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef))
ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, AbsDef))
ContextCU->addDIEEntry(AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const {
@ -1312,12 +1325,20 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
EntityDie = getOrCreateNameSpace(NS);
else if (auto *M = dyn_cast<DIModule>(Entity))
EntityDie = getOrCreateModule(M);
else if (auto *SP = dyn_cast<DISubprogram>(Entity))
EntityDie = getOrCreateSubprogramDIE(SP);
else if (auto *T = dyn_cast<DIType>(Entity))
else if (auto *SP = dyn_cast<DISubprogram>(Entity)) {
// If there is an abstract subprogram, refer to it. Note that this assumes
// that all the abstract subprograms have been already created (which is
// correct until imported entities get emitted in DwarfDebug::endModule()).
if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(SP))
EntityDie = AbsSPDie;
else
EntityDie = getOrCreateSubprogramDIE(SP);
} else if (auto *T = dyn_cast<DIType>(Entity))
EntityDie = getOrCreateTypeDIE(T);
else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
EntityDie = getOrCreateGlobalVariableDIE(GV, {});
else if (auto *IE = dyn_cast<DIImportedEntity>(Entity))
EntityDie = getOrCreateImportedEntityDIE(IE);
else
EntityDie = getDIE(Entity);
assert(EntityDie);
@ -1348,9 +1369,24 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
return IMDie;
}
DIE *DwarfCompileUnit::getOrCreateImportedEntityDIE(
const DIImportedEntity *IE) {
// Check for pre-existence.
if (DIE *Die = getDIE(IE))
return Die;
DIE *ContextDIE = getOrCreateContextDIE(IE->getScope());
assert(ContextDIE && "Empty scope for the imported entity!");
DIE *IMDie = constructImportedEntityDIE(IE);
ContextDIE->addChild(IMDie);
return IMDie;
}
void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
DIE *D = getDIE(SP);
if (DIE *AbsSPDIE = getAbstractSPDies().lookup(SP)) {
if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(SP)) {
if (D)
// If this subprogram has an abstract definition, reference that
addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
@ -1644,3 +1680,29 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
Btr.Die = &Die;
}
}
DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) {
// Assume if there is an abstract tree all the DIEs are already emitted.
bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram());
if (isAbstract && getAbstractScopeDIEs().count(LB))
return getAbstractScopeDIEs()[LB];
assert(!isAbstract && "Missed lexical block DIE in abstract tree!");
// Return a concrete DIE if it exists or nullptr otherwise.
return LexicalBlockDIEs.lookup(LB);
}
DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
if (isa_and_nonnull<DILocalScope>(Context)) {
if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context))
Context = LFScope->getNonLexicalBlockFileScope();
if (auto *LScope = dyn_cast<DILexicalBlock>(Context))
return getLexicalBlockDIE(LScope);
// Otherwise the context must be a DISubprogram.
auto *SPScope = cast<DISubprogram>(Context);
if (getAbstractScopeDIEs().count(SPScope))
return getAbstractScopeDIEs()[SPScope];
}
return DwarfUnit::getOrCreateContextDIE(Context);
}

View File

@ -61,11 +61,6 @@ class DwarfCompileUnit final : public DwarfUnit {
/// The start of the unit macro info within macro section.
MCSymbol *MacroLabelBegin;
using ImportedEntityList = SmallVector<const MDNode *, 8>;
using ImportedEntityMap = DenseMap<const MDNode *, ImportedEntityList>;
ImportedEntityMap ImportedEntities;
/// GlobalNames - A map of globally visible named entities for this unit.
StringMap<const DIE *> GlobalNames;
@ -79,7 +74,20 @@ class DwarfCompileUnit final : public DwarfUnit {
// ranges/locs.
const MCSymbol *BaseAddress = nullptr;
DenseMap<const MDNode *, DIE *> AbstractSPDies;
using MDNodeSetVector =
SetVector<const MDNode *, SmallVector<const MDNode *, 4>,
SmallPtrSet<const MDNode *, 4>>;
// List of entities (either static locals, types or imports) that
// belong to subprograms within this CU.
MDNodeSetVector DeferredLocalDecls;
// List of concrete lexical block scopes belong to subprograms within this CU.
DenseMap<const DILocalScope *, DIE *> LexicalBlockDIEs;
// List of abstract local scopes (either DISubprogram or DILexicalBlock).
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
/// DWO ID for correlating skeleton and split units.
@ -94,10 +102,10 @@ class DwarfCompileUnit final : public DwarfUnit {
bool isDwoUnit() const override;
DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() {
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
return AbstractSPDies;
return DU->getAbstractSPDies();
return AbstractLocalScopeDIEs;
return DU->getAbstractScopeDIEs();
}
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {
@ -175,17 +183,6 @@ public:
unsigned getOrCreateSourceID(const DIFile *File) override;
void addImportedEntity(const DIImportedEntity* IE) {
DIScope *Scope = IE->getScope();
assert(Scope && "Invalid Scope encoding!");
if (!isa<DILocalScope>(Scope))
// No need to add imported enities that are not local declaration.
return;
auto *LocalScope = cast<DILocalScope>(Scope)->getNonLexicalBlockFileScope();
ImportedEntities[LocalScope].push_back(IE);
}
/// addRange - Add an address range to the list of ranges for this unit.
void addRange(RangeSpan Range);
@ -217,6 +214,11 @@ public:
/// attach DW_AT_low_pc/DW_AT_high_pc labels.
DIE *constructLexicalScopeDIE(LexicalScope *Scope);
/// Get a DIE for the given DILexicalBlock.
/// Note that this function assumes that the DIE has been already created
/// and it's an error, if it hasn't.
DIE *getLexicalBlockDIE(const DILexicalBlock *LB);
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false);
@ -228,6 +230,10 @@ public:
void createBaseTypeDIEs();
/// Construct a DIE for a given scope.
/// This instance of 'getOrCreateContextDIE()' can handle DILocalScope.
DIE *getOrCreateContextDIE(const DIScope *Ty) override;
/// Construct a DIE for this subprogram scope.
DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
LexicalScope *Scope);
@ -266,8 +272,9 @@ public:
void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
SmallVector<DbgCallSiteParam, 4> &Params);
/// Construct import_module DIE.
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
/// Get or create a DIE for an imported entity.
DIE *getOrCreateImportedEntityDIE(const DIImportedEntity *IE);
DIE *constructImportedEntityDIE(const DIImportedEntity *IE);
void finishSubprogramDefinition(const DISubprogram *SP);
void finishEntityDefinition(const DbgEntity *Entity);
@ -364,6 +371,8 @@ public:
bool hasDwarfPubSections() const;
void addBaseTypeRef(DIEValueList &Die, int64_t Idx);
MDNodeSetVector &getDeferredLocalDecls() { return DeferredLocalDecls; }
};
} // end namespace llvm

View File

@ -507,7 +507,7 @@ void DwarfDebug::addSubprogramNames(const DICompileUnit &CU,
// well into the name table. Only do that if we are going to actually emit
// that name.
if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() &&
(useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP)))
(useAllLinkageNames() || InfoHolder.getAbstractScopeDIEs().lookup(SP)))
addAccelName(CU, SP->getLinkageName(), Die);
// If this is an Objective-C selector name add it to the ObjC accelerator
@ -1105,9 +1105,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
DwarfCompileUnit &NewCU = *OwnedUnit;
InfoHolder.addUnit(std::move(OwnedUnit));
for (auto *IE : DIUnit->getImportedEntities())
NewCU.addImportedEntity(IE);
// LTO with assembly output shares a single line table amongst multiple CUs.
// To avoid the compilation directory being ambiguous, let the line table
// explicitly describe the directory of all files, never relying on the
@ -1130,14 +1127,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
return NewCU;
}
void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity *N) {
if (isa<DILocalScope>(N->getScope()))
return;
if (DIE *D = TheCU.getOrCreateContextDIE(N->getScope()))
D->addChild(TheCU.constructImportedEntityDIE(N));
}
/// Sort and unique GVEs by comparing their fragment offset.
static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &
sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
@ -1215,16 +1204,8 @@ void DwarfDebug::beginModule(Module *M) {
DebugLocs.setSym(Asm->createTempSymbol("loclists_table_base"));
for (DICompileUnit *CUNode : M->debug_compile_units()) {
// FIXME: Move local imported entities into a list attached to the
// subprogram, then this search won't be needed and a
// getImportedEntities().empty() test should go below with the rest.
bool HasNonLocalImportedEntities = llvm::any_of(
CUNode->getImportedEntities(), [](const DIImportedEntity *IE) {
return !isa<DILocalScope>(IE->getScope());
});
if (!HasNonLocalImportedEntities && CUNode->getEnumTypes().empty() &&
CUNode->getRetainedTypes().empty() &&
if (CUNode->getImportedEntities().empty() &&
CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() &&
CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty())
continue;
@ -1442,8 +1423,17 @@ void DwarfDebug::endModule() {
DwarfCompileUnit *CU = &*P.second;
// Emit imported entities.
for (auto *IE : CUNode->getImportedEntities())
constructAndAddImportedEntityDIE(*CU, IE);
for (auto *IE : CUNode->getImportedEntities()) {
assert(!isa_and_nonnull<DILocalScope>(IE->getScope()) &&
"Unexpected function-local entity in 'imports' CU field.");
CU->getOrCreateImportedEntityDIE(IE);
}
for (const auto *D : CU->getDeferredLocalDecls()) {
if (auto *IE = dyn_cast<DIImportedEntity>(D))
CU->getOrCreateImportedEntityDIE(IE);
else
llvm_unreachable("Unexpected local retained node!");
}
// Emit base types.
CU->createBaseTypeDIEs();
@ -1520,16 +1510,6 @@ void DwarfDebug::endModule() {
// FIXME: AbstractVariables.clear();
}
void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU,
const DINode *Node,
const MDNode *ScopeNode) {
if (CU.getExistingAbstractEntity(Node))
return;
CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope(
cast<DILocalScope>(ScopeNode)));
}
void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
const DINode *Node, const MDNode *ScopeNode) {
if (CU.getExistingAbstractEntity(Node))
@ -1540,6 +1520,21 @@ void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
CU.createAbstractEntity(Node, Scope);
}
static const DILocalScope *getRetainedNodeScope(const MDNode *N) {
const DIScope *S;
if (const auto *LV = dyn_cast<DILocalVariable>(N))
S = LV->getScope();
else if (const auto *L = dyn_cast<DILabel>(N))
S = L->getScope();
else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
S = IE->getScope();
else
llvm_unreachable("Unexpected retained node!");
// Ensure the scope is not a DILexicalBlockFile.
return cast<DILocalScope>(S)->getNonLexicalBlockFileScope();
}
// Collect variable information from side table maintained by MF.
void DwarfDebug::collectVariableInfoFromMFTable(
DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) {
@ -1984,19 +1979,18 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym);
}
// Collect info for variables/labels that were optimized out.
// Collect info for retained nodes.
for (const DINode *DN : SP->getRetainedNodes()) {
if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
continue;
LexicalScope *Scope = nullptr;
if (auto *DV = dyn_cast<DILocalVariable>(DN)) {
Scope = LScopes.findLexicalScope(DV->getScope());
} else if (auto *DL = dyn_cast<DILabel>(DN)) {
Scope = LScopes.findLexicalScope(DL->getScope());
const auto *LS = getRetainedNodeScope(DN);
if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) {
if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
continue;
LexicalScope *LexS = LScopes.findLexicalScope(LS);
if (LexS)
createConcreteEntity(TheCU, *LexS, DN, nullptr);
} else {
LocalDeclsPerLS[LS].insert(DN);
}
if (Scope)
createConcreteEntity(TheCU, *Scope, DN, nullptr);
}
}
@ -2311,27 +2305,28 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
}
#ifndef NDEBUG
size_t NumAbstractScopes = LScopes.getAbstractScopesList().size();
size_t NumAbstractSubprograms = LScopes.getAbstractScopesList().size();
#endif
// Construct abstract scopes.
for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
const auto *SP = cast<DISubprogram>(AScope->getScopeNode());
for (const DINode *DN : SP->getRetainedNodes()) {
if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
continue;
const MDNode *Scope = nullptr;
if (auto *DV = dyn_cast<DILocalVariable>(DN))
Scope = DV->getScope();
else if (auto *DL = dyn_cast<DILabel>(DN))
Scope = DL->getScope();
else
llvm_unreachable("Unexpected DI type!");
// Collect info for variables/labels that were optimized out.
ensureAbstractEntityIsCreated(TheCU, DN, Scope);
assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
&& "ensureAbstractEntityIsCreated inserted abstract scopes");
const auto *LS = getRetainedNodeScope(DN);
// Ensure LexicalScope is created for the scope of this node.
auto *LexS = LScopes.getOrCreateAbstractScope(LS);
assert(LexS && "Expected the LexicalScope to be created.");
if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) {
// Collect info for variables/labels that were optimized out.
if (!Processed.insert(InlinedEntity(DN, nullptr)).second ||
TheCU.getExistingAbstractEntity(DN))
continue;
TheCU.createAbstractEntity(DN, LexS);
} else {
// Remember the node if this is a local declarations.
LocalDeclsPerLS[LS].insert(DN);
}
assert(
LScopes.getAbstractScopesList().size() == NumAbstractSubprograms &&
"getOrCreateAbstractScope() inserted an abstract subprogram scope");
}
constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
@ -2352,6 +2347,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
// can be used cross-function)
InfoHolder.getScopeVariables().clear();
InfoHolder.getScopeLabels().clear();
LocalDeclsPerLS.clear();
PrevLabel = nullptr;
CurFn = nullptr;
}

View File

@ -320,6 +320,13 @@ class DwarfDebug : public DebugHandlerBase {
/// create DIEs.
SmallSetVector<const DISubprogram *, 16> ProcessedSPNodes;
/// Map function-local imported entities to their parent local scope
/// (either DILexicalBlock or DISubprogram) for a processed function
/// (including inlined subprograms).
using MDNodeSet = SetVector<const MDNode *, SmallVector<const MDNode *, 2>,
SmallPtrSet<const MDNode *, 2>>;
DenseMap<const DILocalScope *, MDNodeSet> LocalDeclsPerLS;
/// If nonnull, stores the current machine function we're processing.
const MachineFunction *CurFn = nullptr;
@ -454,9 +461,6 @@ private:
using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU,
const DINode *Node,
const MDNode *Scope);
void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
const DINode *Node,
const MDNode *Scope);
@ -596,10 +600,6 @@ private:
void finishUnitAttributes(const DICompileUnit *DIUnit,
DwarfCompileUnit &NewCU);
/// Construct imported_module or imported_declaration DIE.
void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
const DIImportedEntity *N);
/// Register a source line with debug info. Returns the unique
/// label that was emitted and which provides correspondence to the
/// source line list.
@ -838,6 +838,10 @@ public:
/// If the \p File has an MD5 checksum, return it as an MD5Result
/// allocated in the MCContext.
std::optional<MD5::MD5Result> getMD5AsBytes(const DIFile *File) const;
MDNodeSet &getLocalDeclsForScope(const DILocalScope *S) {
return LocalDeclsPerLS[S];
}
};
} // end namespace llvm

View File

@ -26,6 +26,7 @@ class DbgEntity;
class DbgVariable;
class DbgLabel;
class DINode;
class DILocalScope;
class DwarfCompileUnit;
class DwarfUnit;
class LexicalScope;
@ -87,7 +88,7 @@ class DwarfFile {
DenseMap<LexicalScope *, LabelList> ScopeLabels;
// Collection of abstract subprogram DIEs.
DenseMap<const MDNode *, DIE *> AbstractSPDies;
DenseMap<const DILocalScope *, DIE *> AbstractLocalScopeDIEs;
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
/// Maps MDNodes for type system with the corresponding DIEs. These DIEs can
@ -162,8 +163,8 @@ public:
return ScopeLabels;
}
DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
return AbstractSPDies;
DenseMap<const DILocalScope *, DIE *> &getAbstractScopeDIEs() {
return AbstractLocalScopeDIEs;
}
DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {

View File

@ -1223,7 +1223,7 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,
"decl has a linkage name and it is different");
if (DeclLinkageName.empty() &&
// Always emit it for abstract subprograms.
(DD->useAllLinkageNames() || DU->getAbstractSPDies().lookup(SP)))
(DD->useAllLinkageNames() || DU->getAbstractScopeDIEs().lookup(SP)))
addLinkageName(SPDie, LinkageName);
if (!DeclDie)

View File

@ -245,10 +245,10 @@ public:
DIE *createTypeDIE(const DIScope *Context, DIE &ContextDIE, const DIType *Ty);
/// Find existing DIE or create new DIE for the given type.
DIE *getOrCreateTypeDIE(const MDNode *TyNode);
virtual DIE *getOrCreateTypeDIE(const MDNode *TyNode);
/// Get context owner's DIE.
DIE *getOrCreateContextDIE(const DIScope *Context);
virtual DIE *getOrCreateContextDIE(const DIScope *Context);
/// Construct DIEs for types that contain vtables.
void constructContainingTypeDIEs();

View File

@ -35,7 +35,7 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU)
if (const auto &GVs = CUNode->getGlobalVariables())
AllGVs.assign(GVs.begin(), GVs.end());
if (const auto &IMs = CUNode->getImportedEntities())
AllImportedModules.assign(IMs.begin(), IMs.end());
ImportedModules.assign(IMs.begin(), IMs.end());
if (const auto &MNs = CUNode->getMacros())
AllMacrosPerParent.insert({nullptr, {MNs.begin(), MNs.end()}});
}
@ -93,10 +93,10 @@ void DIBuilder::finalize() {
if (!AllGVs.empty())
CUNode->replaceGlobalVariables(MDTuple::get(VMContext, AllGVs));
if (!AllImportedModules.empty())
if (!ImportedModules.empty())
CUNode->replaceImportedEntities(MDTuple::get(
VMContext, SmallVector<Metadata *, 16>(AllImportedModules.begin(),
AllImportedModules.end())));
VMContext, SmallVector<Metadata *, 16>(ImportedModules.begin(),
ImportedModules.end())));
for (const auto &I : AllMacrosPerParent) {
// DIMacroNode's with nullptr parent are DICompileUnit direct children.
@ -160,7 +160,7 @@ static DIImportedEntity *
createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context,
Metadata *NS, DIFile *File, unsigned Line, StringRef Name,
DINodeArray Elements,
SmallVectorImpl<TrackingMDNodeRef> &AllImportedModules) {
SmallVectorImpl<TrackingMDNodeRef> &ImportedModules) {
if (Line)
assert(File && "Source location has line number but no file");
unsigned EntitiesCount = C.pImpl->DIImportedEntitys.size();
@ -169,7 +169,7 @@ createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context,
if (EntitiesCount < C.pImpl->DIImportedEntitys.size())
// A new Imported Entity was just added to the context.
// Add it to the Imported Modules list.
AllImportedModules.emplace_back(M);
ImportedModules.emplace_back(M);
return M;
}
@ -179,7 +179,7 @@ DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context,
DINodeArray Elements) {
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module,
Context, NS, File, Line, StringRef(), Elements,
AllImportedModules);
getImportTrackingVector(Context));
}
DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context,
@ -188,7 +188,7 @@ DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context,
DINodeArray Elements) {
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module,
Context, NS, File, Line, StringRef(), Elements,
AllImportedModules);
getImportTrackingVector(Context));
}
DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M,
@ -196,7 +196,7 @@ DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M,
DINodeArray Elements) {
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module,
Context, M, File, Line, StringRef(), Elements,
AllImportedModules);
getImportTrackingVector(Context));
}
DIImportedEntity *
@ -207,7 +207,7 @@ DIBuilder::createImportedDeclaration(DIScope *Context, DINode *Decl,
// types that have one.
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration,
Context, Decl, File, Line, Name, Elements,
AllImportedModules);
getImportTrackingVector(Context));
}
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,

View File

@ -1383,9 +1383,11 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
auto *Node = dyn_cast<MDTuple>(RawNode);
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
for (Metadata *Op : Node->operands()) {
CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),
"invalid retained nodes, expected DILocalVariable or DILabel", &N,
Node, Op);
CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) ||
isa<DIImportedEntity>(Op)),
"invalid retained nodes, expected DILocalVariable, DILabel or "
"DIImportedEntity",
&N, Node, Op);
}
}
CheckDI(!hasConflictingReferenceFlags(N.getFlags()),

View File

@ -1211,39 +1211,7 @@ void IRLinker::prepareCompileUnitsForImport() {
// size inefficient.
CU->replaceGlobalVariables(nullptr);
// Imported entities only need to be mapped in if they have local
// scope, as those might correspond to an imported entity inside a
// function being imported (any locally scoped imported entities that
// don't end up referenced by an imported function will not be emitted
// into the object). Imported entities not in a local scope
// (e.g. on the namespace) only need to be emitted by the originating
// module. Create a list of the locally scoped imported entities, and
// replace the source CUs imported entity list with the new list, so
// only those are mapped in.
// FIXME: Locally-scoped imported entities could be moved to the
// functions they are local to instead of listing them on the CU, and
// we would naturally only link in those needed by function importing.
SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
bool ReplaceImportedEntities = false;
for (auto *IE : CU->getImportedEntities()) {
DIScope *Scope = IE->getScope();
assert(Scope && "Invalid Scope encoding!");
if (isa<DILocalScope>(Scope))
AllImportedModules.emplace_back(IE);
else
ReplaceImportedEntities = true;
}
if (ReplaceImportedEntities) {
if (!AllImportedModules.empty())
CU->replaceImportedEntities(MDTuple::get(
CU->getContext(),
SmallVector<Metadata *, 16>(AllImportedModules.begin(),
AllImportedModules.end())));
else
// If there were no local scope imported entities, we can map
// the whole list to nullptr.
CU->replaceImportedEntities(nullptr);
}
CU->replaceImportedEntities(nullptr);
}
}

View File

@ -4,11 +4,11 @@
; RUN: llvm-dis -o - %s.bc | FileCheck %s
;Test whether DIImportedEntity are generated correctly.
; CHECK: distinct !DICompileUnit(language: DW_LANG_Fortran90
; CHECK-SAME: imports: [[IMPORTS:![0-9]+]]
; CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "use_renamed"
; CHECK-SAME: retainedNodes: [[IMPORTS:![0-9]+]]
; CHECK: [[IMPORTS]] = !{[[IMPORT1:![0-9]+]], [[IMPORT2:![0-9]+]]}
; CHECK: [[IMPORT1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: {{![0-9]+}}, entity: {{![0-9]+}}, file: {{![0-9]+}}, line: {{[0-9]+}})
; CHECK: [[IMPORT2]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "var4", scope: {{![0-9]+}}, entity: {{![0-9]+}}, file: {{![0-9]+}}, line: {{[0-9]+}})
; CHECK: [[IMPORT1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[SP]], entity: {{![0-9]+}}, file: {{![0-9]+}}, line: {{[0-9]+}})
; CHECK: [[IMPORT2]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "var4", scope: [[SP]], entity: {{![0-9]+}}, file: {{![0-9]+}}, line: {{[0-9]+}})
; ModuleID = 'DIImportedEntity_backward.bc'
source_filename = "/tmp/usemodulealias.ll"
@ -58,7 +58,7 @@ declare void @fort_init(...)
!1 = distinct !DIGlobalVariable(name: "var1", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true)
!2 = !DIModule(scope: !4, name: "mymod", file: !3, line: 1)
!3 = !DIFile(filename: "DIImportedEntity_backward.f90", directory: "/tmp")
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !12, nameTableKind: None)
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None)
!5 = !{}
!6 = !{!0, !7, !10}
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4))
@ -68,7 +68,7 @@ declare void @fort_init(...)
!11 = distinct !DIGlobalVariable(name: "var3", scope: !2, file: !3, line: 4, type: !9, isLocal: false, isDefinition: true)
!12 = !{!13, !19}
!13 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !14, entity: !2, file: !3, line: 10)
!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4)
!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4, retainedNodes: !12)
!15 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 7, type: !16, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4)
!16 = !DISubroutineType(cc: DW_CC_program, types: !17)
!17 = !{null}

View File

@ -1,6 +1,6 @@
; RUN: llvm-as -o - %s | llvm-dis -o - | FileCheck %s
; CHECK: DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
; CHECK: DIModule(scope: !2, name: "external_module", isDecl: true)
; CHECK: DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: ![[MOD:[0-9]+]], file: !3, line: 2)
; CHECK: ![[MOD]] = !DIModule(scope: !2, name: "external_module", isDecl: true)
; ModuleID = 'em.f90'
source_filename = "em.f90"

View File

@ -0,0 +1,118 @@
; Test moving of local imports from DICompileUnit's 'imports' to DISubprogram's 'retainedNodes'
;
; RUN: llvm-dis -o - %s.bc | FileCheck %s
%"struct.ns::t1" = type { i8 }
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
declare dso_local void @_Z3pinv() local_unnamed_addr
define dso_local i32 @main() local_unnamed_addr !dbg !23 {
entry:
call void @llvm.dbg.declare(metadata ptr undef, metadata !39, metadata !DIExpression()), !dbg !40
call void @_Z3pinv(), !dbg !42
ret i32 0, !dbg !43
}
define dso_local i32 @main2() local_unnamed_addr !dbg !29 {
ret i32 0
}
attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
!llvm.dbg.cu = !{!0, !16}
!llvm.ident = !{!33, !33}
!llvm.module.flags = !{!34, !35, !36, !37, !38}
; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !2,
; CHECK: !2 = !{!3}
; CHECK: !3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !4,
; CHECK: !4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4"
; CHECK: !5 = !{}
; CHECK: !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !7, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !5, nameTableKind: GNU)
; CHECK: !14 = distinct !DISubprogram(name: "main", scope: !7, file: !7, line: 2, type: !15, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !18)
; CHECK: !18 = !{!19}
; CHECK: !19 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !20, entity: !23,
; CHECK: !20 = !DILexicalBlock(scope: !21, file: !7, line: 7, column: 35)
; CHECK: !21 = !DILexicalBlock(scope: !22, file: !7, line: 7, column: 35)
; CHECK: !22 = !DILexicalBlock(scope: !14, file: !7, line: 7, column: 35)
; CHECK: !23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t5", scope: !20,
; CHECK: !25 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !26, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !28)
; CHECK: !28 = !{!29, !32, !34}
; CHECK: !29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !30,
; CHECK: !30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1",
; CHECK: !32 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !33,
; CHECK: !33 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2",
; CHECK: !34 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !35,
; CHECK: !35 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t3",
; CHECK: !40 = distinct !DISubprogram(name: "main2", scope: !7, file: !7, line: 10, type: !15, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !41)
; CHECK: !41 = !{!42, !44}
; CHECK: !42 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !40, entity: !43,
; CHECK: !43 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t6"
; CHECK: !44 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !40, entity: !45,
; CHECK: !45 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t7",
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !2, nameTableKind: GNU)
!1 = !DIFile(filename: "a.cpp", directory: "/")
!2 = !{!3, !10, !12, !14}
; Move t1 to DISubprogram f1
!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !8, file: !1, line: 3)
!4 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !7)
!5 = !DISubroutineType(types: !6)
!6 = !{null}
!7 = !{}
!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", scope: !9, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t1E")
!9 = !DINamespace(name: "ns", scope: null)
; Move t2 to DISubprogram f1
!10 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !11, file: !1, line: 3)
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", scope: !9, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t2E")
; Move t3 to DISubprogram f1
!12 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !13, file: !1, line: 3)
!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t3", scope: !9, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t3E")
; Leave t4 in CU
!14 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !15, file: !1, line: 3)
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4", scope: !0, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t4E")
!16 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !17, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !18, nameTableKind: GNU)
!17 = !DIFile(filename: "b.cpp", directory: "/")
!18 = !{!19, !28, !31}
; Move t5 to DISubprogram main
!19 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !20, entity: !27, file: !1, line: 3)
!20 = !DILexicalBlock(scope: !21, file: !17, line: 7, column: 35)
!21 = !DILexicalBlock(scope: !22, file: !17, line: 7, column: 35)
!22 = !DILexicalBlock(scope: !23, file: !17, line: 7, column: 35)
!23 = distinct !DISubprogram(name: "main", scope: !17, file: !17, line: 2, type: !24, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !16, retainedNodes: !7)
!24 = !DISubroutineType(types: !25)
!25 = !{!26}
!26 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!27 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t5", scope: !20, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t5E")
; Move t6 to DISubprogram main2
!28 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !29, entity: !30, file: !17, line: 3)
!29 = distinct !DISubprogram(name: "main2", scope: !17, file: !17, line: 10, type: !24, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !16, retainedNodes: !7)
!30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t6", scope: !29, file: !17, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t6E")
; Move t7 to DISubprogram main2
!31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !29, entity: !32, file: !17, line: 3)
!32 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t7", scope: !29, file: !17, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t7E")
!33 = !{!"clang version 14.0.0"}
!34 = !{i32 7, !"Dwarf Version", i32 4}
!35 = !{i32 2, !"Debug Info Version", i32 3}
!36 = !{i32 1, !"wchar_size", i32 4}
!37 = !{i32 7, !"uwtable", i32 1}
!38 = !{i32 7, !"frame-pointer", i32 2}
!39 = !DILocalVariable(name: "v1", scope: !4, file: !1, line: 3, type: !8)
!40 = !DILocation(line: 3, column: 37, scope: !4, inlinedAt: !41)
!41 = distinct !DILocation(line: 3, column: 3, scope: !23)
!42 = !DILocation(line: 3, column: 41, scope: !4, inlinedAt: !41)
!43 = !DILocation(line: 4, column: 1, scope: !23)

Binary file not shown.

View File

@ -21,12 +21,12 @@ attributes #1 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!1}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !2, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, retainedTypes: !3, globals: !3, imports: !4)
!1 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !2, producer: "", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, retainedTypes: !3, globals: !3)
!2 = !DIFile(filename: "input", directory: "/")
!3 = !{}
!4 = !{!5}
!5 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !6, entity: !9, file: !2, line: 18)
!6 = distinct !DISubprogram(name: "p", scope: !1, file: !2, line: 18, type: !7, isLocal: false, isDefinition: true, scopeLine: 18, isOptimized: false, unit: !1)
!6 = distinct !DISubprogram(name: "p", scope: !1, file: !2, line: 18, type: !7, isLocal: false, isDefinition: true, scopeLine: 18, isOptimized: false, unit: !1, retainedNodes: !4)
!7 = !DISubroutineType(cc: DW_CC_program, types: !8)
!8 = !{null}
!9 = !DIModule(scope: !1, name: "mod")

View File

@ -0,0 +1,72 @@
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s
; namespace ns {
; inline __attribute__((always_inline))
; void foo() { int a = 4; }
; }
;
; void goo() {
; using ns::foo;
; foo();
; }
; Ensure that imported declarations reference the correct subprograms even if
; those subprograms are inlined.
; CHECK: DW_TAG_compile_unit
; CHECK: DW_TAG_namespace
; CHECK: DW_AT_name ("ns")
; CHECK: [[FOO:0x.*]]: DW_TAG_subprogram
; CHECK: DW_AT_name ("foo")
; CHECK: DW_TAG_variable
; CHECK: NULL
; CHECK: NULL
; CHECK: DW_TAG_base_type
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name ("goo")
; CHECK: DW_TAG_inlined_subroutine
; CHECK: DW_AT_abstract_origin ([[FOO]]
; CHECK: DW_TAG_variable
; CHECK: NULL
; CHECK: DW_TAG_imported_declaration
; CHECK: DW_AT_import ([[FOO]])
; CHECK: NULL
; CHECK: NULL
; Function Attrs: mustprogress noinline optnone uwtable
define dso_local void @_Z3goov() !dbg !4 {
entry:
%a.i = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %a.i, metadata !16, metadata !DIExpression()), !dbg !18
store i32 4, i32* %a.i, align 4, !dbg !18
ret void, !dbg !20
}
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!10, !11, !12, !13, !14}
!llvm.ident = !{!15}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "imported-inlined-declaration.cpp", directory: "")
!2 = !{!3}
!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !8, file: !1, line: 7)
!4 = distinct !DISubprogram(name: "goo", linkageName: "_Z3goov", scope: !1, file: !1, line: 6, type: !5, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!5 = !DISubroutineType(types: !6)
!6 = !{null}
!7 = !{}
!8 = distinct !DISubprogram(name: "foo", linkageName: "_ZN2ns3fooEv", scope: !9, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !7)
!9 = !DINamespace(name: "ns", scope: null)
!10 = !{i32 7, !"Dwarf Version", i32 4}
!11 = !{i32 2, !"Debug Info Version", i32 3}
!12 = !{i32 1, !"wchar_size", i32 4}
!13 = !{i32 7, !"uwtable", i32 1}
!14 = !{i32 7, !"frame-pointer", i32 2}
!15 = !{!"clang version 14.0.0"}
!16 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 3, type: !17)
!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!18 = !DILocation(line: 3, column: 18, scope: !8, inlinedAt: !19)
!19 = distinct !DILocation(line: 8, column: 2, scope: !4)
!20 = !DILocation(line: 9, column: 1, scope: !4)

View File

@ -13,21 +13,17 @@
; Ensure that top level imported declarations don't produce an extra degenerate
; concrete subprogram definition.
; FIXME: imported entities should only be emitted to the abstract origin if one is present
; CHECK: DW_TAG_compile_unit
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name ("f1")
; CHECK: DW_TAG_imported_declaration
; CHECK: NULL
; CHECK: DW_TAG_namespace
; CHECK: DW_TAG_subprogram
; CHECK: NULL
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name ("f2")
; CHECK: DW_TAG_inlined_subroutine
; CHECK: DW_TAG_imported_declaration
; CHECK: NULL
; CHECK: NULL
; CHECK: DW_TAG_namespace
; CHECK: DW_TAG_subprogram
; CHECK: NULL
; CHECK: NULL
@ -44,12 +40,12 @@ declare void @_ZN2ns1fEv()
!llvm.module.flags = !{!10, !11, !12}
!llvm.ident = !{!13}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3)
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "imported-name-inlined.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
!2 = !{}
!3 = !{!4}
!4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !5, entity: !8, file: !1, line: 5)
!5 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 4, type: !6, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!5 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 4, type: !6, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !3)
!6 = !DISubroutineType(types: !7)
!7 = !{null}
!8 = !DISubprogram(name: "f", linkageName: "_ZN2ns1fEv", scope: !9, file: !1, line: 2, type: !6, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false)

View File

@ -33,6 +33,10 @@
; CHECK: DW_TAG_formal_parameter
; CHECK: NULL
; CHECK: [[FUNC_FWD:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
; CHECK: DW_AT_name ("func_fwd")
; CHECK-NOT: DW_AT_declaration
; CHECK: [[BAZ:0x[0-9a-f]*]]:{{.*}}DW_TAG_typedef
; CHECK: DW_AT_name ("baz")
@ -43,10 +47,6 @@
; CHECK: [[FUNC_DECL:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
; CHECK: DW_AT_name ("func_decl")
; CHECK: DW_AT_declaration
; CHECK: [[FUNC_FWD:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
; CHECK: DW_AT_name ("func_fwd")
; CHECK-NOT: DW_AT_declaration
; CHECK: NULL
; CHECK: DW_TAG_imported_module
@ -63,6 +63,12 @@
; CHECK: DW_AT_MIPS_linkage_name
; CHECK: DW_AT_name ("func")
; CHECK: DW_TAG_formal_parameter
; CHECK: DW_TAG_lexical_block
; CHECK: DW_TAG_imported_module
; CHECK: DW_AT_decl_file ([[F2]])
; CHECK: DW_AT_decl_line (23)
; CHECK: DW_AT_import {{.*}}
; CHECK: NULL
; CHECK: DW_TAG_imported_module
; CHECK: DW_AT_decl_file ([[F2:.*]])
; CHECK: DW_AT_decl_line (26)
@ -113,12 +119,6 @@
; CHECK: DW_AT_decl_file ([[F2]])
; CHECK: DW_AT_decl_line (37)
; CHECK: DW_AT_import ([[FUNC_FWD]])
; CHECK: DW_TAG_lexical_block
; CHECK: DW_TAG_imported_module
; CHECK: DW_AT_decl_file ([[F2]])
; CHECK: DW_AT_decl_line (23)
; CHECK: DW_AT_import {{.*}}
; CHECK: NULL
; CHECK: NULL
; CHECK: DW_TAG_subprogram
@ -293,7 +293,7 @@ attributes #1 = { nounwind readnone }
!18 = !DIFile(filename: "foo.cpp", directory: "/tmp")
!19 = !DISubroutineType(types: !20)
!20 = !{null}
!21 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcb", line: 21, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 21, file: !5, scope: !18, type: !22, retainedNodes: !2)
!21 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcb", line: 21, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 21, file: !5, scope: !18, type: !22, retainedNodes: !77)
!22 = !DISubroutineType(types: !23)
!23 = !{!13, !24}
!24 = !DIBasicType(tag: DW_TAG_base_type, name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean)
@ -305,7 +305,7 @@ attributes #1 = { nounwind readnone }
!30 = !{!131, !132}
!31 = !DIGlobalVariable(name: "i", linkageName: "_ZN1A1B1iE", line: 20, isLocal: false, isDefinition: true, scope: !6, file: !18, type: !13)
!32 = !DIGlobalVariable(name: "var_fwd", linkageName: "_ZN1A1B7var_fwdE", line: 44, isLocal: false, isDefinition: true, scope: !6, file: !18, type: !13)
!33 = !{!34, !35, !36, !37, !40, !41, !42, !43, !44, !45, !47, !48, !49, !51, !54, !55, !56}
!33 = !{!34, !35, !36, !56}
!34 = !DIImportedEntity(tag: DW_TAG_imported_module, file: !5, line: 15, scope: !7, entity: !6)
!35 = !DIImportedEntity(tag: DW_TAG_imported_module, file: !5, line: 18, scope: !0, entity: !7)
!36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, file: !5, line: 19, name: "E", scope: !0, entity: !7)
@ -348,5 +348,6 @@ attributes #1 = { nounwind readnone }
!73 = !DILocation(line: 47, column: 21, scope: !26)
!74 = !DILocation(line: 0, scope: !75)
!75 = !DILexicalBlockFile(discriminator: 0, file: !5, scope: !27)
!77 = !{!37, !40, !41, !42, !43, !44, !45, !47, !48, !49, !51, !54, !55}
!131 = !DIGlobalVariableExpression(var: !31, expr: !DIExpression())
!132 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())

View File

@ -0,0 +1,75 @@
; REQUIRES: x86-registered-target
; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}"
; CHECK-LABEL: debug_info contents
; CHECK: DW_TAG_compile_unit
; CHECK: DW_AT_GNU_dwo_name
; CHECK: DW_AT_GNU_dwo_id
; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_inlined_subroutine
; CHECK: NULL
; CHECK: NULL
; CHECK-LABEL: debug_info.dwo contents
; CHECK: DW_TAG_compile_unit
; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_imported_declaration
; CHECK: NULL
; CHECK: DW_TAG_subprogram
; CHECK: DW_TAG_inlined_subroutine
; CHECK: NULL
; CHECK: DW_TAG_namespace
; CHECK: DW_TAG_structure_type
; CHECK: NULL
; CHECK: DW_TAG_base_type
; CHECK: NULL
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%"struct.ns::t1" = type { i8 }
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare dso_local void @_Z3pinv() local_unnamed_addr
define dso_local i32 @main() local_unnamed_addr !dbg !18 {
entry:
call void @llvm.dbg.declare(metadata %"struct.ns::t1"* undef, metadata !22, metadata !DIExpression()), !dbg !23
call void @_Z3pinv(), !dbg !25
ret i32 0, !dbg !26
}
!llvm.dbg.cu = !{!0, !10}
!llvm.ident = !{!12, !12}
!llvm.module.flags = !{!13, !14, !15, !16, !17}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: true, nameTableKind: GNU)
!1 = !DIFile(filename: "a.cpp", directory: "/")
!2 = !{!3}
!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !8, file: !1, line: 3)
!4 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!5 = !DISubroutineType(types: !6)
!6 = !{null}
!7 = !{}
!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", scope: !9, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t1E")
!9 = !DINamespace(name: "ns", scope: null)
!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: true, nameTableKind: GNU)
!11 = !DIFile(filename: "b.cpp", directory: "/")
!12 = !{!"clang version 14.0.0"}
!13 = !{i32 7, !"Dwarf Version", i32 4}
!14 = !{i32 2, !"Debug Info Version", i32 3}
!15 = !{i32 1, !"wchar_size", i32 4}
!16 = !{i32 7, !"uwtable", i32 1}
!17 = !{i32 7, !"frame-pointer", i32 2}
!18 = distinct !DISubprogram(name: "main", scope: !11, file: !11, line: 2, type: !19, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !7)
!19 = !DISubroutineType(types: !20)
!20 = !{!21}
!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!22 = !DILocalVariable(name: "v1", scope: !4, file: !1, line: 3, type: !8)
!23 = !DILocation(line: 3, column: 37, scope: !4, inlinedAt: !24)
!24 = distinct !DILocation(line: 3, column: 3, scope: !18)
!25 = !DILocation(line: 3, column: 41, scope: !4, inlinedAt: !24)
!26 = !DILocation(line: 4, column: 1, scope: !18)

View File

@ -0,0 +1,44 @@
; REQUIRES: x86-registered-target
; RUN: %llc_dwarf -split-dwarf-file=%t.dwo < %s | FileCheck %s
; Ensure function-local DW_TAG_imported_declaration get skipped if its parent subprogram was not emitted.
; CHECK-NOT: DW_TAG_imported_declaration
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @f1() !dbg !13 {
lbl:
ret void, !dbg !16
}
define void @f2() !dbg !22 {
lbl:
ret void, !dbg !23
}
!llvm.dbg.cu = !{!0, !2, !10}
!llvm.module.flags = !{!12}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, emissionKind: FullDebug)
!1 = !DIFile(filename: "a.cc", directory: "")
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug)
!3 = !DIFile(filename: "b.cc", directory: "")
!4 = !{!5}
!5 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !6, entity: !7)
!6 = !DISubprogram(scope: null, spFlags: DISPFlagOptimized, retainedNodes: !4)
!7 = !DINamespace(scope: !2)
!8 = !DISubroutineType(types: !9)
!9 = !{}
!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11, emissionKind: FullDebug)
!11 = !DIFile(filename: "c.cc", directory: "")
!12 = !{i32 2, !"Debug Info Version", i32 3}
!13 = distinct !DISubprogram(scope: null, type: !8, spFlags: DISPFlagDefinition, unit: !0)
!16 = !DILocation(line: 0, scope: !17, inlinedAt: !18)
!17 = distinct !DISubprogram(scope: null, unit: !10)
!18 = !DILocation(line: 0, scope: !21)
!21 = !DILexicalBlockFile(scope: !13, discriminator: 0)
!22 = distinct !DISubprogram(scope: null, type: !8, spFlags: DISPFlagDefinition, unit: !0)
!23 = !DILocation(line: 0, scope: !24, inlinedAt: !25)
!24 = distinct !DISubprogram(scope: null, unit: !2)
!25 = !DILocation(line: 0, scope: !22)

View File

@ -0,0 +1,71 @@
; UNSUPPORTED: target={{.*}}-aix{{.*}}
; REQUIRES: x86-registered-target
; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s \
; RUN: | llvm-dwarfdump -debug-info - \
; RUN: | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Ensure that the imported entity 'nn::A' gets emitted in 'foo()'s abstract tree
; in the destination (where 'foo()' was inlined) compile unit.
; CHECK-LABEL: .debug_info contents
; CHECK: DW_TAG_skeleton_unit
; CHECK: DW_AT_dwo_name
; CHECK-LABEL: .debug_info.dwo contents:
; CHECK: DW_TAG_compile_unit
; CHECK: DW_AT_name ("test.cpp")
; CHECK: DW_AT_dwo_name
; CHECK: [[ABSTRACT_FOO:0x[0-9a-f]+]]: DW_TAG_subprogram
; CHECK: DW_AT_name ("foo")
; CHECK: DW_TAG_imported_declaration
; CHECK: DW_AT_import ([[A:0x[0-9a-f]+]])
; CHECK: NULL
; CHECK: DW_TAG_base_type
; CHECK: DW_AT_name ("int")
; CHECK: DW_TAG_subprogram
; CHECK: DW_AT_name ("main")
; CHECK: DW_TAG_inlined_subroutine
; CHECK: DW_AT_abstract_origin ([[ABSTRACT_FOO]] "_Z3foov")
; CHECK: NULL
; CHECK: DW_TAG_namespace
; CHECK: DW_AT_name ("nn")
; CHECK: [[A]]: DW_TAG_variable
; CHECK: DW_AT_name ("A")
; CHECK: NULL
; CHECK: NULL
define dso_local noundef i32 @main() local_unnamed_addr !dbg !20 {
entry:
ret i32 42, !dbg !21
}
!llvm.dbg.cu = !{!0, !2}
!llvm.module.flags = !{!13, !14}
!llvm.ident = !{!19, !19}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, splitDebugFilename: "test.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU)
!1 = !DIFile(filename: "test.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "e7c2808ee27614e496499d55e4b37962")
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, splitDebugFilename: "cu1.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU)
!3 = !DIFile(filename: "cu1.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "c0b84240ef5682b87083b33cf9038171")
!4 = !{!5}
!5 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !6, entity: !11, file: !3, line: 5)
!6 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 5, type: !7, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
!7 = !DISubroutineType(types: !8)
!8 = !{!9}
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!10 = !{}
!11 = distinct !DIGlobalVariable(name: "A", linkageName: "_ZN2nn1AE", scope: !12, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true)
!12 = !DINamespace(name: "nn", scope: null)
!13 = !{i32 7, !"Dwarf Version", i32 5}
!14 = !{i32 2, !"Debug Info Version", i32 3}
!19 = !{!"clang version 15.0.0"}
!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
!21 = !DILocation(line: 4, column: 3, scope: !6, inlinedAt: !22)
!22 = !DILocation(line: 4, column: 3, scope: !20)

View File

@ -38,7 +38,7 @@ define void @invalid_subprogram_declaration() !dbg !9 { ret void }
define void @invalid_retained_nodes_list() !dbg !10 { ret void }
!10 = distinct !DISubprogram(retainedNodes: !0)
; CHECK: invalid retained nodes, expected DILocalVariable or DILabel
; CHECK: invalid retained nodes, expected DILocalVariable, DILabel or DIImportedEntity
define void @invalid_retained_nodes_expected() !dbg !11 { ret void }
!11 = distinct !DISubprogram(retainedNodes: !{!0})

View File

@ -73,13 +73,13 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
!3 = !DIFile(filename: "em.f90", directory: "tests")
!4 = !DISubroutineType(types: !5)
!5 = !{null}
!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, imports: !9, splitDebugInlining: false, nameTableKind: None)
!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None)
!7 = !{}
!8 = !{!0}
!9 = !{!10}
!9 = !{}
!10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
!11 = !DIModule(scope: !2, name: "external_module", isDecl: true)
!12 = !{!13}
!12 = !{!10, !13}
!13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14)
!14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float)
!15 = !{i32 2, !"Debug Info Version", i32 3}

View File

@ -81,7 +81,7 @@ declare void @fort_init(...)
!1 = distinct !DIGlobalVariable(name: "var1", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true)
!2 = !DIModule(scope: !4, name: "mymod", file: !3, line: 1)
!3 = !DIFile(filename: "DIImportedEntity_elements.f90", directory: "/tmp")
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !12, nameTableKind: None)
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, nameTableKind: None)
!5 = !{}
!6 = !{!0, !7, !10}
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4))
@ -91,7 +91,7 @@ declare void @fort_init(...)
!11 = distinct !DIGlobalVariable(name: "var3", scope: !2, file: !3, line: 4, type: !9, isLocal: false, isDefinition: true)
!12 = !{!13}
!13 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !14, entity: !2, file: !3, line: 10, elements: !19)
!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4)
!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4, retainedNodes: !12)
!15 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 7, type: !16, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4)
!16 = !DISubroutineType(cc: DW_CC_program, types: !17)
!17 = !{null}

View File

@ -97,7 +97,7 @@ attributes #1 = { "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp
!llvm.module.flags = !{!22, !23}
!llvm.ident = !{!24}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !18)
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2)
!1 = !DIFile(filename: "fission-inline.cpp", directory: "/tmp/dbginfo")
!2 = !{}
!3 = !{!4}
@ -106,7 +106,7 @@ attributes #1 = { "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp
!6 = !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 4, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 4, file: !1, scope: !4, type: !7)
!7 = !DISubroutineType(types: !8)
!8 = !{null, null}
!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !2)
!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !18)
!11 = distinct !DISubprogram(name: "f2<int>", linkageName: "_ZN3foo2f2IiEEvv", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !4, type: !12, templateParams: !14, declaration: !17, retainedNodes: !2)
!12 = !DISubroutineType(types: !13)
!13 = !{null}

View File

@ -16,12 +16,12 @@ entry:
!llvm.module.flags = !{!9, !10, !11}
!llvm.ident = !{!12}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (trunk 349508) (llvm/trunk 349520)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3, nameTableKind: None)
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (trunk 349508) (llvm/trunk 349520)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
!1 = !DIFile(filename: "test.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
!2 = !{}
!3 = !{!4}
!4 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !8, file: !1, line: 2)
!5 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
!5 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !3)
!6 = !DISubroutineType(types: !7)
!7 = !{null}
!8 = !DINamespace(name: "ns1", scope: null)

View File

@ -53,7 +53,7 @@ attributes #1 = { "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp
!llvm.module.flags = !{!22, !23}
!llvm.ident = !{!24}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, splitDebugInlining: false, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !18)
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, splitDebugInlining: false, file: !1, enums: !2, retainedTypes: !3, globals: !2)
!1 = !DIFile(filename: "fission-inline.cpp", directory: "")
!2 = !{}
!3 = !{!4}
@ -62,7 +62,7 @@ attributes #1 = { "less-precise-fpmad"="false" "frame-pointer"="all" "no-infs-fp
!6 = !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 4, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 4, file: !1, scope: !4, type: !7)
!7 = !DISubroutineType(types: !8)
!8 = !{null, null}
!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !2)
!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !18)
!11 = distinct !DISubprogram(name: "f2<int>", linkageName: "_ZN3foo2f2IiEEvv", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !4, type: !12, templateParams: !14, declaration: !17, retainedNodes: !2)
!12 = !DISubroutineType(types: !13)
!13 = !{null}

View File

@ -119,10 +119,10 @@ attributes #2 = { nounwind }
!llvm.module.flags = !{!15, !16}
!llvm.ident = !{!17}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 264349)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, imports: !10)
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 264349)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2)
!1 = !DIFile(filename: "test.cpp", directory: "/")
!2 = !{}
!4 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!4 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !10)
!5 = !DISubroutineType(types: !6)
!6 = !{!7}
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)

View File

@ -41,7 +41,7 @@ source_filename = "namelist2.ll"
!1 = distinct !DIGlobalVariable(name: "aa", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true)
!2 = !DIModule(scope: !4, name: "mm", file: !3, line: 1)
!3 = !DIFile(filename: "namelist2.f90", directory: "/dir")
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist2.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !14, nameTableKind: None)
!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist2.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, nameTableKind: None)
!5 = !{}
!6 = !{!0, !7, !10}
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4))
@ -53,7 +53,7 @@ source_filename = "namelist2.ll"
!13 = !{!1, !8}
!14 = !{!15}
!15 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !16, entity: !2, file: !3, line: 6)
!16 = distinct !DISubprogram(name: "test", scope: !4, file: !3, line: 6, type: !17, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4)
!16 = distinct !DISubprogram(name: "test", scope: !4, file: !3, line: 6, type: !17, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !14)
!17 = !DISubroutineType(types: !18)
!18 = !{null}
!19 = !{i32 2, !"Dwarf Version", i32 4}

View File

@ -6,15 +6,15 @@
!llvm.dbg.cu = !{!0, !5}
!llvm.module.flags = !{!3, !4}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2)
!1 = !DIFile(filename: "<stdin>", directory: "/")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !6)
!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
!6 = !{!7}
!7 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !8, entity: !8, file: !1, line: 3)
!8 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !5, retainedNodes: !2)
!8 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !5, retainedNodes: !6)
!9 = !DISubroutineType(types: !10)
!10 = !{null}
!11 = !DINamespace(name: "ns", scope: null)

View File

@ -2,12 +2,11 @@
; RUN: llvm-as %p/Inputs/pr26037.ll -o %t2.bc
; RUN: llvm-link -S -only-needed %t2.bc %t.bc | FileCheck %s
; CHECK: !DIImportedEntity({{.*}}, scope: ![[B:[0-9]+]], entity: ![[A:[0-9]+]]
; CHECK: ![[B]] = distinct !DISubprogram(name: "b"
; CHECK: ![[CU_MAIN:[0-9]+]] = distinct !DICompileUnit(
; CHECK: ![[CU:[0-9]+]] = distinct !DICompileUnit(
; CHECK: !DIImportedEntity({{.*}}, scope: ![[CU]], entity: ![[A:[0-9]+]]
; CHECK: ![[A]] = distinct !DISubprogram(name: "a"
; CHECK: !DIImportedEntity({{.*}}, scope: ![[LBC:[0-9]+]], entity: ![[LBD:[0-9]+]]
; CHECK: ![[LBC]] = distinct !DILexicalBlock(scope: ![[C:[0-9]+]]
; CHECK: ![[C]] = distinct !DISubprogram(name: "c"
; CHECK: !DIImportedEntity({{.*}}, scope: ![[CU]], entity: ![[LBD:[0-9]+]]
; CHECK: ![[LBD]] = distinct !DILexicalBlock(scope: ![[D:[0-9]+]]
; CHECK: ![[D]] = distinct !DISubprogram(name: "d"
@ -16,16 +15,6 @@ entry:
ret void, !dbg !14
}
define void @_ZN1A1bEv() #0 !dbg !8 {
entry:
ret void, !dbg !15
}
define void @_ZN1A1cEv() #0 !dbg !18 {
entry:
ret void, !dbg !21
}
define void @_ZN1A1dEv() #0 !dbg !20 {
entry:
ret void, !dbg !22
@ -42,18 +31,13 @@ entry:
!5 = !DINamespace(name: "A", scope: null)
!6 = !DISubroutineType(types: !7)
!7 = !{null}
!8 = distinct !DISubprogram(name: "b", linkageName: "_ZN1A1bEv", scope: !5, file: !1, line: 8, type: !6, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!9 = !{!10, !16}
!10 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !8, entity: !4, file: !1, line: 8)
!10 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !4, file: !1, line: 8)
!11 = !{i32 2, !"Dwarf Version", i32 4}
!12 = !{i32 2, !"Debug Info Version", i32 3}
!13 = !{!"clang version 3.8.0 (trunk 256934) (llvm/trunk 256936)"}
!14 = !DILocation(line: 7, column: 12, scope: !4)
!15 = !DILocation(line: 8, column: 24, scope: !8)
!16 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !17, entity: !19, file: !1, line: 8)
!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 8)
!18 = distinct !DISubprogram(name: "c", linkageName: "_ZN1A1cEv", scope: !5, file: !1, line: 9, type: !6, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!16 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !19, file: !1, line: 8)
!19 = distinct !DILexicalBlock(scope: !20, file: !1, line: 10, column: 8)
!20 = distinct !DISubprogram(name: "d", linkageName: "_ZN1A1dEv", scope: !5, file: !1, line: 10, type: !6, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
!21 = !DILocation(line: 9, column: 8, scope: !18)
!22 = !DILocation(line: 10, column: 8, scope: !20)

View File

@ -5,15 +5,13 @@
; RUN: opt -module-summary %p/Inputs/debuginfo-cu-import.ll -o %t2.bc
; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc
; Don't import enums, macros, retainedTypes or globals lists.
; Only import local scope imported entities.
; Don't import enums, macros, retainedTypes, globals or imports lists.
; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s
; CHECK-NOT: DICompileUnit{{.*}} enums:
; CHECK-NOT: DICompileUnit{{.*}} macros:
; CHECK-NOT: DICompileUnit{{.*}} retainedTypes:
; CHECK-NOT: DICompileUnit{{.*}} globals:
; CHECK: DICompileUnit{{.*}} imports: ![[IMP:[0-9]+]]
; CHECK: ![[IMP]] = !{!{{[0-9]+}}}
; CHECK-NOT: DICompileUnit{{.*}} imports:
; ModuleID = 'debuginfo-cu-import.c'
source_filename = "debuginfo-cu-import.c"
@ -50,14 +48,14 @@ entry:
!8 = !{!9}
!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
!10 = !DIGlobalVariable(name: "version", scope: !4, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true)
!11 = !{!12, !16}
!11 = !{!12}
!12 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !13, file: !1, line: 8)
!13 = distinct !DISubprogram(name: "a", linkageName: "_ZN1A1aEv", scope: !4, file: !1, line: 7, type: !14, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
!14 = !DISubroutineType(types: !15)
!15 = !{null}
!16 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !17, entity: !19, file: !1, line: 8)
!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 8)
!18 = distinct !DISubprogram(name: "c", linkageName: "_ZN1A1cEv", scope: !4, file: !1, line: 9, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
!18 = distinct !DISubprogram(name: "c", linkageName: "_ZN1A1cEv", scope: !4, file: !1, line: 9, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !33)
!19 = distinct !DILexicalBlock(scope: !20, file: !1, line: 10, column: 8)
!20 = distinct !DISubprogram(name: "d", linkageName: "_ZN1A1dEv", scope: !4, file: !1, line: 10, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
!21 = !{!22}
@ -72,4 +70,4 @@ entry:
!30 = !DILocation(line: 7, column: 12, scope: !13)
!31 = distinct !DISubprogram(name: "b", linkageName: "_ZN1A1bEv", scope: !4, file: !1, line: 8, type: !14, isLocal: true, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5)
!32 = !DILocation(line: 8, column: 24, scope: !31)
!33 = !{!16}