summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-03-15 21:24:04 +0000
committerReid Kleckner <rnk@google.com>2018-03-15 21:24:04 +0000
commit5a791ee4081469d65d98fe02d4c767b455f6f69b (patch)
tree1fcef27558e2fac244bb1b1bb402218e986975d5 /llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parente9dc30d2c2add1bdc363a517f87d5a5ae26d094d (diff)
downloadbcm5719-llvm-5a791ee4081469d65d98fe02d4c767b455f6f69b.tar.gz
bcm5719-llvm-5a791ee4081469d65d98fe02d4c767b455f6f69b.zip
Re-land r327620 "[CodeView] Initial support for emitting S_BLOCK32 symbols for lexical scopes"
This is safe to land now that we don't copy FunctionInfo when rehashing the DenseMap. llvm-svn: 327670
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp147
1 files changed, 141 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 89a7974e473..5a413bed920 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -365,15 +365,15 @@ unsigned CodeViewDebug::getPointerSizeInBytes() {
}
void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
- const DILocation *InlinedAt) {
- if (InlinedAt) {
+ const LexicalScope *LS) {
+ if (const DILocation *InlinedAt = LS->getInlinedAt()) {
// This variable was inlined. Associate it with the InlineSite.
const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
Site.InlinedLocals.emplace_back(Var);
} else {
- // This variable goes in the main ProcSym.
- CurFn->Locals.emplace_back(Var);
+ // This variable goes into the corresponding lexical scope.
+ ScopeVariables[LS].emplace_back(Var);
}
}
@@ -905,6 +905,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.EmitLabel(ProcRecordEnd);
emitLocalVariableList(FI.Locals);
+ emitLexicalBlockList(FI.ChildBlocks, FI);
// Emit inlined call site information. Only emit functions inlined directly
// into the parent function. We'll emit the other sites recursively as part
@@ -1025,7 +1026,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
LocalVariable Var;
Var.DIVar = VI.Var;
Var.DefRanges.emplace_back(std::move(DefRange));
- recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
+ recordLocalVariable(std::move(Var), Scope);
}
}
@@ -1156,7 +1157,7 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
Var.DIVar = DIVar;
calculateRanges(Var, Ranges);
- recordLocalVariable(std::move(Var), InlinedAt);
+ recordLocalVariable(std::move(Var), Scope);
}
}
@@ -2363,6 +2364,131 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
}
}
+void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
+ const FunctionInfo& FI) {
+ for (LexicalBlock *Block : Blocks)
+ emitLexicalBlock(*Block, FI);
+}
+
+/// Emit an S_BLOCK32 and S_END record pair delimiting the contents of a
+/// lexical block scope.
+void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
+ const FunctionInfo& FI) {
+ MCSymbol *RecordBegin = MMI->getContext().createTempSymbol(),
+ *RecordEnd = MMI->getContext().createTempSymbol();
+
+ // Lexical block symbol record.
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(RecordEnd, RecordBegin, 2); // Record Length
+ OS.EmitLabel(RecordBegin);
+ OS.AddComment("Record kind: S_BLOCK32");
+ OS.EmitIntValue(SymbolKind::S_BLOCK32, 2); // Record Kind
+ OS.AddComment("PtrParent");
+ OS.EmitIntValue(0, 4); // PtrParent
+ OS.AddComment("PtrEnd");
+ OS.EmitIntValue(0, 4); // PtrEnd
+ OS.AddComment("Code size");
+ OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size
+ OS.AddComment("Function section relative address");
+ OS.EmitCOFFSecRel32(Block.Begin, /*Offset=*/0); // Func Offset
+ OS.AddComment("Function section index");
+ OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol
+ OS.AddComment("Lexical block name");
+ emitNullTerminatedSymbolName(OS, Block.Name); // Name
+ OS.EmitLabel(RecordEnd);
+
+ // Emit variables local to this lexical block.
+ emitLocalVariableList(Block.Locals);
+
+ // Emit lexical blocks contained within this block.
+ emitLexicalBlockList(Block.Children, FI);
+
+ // Close the lexical block scope.
+ OS.AddComment("Record length");
+ OS.EmitIntValue(2, 2); // Record Length
+ OS.AddComment("Record kind: S_END");
+ OS.EmitIntValue(SymbolKind::S_END, 2); // Record Kind
+}
+
+/// Convenience routine for collecting lexical block information for a list
+/// of lexical scopes.
+void CodeViewDebug::collectLexicalBlockInfo(
+ SmallVectorImpl<LexicalScope *> &Scopes,
+ SmallVectorImpl<LexicalBlock *> &Blocks,
+ SmallVectorImpl<LocalVariable> &Locals) {
+ for (LexicalScope *Scope : Scopes)
+ collectLexicalBlockInfo(*Scope, Blocks, Locals);
+}
+
+/// Populate the lexical blocks and local variable lists of the parent with
+/// information about the specified lexical scope.
+void CodeViewDebug::collectLexicalBlockInfo(
+ LexicalScope &Scope,
+ SmallVectorImpl<LexicalBlock *> &ParentBlocks,
+ SmallVectorImpl<LocalVariable> &ParentLocals) {
+ 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;
+
+ 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);
+ return;
+ }
+
+ // Create a new CodeView lexical block for this lexical scope. If we've
+ // seen this DILexicalBlock before then the scope tree is malformed and
+ // we can handle this gracefully by not processing it a second time.
+ auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
+ if (!BlockInsertion.second)
+ return;
+
+ // Create a lexical block containing the local 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;
+ Block.Begin = getLabelBeforeInsn(Range.first);
+ Block.End = getLabelAfterInsn(Range.second);
+ 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);
+ ParentBlocks.push_back(&Block);
+ collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals);
+}
+
void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
const Function &GV = MF->getFunction();
assert(FnDebugInfo.count(&GV));
@@ -2370,6 +2496,15 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
collectVariableInfo(GV.getSubprogram());
+ // Build the lexical block structure to emit for this routine.
+ if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
+ collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals);
+
+ // Clear the scope and variable information from the map which will not be
+ // valid after we have finished processing this routine. This also prepares
+ // the map for the subsequent routine.
+ ScopeVariables.clear();
+
// Don't emit anything if we don't have any line tables.
if (!CurFn->HaveLineInfo) {
FnDebugInfo.erase(&GV);
OpenPOWER on IntegriCloud