mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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>
This commit is contained in:
@@ -432,6 +432,12 @@ public:
|
||||
return isDebugInfoLoc() ? Loc.DebugInfoLoc
|
||||
: decode(getDebugSourceLoc(), SM);
|
||||
}
|
||||
|
||||
/// Compiler-generated locations may be applied to instructions without any
|
||||
/// clear correspondence to an AST node in an otherwise normal function.
|
||||
static DebugLoc getCompilerGeneratedDebugLoc() {
|
||||
return {0, 0, "<compiler-generated>"};
|
||||
}
|
||||
|
||||
/// Pretty-print the value.
|
||||
void dump(const SourceManager &SM) const;
|
||||
@@ -487,8 +493,11 @@ public:
|
||||
/// specified type is incorrect, asserts.
|
||||
template <typename T> T *castTo() const { return castNodeTo<T>(Loc.ASTNode); }
|
||||
|
||||
/// Compiler-generated locations may be applied to instructions without any
|
||||
/// clear correspondence to an AST node in an otherwise normal function.
|
||||
/// The auto-generated bit also turns off certain diagnostics passes such.
|
||||
static RegularLocation getAutoGeneratedLocation() {
|
||||
RegularLocation AL;
|
||||
RegularLocation AL(getCompilerGeneratedDebugLoc());
|
||||
AL.markAutoGenerated();
|
||||
return AL;
|
||||
}
|
||||
@@ -502,12 +511,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
/// Compiler-generated locations may be applied to instructions without any
|
||||
/// clear correspondence to an AST node.
|
||||
static inline RegularLocation getCompilerGeneratedLocation() {
|
||||
return {SourceLoc()};
|
||||
}
|
||||
|
||||
/// Used to represent a return instruction in user code.
|
||||
///
|
||||
/// Allowed on an BranchInst, ReturnInst.
|
||||
@@ -712,7 +715,8 @@ class SILDebugLocation {
|
||||
|
||||
public:
|
||||
SILDebugLocation()
|
||||
: Scope(nullptr), Location(getCompilerGeneratedLocation()) {}
|
||||
: Scope(nullptr),
|
||||
Location(RegularLocation::getAutoGeneratedLocation()) {}
|
||||
SILDebugLocation(SILLocation Loc, const SILDebugScope *DS)
|
||||
: Scope(DS), Location(Loc) {}
|
||||
SILLocation getLocation() const { return Location; }
|
||||
|
||||
@@ -1561,20 +1561,23 @@ void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder,
|
||||
if (!Scope)
|
||||
return;
|
||||
|
||||
SILFunction *Fn = DS->getInlinedFunction();
|
||||
SILLocation::DebugLoc L;
|
||||
|
||||
if ((Loc && Loc->isAutoGenerated()) || (Fn && Fn->isThunk())) {
|
||||
SILFunction *Fn = DS->getInlinedFunction();
|
||||
if (Fn && Fn->isThunk()) {
|
||||
L = SILLocation::getCompilerGeneratedDebugLoc();
|
||||
} else if (DS == LastScope && Loc && Loc->isAutoGenerated()) {
|
||||
// Reuse the last source location if we are still in the same
|
||||
// scope to get a more contiguous line table.
|
||||
// Otherwise use a line 0 artificial location.
|
||||
if (DS == LastScope)
|
||||
L = LastDebugLoc;
|
||||
else
|
||||
L.Filename = LastDebugLoc.Filename;
|
||||
L = LastDebugLoc;
|
||||
} else {
|
||||
// Decode the location.
|
||||
L = getDebugLocation(Loc);
|
||||
// Otherwise use a line 0 artificial location, but the file from the
|
||||
// location.
|
||||
if (Loc && Loc->isAutoGenerated()) {
|
||||
L.Line = 0;
|
||||
L.Column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto *File = getOrCreateFile(L.Filename);
|
||||
@@ -1748,17 +1751,20 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
|
||||
Name = getName(DS->Loc);
|
||||
}
|
||||
|
||||
/// The source line used for the function prologue.
|
||||
unsigned ScopeLine = 0;
|
||||
SILLocation::DebugLoc L;
|
||||
unsigned ScopeLine = 0; /// The source line used for the function prologue.
|
||||
// Bare functions and thunks should not have any line numbers. This
|
||||
// is especially important for shared functions like reabstraction
|
||||
// thunk helpers, where DS->Loc is an arbitrary location of whichever use
|
||||
// was emitted first.
|
||||
if (DS && (!SILFn || (!SILFn->isBare() && !SILFn->isThunk()))) {
|
||||
// Bare functions and thunks should not have any line numbers. This
|
||||
// is especially important for shared functions like reabstraction
|
||||
// thunk helpers, where DS->Loc is an arbitrary location of whichever use
|
||||
// was emitted first.
|
||||
L = decodeDebugLoc(DS->Loc);
|
||||
ScopeLine = L.Line;
|
||||
if (!DS->Loc.isDebugInfoLoc())
|
||||
L = decodeSourceLoc(DS->Loc.getSourceLoc());
|
||||
} else {
|
||||
L = SILLocation::getCompilerGeneratedDebugLoc();
|
||||
}
|
||||
|
||||
auto Line = L.Line;
|
||||
@@ -1769,8 +1775,7 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
|
||||
|
||||
// We know that main always comes from MainFile.
|
||||
if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION) {
|
||||
if (L.Filename.empty())
|
||||
File = MainFile;
|
||||
File = MainFile;
|
||||
Line = 1;
|
||||
Name = LinkageName;
|
||||
}
|
||||
@@ -1787,16 +1792,15 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
|
||||
bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
|
||||
bool IsDefinition = true;
|
||||
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
|
||||
|
||||
// Mark everything that is not visible from the source code (i.e.,
|
||||
// does not have a Swift name) as artificial, so the debugger can
|
||||
// ignore it. Explicit closures are exempt from this rule. We also
|
||||
// make an exception for toplevel code, which, although it does not
|
||||
// have a Swift name, does appear prominently in the source code.
|
||||
// ObjC thunks should also not show up in the linetable, because we
|
||||
// never want to set a breakpoint there.
|
||||
if ((Name.empty() && LinkageName != SWIFT_ENTRY_POINT_FUNCTION &&
|
||||
!isExplicitClosure(SILFn)) ||
|
||||
// ObjC thunks should also not show up in the linetable, because we
|
||||
// never want to set a breakpoint there.
|
||||
(Rep == SILFunctionTypeRepresentation::ObjCMethod) ||
|
||||
isAllocatingConstructor(Rep, DeclCtx)) {
|
||||
Flags |= llvm::DINode::FlagArtificial;
|
||||
@@ -1849,7 +1853,9 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,
|
||||
RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation();
|
||||
const SILDebugScope *Scope = new (IGM.getSILModule()) SILDebugScope(ALoc);
|
||||
emitFunction(Scope, Fn, SILFunctionTypeRepresentation::Thin, SILTy);
|
||||
setCurrentLoc(Builder, Scope);
|
||||
/// Reusing the current file would be wrong: An objc thunk, for example, could
|
||||
/// be triggered from any random location. Use a placeholder name instead.
|
||||
setCurrentLoc(Builder, Scope, ALoc);
|
||||
}
|
||||
|
||||
void IRGenDebugInfoImpl::emitVariableDeclaration(
|
||||
|
||||
@@ -457,7 +457,7 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
auto fn = existingFn;
|
||||
|
||||
// TODO: use the correct SILLocation from module.
|
||||
SILLocation loc = getCompilerGeneratedLocation();
|
||||
SILLocation loc = RegularLocation::getAutoGeneratedLocation();
|
||||
|
||||
// If we have an existing function, verify that the types match up.
|
||||
if (fn) {
|
||||
|
||||
@@ -70,7 +70,7 @@ func foo(_ a: Int64, _ b: Int64) -> Int64 {
|
||||
// CHECK-DAG: ![[FILE_CWD:[0-9]+]] = !DIFile(filename: "{{.*}}DebugInfo/basic.swift", directory: "{{.*}}")
|
||||
// CHECK-DAG: ![[MAINFILE:[0-9]+]] = !DIFile(filename: "basic.swift", directory: "{{.*}}DebugInfo")
|
||||
// CHECK-DAG: !DICompileUnit(language: DW_LANG_Swift, file: ![[FILE_CWD]],{{.*}} producer: "{{.*}}Swift version{{.*}},{{.*}} flags: "{{[^"]*}}-emit-ir
|
||||
// CHECK-DAG: !DISubprogram(name: "main"
|
||||
// CHECK-DAG: !DISubprogram(name: "main", {{.*}}file: ![[MAINFILE]],
|
||||
|
||||
// Function type for foo.
|
||||
// CHECK-DAG: ![[FOOTYPE]] = !DISubroutineType(types: ![[PARAMTYPES:[0-9]+]])
|
||||
|
||||
@@ -16,8 +16,11 @@ let i = foo.foo(-, x: y)
|
||||
// CHECK: define {{.*}}@"$Ss5Int64VABIyByd_A2BIgyd_TR"
|
||||
// CHECK-NOT: ret
|
||||
// CHECK: call {{.*}}, !dbg ![[LOC:.*]]
|
||||
// CHECK: ![[FILE:[0-9]+]] = !DIFile(filename: "<compiler-generated>", directory: "")
|
||||
// CHECK: ![[THUNK:.*]] = distinct !DISubprogram(linkageName: "$Ss5Int64VABIyByd_A2BIgyd_TR"
|
||||
// CHECK-SAME: file: ![[FILE]]
|
||||
// CHECK-NOT: line:
|
||||
// CHECK-SAME: flags: DIFlagArtificial
|
||||
// CHECK-SAME: ){{$}}
|
||||
// CHECK: ![[LOC]] = !DILocation(line: 0, scope: ![[THUNK]])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user