mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Reapply "Serialize debug scope and location info in the SIL assembler language.""
This ireapplies commit 255c52de9f.
Original commit message:
Serialize debug scope and location info in the SIL assembler language.
At the moment it is only possible to test the effects that SIL
optimization passes have on debug information by observing the
effects of a full .swift -> LLVM IR compilation. This change enable us
to write targeted testcases for single SIL optimization passes.
The new syntax is as follows:
sil-scope-ref ::= 'scope' [0-9]+
sil-scope ::= 'sil_scope' [0-9]+ '{'
sil-loc
'parent' scope-parent
('inlined_at' sil-scope-ref )?
'}'
scope-parent ::= sil-function-name ':' sil-type
scope-parent ::= sil-scope-ref
sil-loc ::= 'loc' string-literal ':' [0-9]+ ':' [0-9]+
Each instruction may have a debug location and a SIL scope reference
at the end. Debug locations consist of a filename, a line number, and
a column number. If the debug location is omitted, it defaults to the
location in the SIL source file. SIL scopes describe the position
inside the lexical scope structure that the Swift expression a SIL
instruction was generated from had originally. SIL scopes also hold
inlining information.
<rdar://problem/22706994>
This commit is contained in:
@@ -389,9 +389,10 @@ class SILPrinter : public SILVisitor<SILPrinter> {
|
||||
unsigned LastBufferID;
|
||||
|
||||
llvm::DenseMap<const SILBasicBlock *, unsigned> BlocksToIDMap;
|
||||
llvm::DenseMap<const ValueBase *, unsigned> ValueToIDMap;
|
||||
SILFunction::ScopeSlotTracker *ScopeSlots;
|
||||
std::unique_ptr<SILFunction::ScopeSlotTracker> ManagedScopeSlotTracker;
|
||||
|
||||
llvm::DenseMap<const ValueBase*, unsigned> ValueToIDMap;
|
||||
|
||||
// Printers for the underlying stream.
|
||||
#define SIMPLE_PRINTER(TYPE) \
|
||||
SILPrinter &operator<<(TYPE value) { \
|
||||
@@ -426,11 +427,21 @@ class SILPrinter : public SILVisitor<SILPrinter> {
|
||||
}
|
||||
|
||||
public:
|
||||
SILPrinter(raw_ostream &OS, bool V = false, bool SortedSIL = false,
|
||||
llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr)
|
||||
: PrintState{{OS}, PrintOptions::printSIL()},
|
||||
Verbose(V), SortedSIL(SortedSIL), LastBufferID(0) {
|
||||
SILPrinter(
|
||||
raw_ostream &OS,
|
||||
bool V = false, bool SortedSIL = false,
|
||||
llvm::DenseMap<CanType, Identifier> *AlternativeTypeNames = nullptr,
|
||||
SILFunction::ScopeSlotTracker *ScopeTracker = nullptr)
|
||||
: PrintState{{OS}, PrintOptions::printSIL()}, Verbose(V),
|
||||
SortedSIL(SortedSIL), LastBufferID(0) {
|
||||
PrintState.ASTOptions.AlternativeTypeNames = AlternativeTypeNames;
|
||||
if (ScopeTracker)
|
||||
ScopeSlots = ScopeTracker;
|
||||
else {
|
||||
ManagedScopeSlotTracker =
|
||||
llvm::make_unique<SILFunction::ScopeSlotTracker>();
|
||||
ScopeSlots = ManagedScopeSlotTracker.get();
|
||||
}
|
||||
}
|
||||
|
||||
ID getID(const SILBasicBlock *B);
|
||||
@@ -558,6 +569,50 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void printDebugLocRef(SILLocation Loc, const SourceManager &SM,
|
||||
bool PrintComma = true) {
|
||||
auto DL = Loc.decodeDebugLoc(SM);
|
||||
if (DL.Filename) {
|
||||
if (PrintComma)
|
||||
*this << ", ";
|
||||
*this << "loc " << QuotedString(DL.Filename) << ':' << DL.Line << ':'
|
||||
<< DL.Column;
|
||||
}
|
||||
}
|
||||
|
||||
void printDebugScope(const SILDebugScope *DS, const SourceManager &SM) {
|
||||
if (!DS)
|
||||
return;
|
||||
|
||||
if (!ScopeSlots->ScopeToIDMap.count(DS)) {
|
||||
printDebugScope(DS->Parent.dyn_cast<const SILDebugScope *>(), SM);
|
||||
printDebugScope(DS->InlinedCallSite, SM);
|
||||
unsigned ID = ++(ScopeSlots->ScopeIndex);
|
||||
ScopeSlots->ScopeToIDMap.insert({DS, ID});
|
||||
*this << "sil_scope " << ID << " { ";
|
||||
printDebugLocRef(DS->Loc, SM, false);
|
||||
*this << " parent ";
|
||||
if (auto *F = DS->Parent.dyn_cast<SILFunction *>())
|
||||
*this << "@" << F->getName() << " : $" << F->getLoweredFunctionType();
|
||||
else {
|
||||
auto *PS = DS->Parent.get<const SILDebugScope *>();
|
||||
*this << ScopeSlots->ScopeToIDMap[PS];
|
||||
}
|
||||
if (auto *CS = DS->InlinedCallSite)
|
||||
*this << " inlined_at " << ScopeSlots->ScopeToIDMap[CS];
|
||||
*this << " }\n";
|
||||
}
|
||||
}
|
||||
|
||||
void printDebugScopeRef(const SILDebugScope *DS, const SourceManager &SM,
|
||||
bool PrintComma = true) {
|
||||
if (DS) {
|
||||
if (PrintComma)
|
||||
*this << ", ";
|
||||
*this << "scope " << ScopeSlots->ScopeToIDMap[DS];
|
||||
}
|
||||
}
|
||||
|
||||
void printSILLocation(SILLocation L, SILModule &M, const SILDebugScope *DS,
|
||||
bool printedSlashes) {
|
||||
if (!L.isNull()) {
|
||||
@@ -643,7 +698,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void print(SILValue V) {
|
||||
void print(SILValue V, bool PrintScopes = false) {
|
||||
// Lazily print any debug locations used in this value.
|
||||
if (PrintScopes)
|
||||
if (auto *I = dyn_cast<SILInstruction>(V)) {
|
||||
auto &SM = I->getModule().getASTContext().SourceMgr;
|
||||
printDebugScope(I->getDebugScope(), SM);
|
||||
}
|
||||
|
||||
if (auto *FRI = dyn_cast<FunctionRefInst>(V))
|
||||
*this << " // function_ref "
|
||||
<< demangleSymbol(FRI->getReferencedFunction()->getName())
|
||||
@@ -660,6 +722,12 @@ public:
|
||||
// Print the value.
|
||||
visit(V);
|
||||
|
||||
if (auto *I = dyn_cast<SILInstruction>(V)) {
|
||||
auto &SM = I->getModule().getASTContext().SourceMgr;
|
||||
printDebugLocRef(I->getLoc(), SM);
|
||||
printDebugScopeRef(I->getDebugScope(), SM);
|
||||
}
|
||||
|
||||
// Print users, or id for valueless instructions.
|
||||
bool printedSlashes = printUsersOfSILValue(V);
|
||||
|
||||
@@ -1587,8 +1655,17 @@ static void printLinkage(llvm::raw_ostream &OS, SILLinkage linkage,
|
||||
}
|
||||
|
||||
/// Pretty-print the SILFunction to the designated stream.
|
||||
void SILFunction::print(llvm::raw_ostream &OS, bool Verbose,
|
||||
void SILFunction::print(llvm::raw_ostream &OS,
|
||||
SILFunction::ScopeSlotTracker &MDT, bool Verbose,
|
||||
bool SortedSIL) const {
|
||||
auto &SM = getModule().getASTContext().SourceMgr;
|
||||
for (auto &BB : *this)
|
||||
for (auto &I : BB) {
|
||||
SILPrinter P(OS, Verbose, SortedSIL, nullptr, &MDT);
|
||||
P.printDebugScope(I.getDebugScope(), SM);
|
||||
}
|
||||
OS << "\n";
|
||||
|
||||
OS << "// " << demangleSymbol(getName()) << '\n';
|
||||
OS << "sil ";
|
||||
printLinkage(OS, getLinkage(), isDefinition());
|
||||
@@ -1667,9 +1744,10 @@ void SILFunction::print(llvm::raw_ostream &OS, bool Verbose,
|
||||
|
||||
if (!isExternalDeclaration()) {
|
||||
OS << " {\n";
|
||||
|
||||
SILPrinter(OS, Verbose, SortedSIL, (Aliases.empty() ? nullptr : &Aliases))
|
||||
.print(this);
|
||||
|
||||
SILPrinter(OS, Verbose, SortedSIL, (Aliases.empty() ? nullptr : &Aliases),
|
||||
&MDT)
|
||||
.print(this);
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
@@ -1749,12 +1827,13 @@ static void printSILGlobals(llvm::raw_ostream &OS, bool Verbose,
|
||||
g->print(OS, Verbose);
|
||||
}
|
||||
|
||||
static void printSILFunctions(llvm::raw_ostream &OS, bool Verbose,
|
||||
bool ShouldSort,
|
||||
static void printSILFunctions(llvm::raw_ostream &OS,
|
||||
bool Verbose, bool ShouldSort,
|
||||
const SILModule::FunctionListType &Functions) {
|
||||
SILFunction::ScopeSlotTracker Tracker;
|
||||
if (!ShouldSort) {
|
||||
for (const SILFunction &f : Functions)
|
||||
f.print(OS, Verbose);
|
||||
f.print(OS, Tracker, Verbose, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1768,7 +1847,7 @@ static void printSILFunctions(llvm::raw_ostream &OS, bool Verbose,
|
||||
}
|
||||
);
|
||||
for (const SILFunction *f : functions)
|
||||
f->print(OS, Verbose, true);
|
||||
f->print(OS, Tracker, Verbose, true);
|
||||
}
|
||||
|
||||
static void printSILVTables(llvm::raw_ostream &OS, bool Verbose,
|
||||
|
||||
Reference in New Issue
Block a user