Skip to content

Commit b4781f6

Browse files
committed
Debug Info: Create artificial functions in a virtual file <compiler-generated>.
For the majority of artificial helper functions the filename is actively misleading since it usually represents the file of the caller that triggered the helper to be generated. Instead, this patch creates a virtual filname `<compiler-generated>` to make it very obvious that the function has not correspondence to any source code. <rdar://problem/33809560>
1 parent c74ae5f commit b4781f6

File tree

5 files changed

+42
-29
lines changed

5 files changed

+42
-29
lines changed

include/swift/SIL/SILLocation.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ class SILLocation {
432432
return isDebugInfoLoc() ? Loc.DebugInfoLoc
433433
: decode(getDebugSourceLoc(), SM);
434434
}
435+
436+
/// Compiler-generated locations may be applied to instructions without any
437+
/// clear correspondence to an AST node in an otherwise normal function.
438+
static DebugLoc getCompilerGeneratedDebugLoc() {
439+
return {0, 0, "<compiler-generated>"};
440+
}
435441

436442
/// Pretty-print the value.
437443
void dump(const SourceManager &SM) const;
@@ -487,8 +493,11 @@ class RegularLocation : public SILLocation {
487493
/// specified type is incorrect, asserts.
488494
template <typename T> T *castTo() const { return castNodeTo<T>(Loc.ASTNode); }
489495

496+
/// Compiler-generated locations may be applied to instructions without any
497+
/// clear correspondence to an AST node in an otherwise normal function.
498+
/// The auto-generated bit also turns off certain diagnostics passes such.
490499
static RegularLocation getAutoGeneratedLocation() {
491-
RegularLocation AL;
500+
RegularLocation AL(getCompilerGeneratedDebugLoc());
492501
AL.markAutoGenerated();
493502
return AL;
494503
}
@@ -502,12 +511,6 @@ class RegularLocation : public SILLocation {
502511
}
503512
};
504513

505-
/// Compiler-generated locations may be applied to instructions without any
506-
/// clear correspondence to an AST node.
507-
static inline RegularLocation getCompilerGeneratedLocation() {
508-
return {SourceLoc()};
509-
}
510-
511514
/// Used to represent a return instruction in user code.
512515
///
513516
/// Allowed on an BranchInst, ReturnInst.
@@ -712,7 +715,8 @@ class SILDebugLocation {
712715

713716
public:
714717
SILDebugLocation()
715-
: Scope(nullptr), Location(getCompilerGeneratedLocation()) {}
718+
: Scope(nullptr),
719+
Location(RegularLocation::getAutoGeneratedLocation()) {}
716720
SILDebugLocation(SILLocation Loc, const SILDebugScope *DS)
717721
: Scope(DS), Location(Loc) {}
718722
SILLocation getLocation() const { return Location; }

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,20 +1561,23 @@ void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder,
15611561
if (!Scope)
15621562
return;
15631563

1564-
SILFunction *Fn = DS->getInlinedFunction();
15651564
SILLocation::DebugLoc L;
1566-
1567-
if ((Loc && Loc->isAutoGenerated()) || (Fn && Fn->isThunk())) {
1565+
SILFunction *Fn = DS->getInlinedFunction();
1566+
if (Fn && Fn->isThunk()) {
1567+
L = SILLocation::getCompilerGeneratedDebugLoc();
1568+
} else if (DS == LastScope && Loc && Loc->isAutoGenerated()) {
15681569
// Reuse the last source location if we are still in the same
15691570
// scope to get a more contiguous line table.
1570-
// Otherwise use a line 0 artificial location.
1571-
if (DS == LastScope)
1572-
L = LastDebugLoc;
1573-
else
1574-
L.Filename = LastDebugLoc.Filename;
1571+
L = LastDebugLoc;
15751572
} else {
15761573
// Decode the location.
15771574
L = getDebugLocation(Loc);
1575+
// Otherwise use a line 0 artificial location, but the file from the
1576+
// location.
1577+
if (Loc && Loc->isAutoGenerated()) {
1578+
L.Line = 0;
1579+
L.Column = 0;
1580+
}
15781581
}
15791582

15801583
auto *File = getOrCreateFile(L.Filename);
@@ -1748,17 +1751,20 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
17481751
Name = getName(DS->Loc);
17491752
}
17501753

1754+
/// The source line used for the function prologue.
1755+
unsigned ScopeLine = 0;
17511756
SILLocation::DebugLoc L;
1752-
unsigned ScopeLine = 0; /// The source line used for the function prologue.
1753-
// Bare functions and thunks should not have any line numbers. This
1754-
// is especially important for shared functions like reabstraction
1755-
// thunk helpers, where DS->Loc is an arbitrary location of whichever use
1756-
// was emitted first.
17571757
if (DS && (!SILFn || (!SILFn->isBare() && !SILFn->isThunk()))) {
1758+
// Bare functions and thunks should not have any line numbers. This
1759+
// is especially important for shared functions like reabstraction
1760+
// thunk helpers, where DS->Loc is an arbitrary location of whichever use
1761+
// was emitted first.
17581762
L = decodeDebugLoc(DS->Loc);
17591763
ScopeLine = L.Line;
17601764
if (!DS->Loc.isDebugInfoLoc())
17611765
L = decodeSourceLoc(DS->Loc.getSourceLoc());
1766+
} else {
1767+
L = SILLocation::getCompilerGeneratedDebugLoc();
17621768
}
17631769

17641770
auto Line = L.Line;
@@ -1769,8 +1775,7 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
17691775

17701776
// We know that main always comes from MainFile.
17711777
if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION) {
1772-
if (L.Filename.empty())
1773-
File = MainFile;
1778+
File = MainFile;
17741779
Line = 1;
17751780
Name = LinkageName;
17761781
}
@@ -1787,16 +1792,15 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
17871792
bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
17881793
bool IsDefinition = true;
17891794
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
1790-
17911795
// Mark everything that is not visible from the source code (i.e.,
17921796
// does not have a Swift name) as artificial, so the debugger can
17931797
// ignore it. Explicit closures are exempt from this rule. We also
17941798
// make an exception for toplevel code, which, although it does not
17951799
// have a Swift name, does appear prominently in the source code.
1800+
// ObjC thunks should also not show up in the linetable, because we
1801+
// never want to set a breakpoint there.
17961802
if ((Name.empty() && LinkageName != SWIFT_ENTRY_POINT_FUNCTION &&
17971803
!isExplicitClosure(SILFn)) ||
1798-
// ObjC thunks should also not show up in the linetable, because we
1799-
// never want to set a breakpoint there.
18001804
(Rep == SILFunctionTypeRepresentation::ObjCMethod) ||
18011805
isAllocatingConstructor(Rep, DeclCtx)) {
18021806
Flags |= llvm::DINode::FlagArtificial;
@@ -1849,7 +1853,9 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
18491853
RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
18501854
const SILDebugScope *Scope = new (IGM.getSILModule()) SILDebugScope(ALoc);
18511855
emitFunction(Scope, Fn, SILFunctionTypeRepresentation::Thin, SILTy);
1852-
setCurrentLoc(Builder, Scope);
1856+
/// Reusing the current file would be wrong: An objc thunk, for example, could
1857+
/// be triggered from any random location. Use a placeholder name instead.
1858+
setCurrentLoc(Builder, Scope, ALoc);
18531859
}
18541860

18551861
void IRGenDebugInfoImpl::emitVariableDeclaration(

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
457457
auto fn = existingFn;
458458

459459
// TODO: use the correct SILLocation from module.
460-
SILLocation loc = getCompilerGeneratedLocation();
460+
SILLocation loc = RegularLocation::getAutoGeneratedLocation();
461461

462462
// If we have an existing function, verify that the types match up.
463463
if (fn) {

test/DebugInfo/basic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func foo(_ a: Int64, _ b: Int64) -> Int64 {
7070
// CHECK-DAG: ![[FILE_CWD:[0-9]+]] = !DIFile(filename: "{{.*}}DebugInfo/basic.swift", directory: "{{.*}}")
7171
// CHECK-DAG: ![[MAINFILE:[0-9]+]] = !DIFile(filename: "basic.swift", directory: "{{.*}}DebugInfo")
7272
// CHECK-DAG: !DICompileUnit(language: DW_LANG_Swift, file: ![[FILE_CWD]],{{.*}} producer: "{{.*}}Swift version{{.*}},{{.*}} flags: "{{[^"]*}}-emit-ir
73-
// CHECK-DAG: !DISubprogram(name: "main"
73+
// CHECK-DAG: !DISubprogram(name: "main", {{.*}}file: ![[MAINFILE]],
7474

7575
// Function type for foo.
7676
// CHECK-DAG: ![[FOOTYPE]] = !DISubroutineType(types: ![[PARAMTYPES:[0-9]+]])

test/DebugInfo/thunks.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ let i = foo.foo(-, x: y)
1616
// CHECK: define {{.*}}@"$Ss5Int64VABIyByd_A2BIgyd_TR"
1717
// CHECK-NOT: ret
1818
// CHECK: call {{.*}}, !dbg ![[LOC:.*]]
19+
// CHECK: ![[FILE:[0-9]+]] = !DIFile(filename: "<compiler-generated>", directory: "")
1920
// CHECK: ![[THUNK:.*]] = distinct !DISubprogram(linkageName: "$Ss5Int64VABIyByd_A2BIgyd_TR"
21+
// CHECK-SAME: file: ![[FILE]]
2022
// CHECK-NOT: line:
23+
// CHECK-SAME: flags: DIFlagArtificial
2124
// CHECK-SAME: ){{$}}
2225
// CHECK: ![[LOC]] = !DILocation(line: 0, scope: ![[THUNK]])
2326

0 commit comments

Comments
 (0)