Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 6 additions & 71 deletions llvm/tools/objwriter/debugInfo/dwarf/dwarfGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,96 +492,31 @@ static void EmitVarLocation(MCObjectStreamer *Streamer,
class LexicalScope
{
public:
LexicalScope(uint64_t Start, uint64_t End, bool IsFuncScope = false) :
Start(Start),
End(End),
IsFuncScope(IsFuncScope) {}

LexicalScope(VarInfo *Info) :
Start(Info->GetStartOffset()),
End(Info->GetEndOffset()),
IsFuncScope(false) { Vars.push_back(Info); }

bool IsContains(const VarInfo *Info) const {
return Start <= Info->GetStartOffset() && End >= Info->GetEndOffset();
}
/// At the moment, the lexical scope reflects IL, not C#, meaning that
/// there is only one scope for the whole method. We could be more precise
/// in the future by pulling the scope information from the PDB.
Comment on lines +496 to +497
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know how the lexical scope information is used by debugger? I suppose it allows the debugger to provide the values of only the subset of locals that are relevant in the current context of the function?

Note that the JIT will shorten and lengthen the live ranges of locals in arbitrary ways when optimizing, but presumably the debugger handles the live ranges and the lexical scopes as two separate sources of "which local values should be displayed here".

In debug the JIT will extend the live range of all IL locals to the full function, regardless of when they are last used (both as a throughput optimization and for diagnostic purposes). Without having these lexical scopes I assume it means that the debugger may display multiple separate locals of the same name (e.g. think two i induction variables from separate loops). If I understand correctly this is what makes having these lexical scopes desirable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that description sounds right to me.

LexicalScope() {}

void AddVar(VarInfo *Info);

void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr);

private:
uint64_t Start;
uint64_t End;
bool IsFuncScope;
std::vector<VarInfo*> Vars;
std::vector<LexicalScope> InnerScopes;
};

void LexicalScope::AddVar(VarInfo *Info) {
if (Info->IsParam() && IsFuncScope) {
Vars.push_back(Info);
return;
}

if (!IsContains(Info))
return;

uint64_t VarStart = Info->GetStartOffset();
uint64_t VarEnd = Info->GetEndOffset();

// Var belongs to inner scope
if (VarStart != Start || VarEnd != End) {
// Try to add variable to one the inner scopes
for (auto &Scope : InnerScopes) {
if (Scope.IsContains(Info)) {
Scope.AddVar(Info);
return;
}
}
// We need to create new inner scope for this var
InnerScopes.emplace_back(Info);
} else {
Vars.push_back(Info);
}
Vars.push_back(Info);
}

void LexicalScope::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr) {
Streamer->SwitchSection(TypeSection);

if (!IsFuncScope)
{
// Dump lexical block DIE
MCContext &context = Streamer->getContext();
unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();

// Abbrev Number
Streamer->emitULEB128IntValue(DwarfAbbrev::LexicalBlock);

// DW_AT_low_pc
const MCExpr *StartExpr = MCConstantExpr::create(Start, context);
const MCExpr *LowPcExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
StartExpr, context);
Streamer->emitValue(LowPcExpr, TargetPointerSize);

// DW_AT_high_pc
Streamer->emitIntValue(End - Start, TargetPointerSize);
}

for (auto *Var : Vars) {
Var->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
}

for (auto &Scope : InnerScopes) {
Scope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr);
}

if (!IsFuncScope) {
// Terminate block
Streamer->emitIntValue(0, 1);
}
}

// StaticVarInfo
Expand Down Expand Up @@ -855,7 +790,7 @@ void SubprogramInfo::DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjec
MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);

LexicalScope FuncScope(0, Size, true);
LexicalScope FuncScope;

for (unsigned i = 0; i < VarInfos.size(); i++) {
FuncScope.AddVar(&VarInfos[i]);
Expand Down