summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp201
1 files changed, 126 insertions, 75 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 4132b1a30c4..990f0f4670b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -124,6 +124,8 @@ CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
TheCPU =
mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());
+ collectGlobalVariableInfo();
+
// Check if we should emit type record hashes.
ConstantInt *GH = mdconst::extract_or_null<ConstantInt>(
MMI->getModule()->getModuleFlag("CodeViewGHash"));
@@ -1038,6 +1040,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
endSymbolRecord(FrameProcEnd);
emitLocalVariableList(FI, FI.Locals);
+ emitGlobalVariableList(FI.Globals);
emitLexicalBlockList(FI.ChildBlocks, FI);
// Emit inlined call site information. Only emit functions inlined directly
@@ -2046,6 +2049,7 @@ void CodeViewDebug::clear() {
GlobalUDTs.clear();
TypeIndices.clear();
CompleteTypeIndices.clear();
+ ScopeGlobals.clear();
}
void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
@@ -2648,6 +2652,7 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
// Emit variables local to this lexical block.
emitLocalVariableList(FI, Block.Locals);
+ emitGlobalVariableList(Block.Globals);
// Emit lexical blocks contained within this block.
emitLexicalBlockList(Block.Children, FI);
@@ -2661,9 +2666,10 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
void CodeViewDebug::collectLexicalBlockInfo(
SmallVectorImpl<LexicalScope *> &Scopes,
SmallVectorImpl<LexicalBlock *> &Blocks,
- SmallVectorImpl<LocalVariable> &Locals) {
+ SmallVectorImpl<LocalVariable> &Locals,
+ SmallVectorImpl<CVGlobalVariable> &Globals) {
for (LexicalScope *Scope : Scopes)
- collectLexicalBlockInfo(*Scope, Blocks, Locals);
+ collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
}
/// Populate the lexical blocks and local variable lists of the parent with
@@ -2671,45 +2677,58 @@ void CodeViewDebug::collectLexicalBlockInfo(
void CodeViewDebug::collectLexicalBlockInfo(
LexicalScope &Scope,
SmallVectorImpl<LexicalBlock *> &ParentBlocks,
- SmallVectorImpl<LocalVariable> &ParentLocals) {
+ SmallVectorImpl<LocalVariable> &ParentLocals,
+ SmallVectorImpl<CVGlobalVariable> &ParentGlobals) {
if (Scope.isAbstractScope())
return;
- auto LocalsIter = ScopeVariables.find(&Scope);
- if (LocalsIter == ScopeVariables.end()) {
- // This scope does not contain variables and can be eliminated.
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
- return;
- }
- SmallVectorImpl<LocalVariable> &Locals = LocalsIter->second;
-
+ // Gather information about the lexical scope including local variables,
+ // global variables, and address ranges.
+ bool IgnoreScope = false;
+ auto LI = ScopeVariables.find(&Scope);
+ SmallVectorImpl<LocalVariable> *Locals =
+ LI != ScopeVariables.end() ? &LI->second : nullptr;
+ auto GI = ScopeGlobals.find(Scope.getScopeNode());
+ SmallVectorImpl<CVGlobalVariable> *Globals =
+ GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode());
- if (!DILB) {
- // This scope is not a lexical block and can be eliminated, but keep any
- // local variables it contains.
- ParentLocals.append(Locals.begin(), Locals.end());
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
- return;
- }
-
const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges();
- if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) {
- // This lexical block scope has too many address ranges to represent in the
- // current CodeView format or does not have a valid address range.
- // Eliminate this lexical scope and promote any locals it contains to the
- // parent scope.
- //
- // For lexical scopes with multiple address ranges you may be tempted to
- // construct a single range covering every instruction where the block is
- // live and everything in between. Unfortunately, Visual Studio only
- // displays variables from the first matching lexical block scope. If the
- // first lexical block contains exception handling code or cold code which
- // is moved to the bottom of the routine creating a single range covering
- // nearly the entire routine, then it will hide all other lexical blocks
- // and the variables they contain.
- //
- ParentLocals.append(Locals.begin(), Locals.end());
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
+
+ // Ignore lexical scopes which do not contain variables.
+ if (!Locals && !Globals)
+ IgnoreScope = true;
+
+ // Ignore lexical scopes which are not lexical blocks.
+ if (!DILB)
+ IgnoreScope = true;
+
+ // Ignore scopes which have too many address ranges to represent in the
+ // current CodeView format or do not have a valid address range.
+ //
+ // For lexical scopes with multiple address ranges you may be tempted to
+ // construct a single range covering every instruction where the block is
+ // live and everything in between. Unfortunately, Visual Studio only
+ // displays variables from the first matching lexical block scope. If the
+ // first lexical block contains exception handling code or cold code which
+ // is moved to the bottom of the routine creating a single range covering
+ // nearly the entire routine, then it will hide all other lexical blocks
+ // and the variables they contain.
+ if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second))
+ IgnoreScope = true;
+
+ if (IgnoreScope) {
+ // This scope can be safely ignored and eliminating it will reduce the
+ // size of the debug information. Be sure to collect any variable and scope
+ // information from the this scope or any of its children and collapse them
+ // into the parent scope.
+ if (Locals)
+ ParentLocals.append(Locals->begin(), Locals->end());
+ if (Globals)
+ ParentGlobals.append(Globals->begin(), Globals->end());
+ collectLexicalBlockInfo(Scope.getChildren(),
+ ParentBlocks,
+ ParentLocals,
+ ParentGlobals);
return;
}
@@ -2720,8 +2739,8 @@ void CodeViewDebug::collectLexicalBlockInfo(
if (!BlockInsertion.second)
return;
- // Create a lexical block containing the local variables and collect the
- // the lexical block information for the children.
+ // Create a lexical block containing the variables and collect the the
+ // lexical block information for the children.
const InsnRange &Range = Ranges.front();
assert(Range.first && Range.second);
LexicalBlock &Block = BlockInsertion.first->second;
@@ -2730,9 +2749,15 @@ void CodeViewDebug::collectLexicalBlockInfo(
assert(Block.Begin && "missing label for scope begin");
assert(Block.End && "missing label for scope end");
Block.Name = DILB->getName();
- Block.Locals = std::move(Locals);
+ if (Locals)
+ Block.Locals = std::move(*Locals);
+ if (Globals)
+ Block.Globals = std::move(*Globals);
ParentBlocks.push_back(&Block);
- collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals);
+ collectLexicalBlockInfo(Scope.getChildren(),
+ Block.Children,
+ Block.Locals,
+ Block.Globals);
}
void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
@@ -2744,7 +2769,10 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
// Build the lexical block structure to emit for this routine.
if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
- collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals);
+ collectLexicalBlockInfo(*CFS,
+ CurFn->ChildBlocks,
+ CurFn->Locals,
+ CurFn->Globals);
// Clear the scope and variable information from the map which will not be
// valid after we have finished processing this routine. This also prepares
@@ -2861,7 +2889,7 @@ void CodeViewDebug::emitDebugInfoForUDTs(
}
}
-void CodeViewDebug::emitDebugInfoForGlobals() {
+void CodeViewDebug::collectGlobalVariableInfo() {
DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
GlobalMap;
for (const GlobalVariable &GV : MMI->getModule()->globals()) {
@@ -2874,42 +2902,56 @@ void CodeViewDebug::emitDebugInfoForGlobals() {
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
for (const MDNode *Node : CUs->operands()) {
const auto *CU = cast<DICompileUnit>(Node);
-
- // First, emit all globals that are not in a comdat in a single symbol
- // substream. MSVC doesn't like it if the substream is empty, so only open
- // it if we have at least one global to emit.
- switchToDebugSectionForSymbol(nullptr);
- MCSymbol *EndLabel = nullptr;
for (const auto *GVE : CU->getGlobalVariables()) {
- if (const auto *GV = GlobalMap.lookup(GVE))
- if (!GV->hasComdat() && !GV->isDeclarationForLinker()) {
- if (!EndLabel) {
- OS.AddComment("Symbol subsection for globals");
- EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- }
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(GVE->getVariable(), GV, Asm->getSymbol(GV));
- }
+ const auto *GV = GlobalMap.lookup(GVE);
+ if (!GV || GV->isDeclarationForLinker())
+ continue;
+ const DIGlobalVariable *DIGV = GVE->getVariable();
+ DIScope *Scope = DIGV->getScope();
+ SmallVector<CVGlobalVariable, 1> *VariableList;
+ if (Scope && isa<DILocalScope>(Scope)) {
+ // Locate a global variable list for this scope, creating one if
+ // necessary.
+ auto Insertion = ScopeGlobals.insert(
+ {Scope, std::unique_ptr<GlobalVariableList>()});
+ if (Insertion.second)
+ Insertion.first->second = llvm::make_unique<GlobalVariableList>();
+ VariableList = Insertion.first->second.get();
+ } else if (GV->hasComdat())
+ // Emit this global variable into a COMDAT section.
+ VariableList = &ComdatVariables;
+ else
+ // Emit this globla variable in a single global symbol section.
+ VariableList = &GlobalVariables;
+ CVGlobalVariable CVGV = {DIGV, GV};
+ VariableList->emplace_back(std::move(CVGV));
}
- if (EndLabel)
- endCVSubsection(EndLabel);
+ }
+}
- // Second, emit each global that is in a comdat into its own .debug$S
- // section along with its own symbol substream.
- for (const auto *GVE : CU->getGlobalVariables()) {
- if (const auto *GV = GlobalMap.lookup(GVE)) {
- if (GV->hasComdat()) {
- MCSymbol *GVSym = Asm->getSymbol(GV);
- OS.AddComment("Symbol subsection for " +
- Twine(GlobalValue::dropLLVMManglingEscape(GV->getName())));
- switchToDebugSectionForSymbol(GVSym);
- EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(GVE->getVariable(), GV, GVSym);
- endCVSubsection(EndLabel);
- }
- }
- }
+void CodeViewDebug::emitDebugInfoForGlobals() {
+ // First, emit all globals that are not in a comdat in a single symbol
+ // substream. MSVC doesn't like it if the substream is empty, so only open
+ // it if we have at least one global to emit.
+ switchToDebugSectionForSymbol(nullptr);
+ if (!GlobalVariables.empty()) {
+ OS.AddComment("Symbol subsection for globals");
+ MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
+ emitGlobalVariableList(GlobalVariables);
+ endCVSubsection(EndLabel);
+ }
+
+ // Second, emit each global that is in a comdat into its own .debug$S
+ // section along with its own symbol substream.
+ for (const CVGlobalVariable &CVGV : ComdatVariables) {
+ MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
+ OS.AddComment("Symbol subsection for " +
+ Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName())));
+ switchToDebugSectionForSymbol(GVSym);
+ MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
+ // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
+ emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
+ endCVSubsection(EndLabel);
}
}
@@ -2925,6 +2967,15 @@ void CodeViewDebug::emitDebugInfoForRetainedTypes() {
}
}
+// Emit each global variable in the specified array.
+void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) {
+ for (const CVGlobalVariable &CVGV : Globals) {
+ MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
+ // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
+ emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
+ }
+}
+
void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
const GlobalVariable *GV,
MCSymbol *GVSym) {
OpenPOWER on IntegriCloud