mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Enhance SILLocation so it can hold separate locations for diagnostics
and debug info. Drop most of the special SILLocation handling from IRGenDebugInfo and eliminate lots of redundant code. Swift SVN r22781
This commit is contained in:
@@ -147,7 +147,7 @@ IRGenDebugInfo::IRGenDebugInfo(const IRGenOptions &Opts,
|
||||
IGM(IGM),
|
||||
MetadataTypeDecl(nullptr),
|
||||
InternalType(nullptr),
|
||||
LastLoc({}),
|
||||
LastDebugLoc({}),
|
||||
LastScope(nullptr)
|
||||
{
|
||||
assert(Opts.DebugInfo);
|
||||
@@ -238,8 +238,10 @@ Location getDeserializedLoc(Decl* D) {
|
||||
|
||||
Location getLoc(SourceManager &SM, SourceLoc Loc) {
|
||||
Location L = {};
|
||||
L.Filename = SM.getBufferIdentifierForLoc(Loc);
|
||||
std::tie(L.Line, L.Col) = SM.getLineAndColumn(Loc);
|
||||
if (Loc.isValid()) {
|
||||
L.Filename = SM.getBufferIdentifierForLoc(Loc);
|
||||
std::tie(L.Line, L.Col) = SM.getLineAndColumn(Loc);
|
||||
}
|
||||
return L;
|
||||
}
|
||||
|
||||
@@ -260,75 +262,33 @@ Location getLoc(SourceManager &SM, WithLoc *S, bool End = false) {
|
||||
return getLoc(SM, Loc);
|
||||
}
|
||||
|
||||
/// getLocForLinetable - extract the start location from a SILLocation.
|
||||
/// \brief Return the start of the location's source range.
|
||||
static Location getStartLocation(SourceManager &SM,
|
||||
Optional<SILLocation> OptLoc) {
|
||||
if (!OptLoc) return {};
|
||||
return getLoc(SM, OptLoc->getStartSourceLoc());
|
||||
}
|
||||
|
||||
/// \brief Return the debug location from a SILLocation.
|
||||
static Location getDebugLocation(SourceManager &SM,
|
||||
Optional<SILLocation> OptLoc) {
|
||||
if (!OptLoc) return {};
|
||||
return getLoc(SM, OptLoc->getDebugSourceLoc());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Extract the start location from a SILLocation.
|
||||
///
|
||||
/// This returns a FullLocation, which contains the location that
|
||||
/// should be used for the linetable and the "true" AST location (used
|
||||
/// for, e.g., variable declarations).
|
||||
static FullLocation getLocation(SourceManager &SM,
|
||||
Optional<SILLocation> OptLoc) {
|
||||
if (!OptLoc)
|
||||
return {};
|
||||
if (!OptLoc) return {};
|
||||
|
||||
SILLocation Loc = OptLoc.getValue();
|
||||
// SILLocations primarily cater diagnostics, for the linetable we
|
||||
// sometimes want the end of, e.g., a closure expression.
|
||||
bool UseEnd = Loc.alwaysPointsToEnd()
|
||||
|| Loc.getKind() == SILLocation::ImplicitReturnKind;
|
||||
|
||||
if (Loc.isNull() || Loc.isAutoGenerated())
|
||||
return {};
|
||||
if (Expr *E = Loc.getAsASTNode<Expr>()) {
|
||||
if (isa<CallExpr>(E))
|
||||
UseEnd = true;
|
||||
auto ELoc = getLoc(SM, E, UseEnd);
|
||||
// Code that has an autoclosure as location should not show up in
|
||||
// the line table (rdar://problem/14627460). Note also that the
|
||||
// closure function still has a valid DW_AT_decl_line. Depending
|
||||
// on how we decide to resolve rdar://problem/14627460, we may
|
||||
// want to use the regular getLoc instead and rather use the
|
||||
// column info.
|
||||
if (isa<AutoClosureExpr>(E))
|
||||
return {{}, ELoc};
|
||||
return {ELoc, ELoc};
|
||||
}
|
||||
if (Pattern *P = Loc.getAsASTNode<Pattern>()) {
|
||||
auto PLoc = getLoc(SM, P, UseEnd);
|
||||
return {PLoc, PLoc};
|
||||
}
|
||||
if (Stmt *S = Loc.getAsASTNode<Stmt>()) {
|
||||
auto SLoc = getLoc(SM, S, UseEnd);
|
||||
auto LinetableLoc = (Loc.getKind() == SILLocation::CleanupKind)
|
||||
? getLoc(SM, S, true)
|
||||
: SLoc;
|
||||
return {LinetableLoc, SLoc};
|
||||
}
|
||||
|
||||
if (Decl *D = Loc.getAsASTNode<Decl>()) {
|
||||
auto DLoc = getLoc(SM, D, UseEnd);
|
||||
auto LinetableLoc = DLoc;
|
||||
if (Loc.isInPrologue())
|
||||
LinetableLoc = {};
|
||||
|
||||
// For return and cleanup code SILLocation points to the start,
|
||||
// because this is where we want diagnostics to appear. For the
|
||||
// line table, we want them to point to the end of the Decl.
|
||||
else if (Loc.getKind() == SILLocation::ImplicitReturnKind ||
|
||||
Loc.getKind() == SILLocation::CleanupKind)
|
||||
LinetableLoc = getLoc(SM, D, true);
|
||||
|
||||
return {LinetableLoc, DLoc};
|
||||
}
|
||||
|
||||
if (Loc.getKind() == SILLocation::SILFileKind) {
|
||||
// Return the location within the SIL file. This is useful for
|
||||
// debugging SIL optimizations.
|
||||
auto SILFileLoc = static_cast<SILFileLocation*>(&Loc);
|
||||
auto SILLoc = getLoc(SM, SILFileLoc->getFileLocation());
|
||||
return { SILLoc, SILLoc };
|
||||
}
|
||||
|
||||
llvm_unreachable("unexpected location type");
|
||||
return { getLoc(SM, Loc.getDebugSourceLoc()),
|
||||
getLoc(SM, Loc.getSourceLoc())};
|
||||
}
|
||||
|
||||
/// Determine whether this debug scope belongs to an explicit closure.
|
||||
@@ -370,7 +330,7 @@ llvm::MDNode* IRGenDebugInfo::createInlinedAt(SILDebugScope *InlinedScope) {
|
||||
if (CallSite->InlinedCallSite)
|
||||
InlinedAt = createInlinedAt(CallSite);
|
||||
|
||||
auto InlineLoc = getLocation(SM, CallSite->Loc).LocForLinetable;
|
||||
auto InlineLoc = getLoc(SM, CallSite->Loc.getDebugSourceLoc());
|
||||
auto DL = llvm::DebugLoc::get(InlineLoc.Line, InlineLoc.Col,
|
||||
ParentScope, InlinedAt);
|
||||
return DL.getAsMDNode(IGM.getLLVMContext());
|
||||
@@ -399,7 +359,7 @@ bool IRGenDebugInfo::lineNumberIsSane(IRBuilder &Builder, unsigned Line) {
|
||||
// Assert monotonically increasing line numbers within the same basic block;
|
||||
llvm::BasicBlock *CurBasicBlock = Builder.GetInsertBlock();
|
||||
if (CurBasicBlock == LastBasicBlock) {
|
||||
return Line >= LastLoc.LocForLinetable.Line;
|
||||
return Line >= LastDebugLoc.Line;
|
||||
}
|
||||
LastBasicBlock = CurBasicBlock;
|
||||
return true;
|
||||
@@ -417,14 +377,14 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
if (!Scope.Verify())
|
||||
return;
|
||||
|
||||
FullLocation L = getLocation(SM, Loc);
|
||||
auto File = getOrCreateFile(L.LocForLinetable.Filename);
|
||||
Location L = getDebugLocation(SM, Loc);
|
||||
auto File = getOrCreateFile(L.Filename);
|
||||
if (Scope.isScope() &&
|
||||
File.getFilename() != llvm::DIScope(Scope).getFilename()) {
|
||||
// We changed files in the middle of a scope. This happens, for
|
||||
// example, when constructors are inlined. Create a new scope to
|
||||
// reflect this.
|
||||
auto File = getOrCreateFile(L.LocForLinetable.Filename);
|
||||
auto File = getOrCreateFile(L.Filename);
|
||||
Scope = DBuilder.createLexicalBlockFile(Scope, File);
|
||||
}
|
||||
|
||||
@@ -443,16 +403,16 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
&& Loc->getKind() != SILLocation::ImplicitReturnKind)
|
||||
return;
|
||||
|
||||
if (L.LocForLinetable.Line == 0 && DS == LastScope) {
|
||||
if (L.Line == 0 && DS == LastScope) {
|
||||
// Reuse the last source location if we are still in the same
|
||||
// scope to get a more contiguous line table.
|
||||
L = LastLoc;
|
||||
L = LastDebugLoc;
|
||||
}
|
||||
|
||||
//FIXME: Enable this assertion.
|
||||
//assert(lineNumberIsSane(Builder, L.LocForLinetable.Line) &&
|
||||
//assert(lineNumberIsSane(Builder, L.Line) &&
|
||||
// "-Onone, but line numbers are not monotonically increasing within bb");
|
||||
LastLoc = L;
|
||||
LastDebugLoc = L;
|
||||
LastScope = DS;
|
||||
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
@@ -463,8 +423,7 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
|
||||
assert(((!InlinedAt) || (InlinedAt && Scope)) && "inlined w/o scope");
|
||||
assert(parentScopesAreSane(DS) && "parent scope sanity check failed");
|
||||
auto DL = llvm::DebugLoc::get(L.LocForLinetable.Line, L.LocForLinetable.Col,
|
||||
Scope, InlinedAt);
|
||||
auto DL = llvm::DebugLoc::get(L.Line, L.Col, Scope, InlinedAt);
|
||||
// TODO: Write a strongly-worded letter to the person that came up
|
||||
// with a pair of functions spelled "get" and "Set".
|
||||
Builder.SetCurrentDebugLocation(DL);
|
||||
@@ -510,7 +469,7 @@ llvm::DIDescriptor IRGenDebugInfo::getOrCreateScope(SILDebugScope *DS) {
|
||||
}
|
||||
|
||||
assert(DS->Parent && "lexical block must have a parent subprogram");
|
||||
Location L = getLocation(SM, DS->Loc).Loc;
|
||||
Location L = getStartLocation(SM, DS->Loc);
|
||||
llvm::DIFile File = getOrCreateFile(L.Filename);
|
||||
llvm::DIDescriptor Parent = getOrCreateScope(DS->Parent);
|
||||
llvm::DILexicalBlock DScope =
|
||||
@@ -1193,7 +1152,7 @@ void IRGenDebugInfo::emitGlobalVariableDeclaration(llvm::GlobalValue *Var,
|
||||
// would confuse both the user and LLDB.
|
||||
return;
|
||||
|
||||
Location L = getLocation(SM, Loc).Loc;
|
||||
Location L = getStartLocation(SM, Loc);
|
||||
|
||||
// Global variables in the top level compilation unit are emitted as
|
||||
// local static variables of SWIFT_ENTRY_POINT_FUNCTION so they
|
||||
|
||||
Reference in New Issue
Block a user