Skip to content

Commit 338dd01

Browse files
committed
Debug Info: Represent macro expansions as inlined functions.
This allows the debugger to choose whether to display the expanded macro (inlined) or the original source code (parent frame). rdar://102916513
1 parent b7f75c1 commit 338dd01

File tree

7 files changed

+94
-29
lines changed

7 files changed

+94
-29
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ static bool equalWithoutExistentialTypes(Type t1, Type t2) {
111111
}
112112

113113
class IRGenDebugInfoImpl : public IRGenDebugInfo {
114-
friend class IRGenDebugInfoImpl;
115114
const IRGenOptions &Opts;
116115
ClangImporter &CI;
117116
SourceManager &SM;
@@ -395,6 +394,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
395394
return false;
396395
}
397396

397+
public:
398398
llvm::MDNode *createInlinedAt(const SILDebugScope *DS) {
399399
auto *CS = DS->InlinedCallSite;
400400
if (!CS)
@@ -414,6 +414,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
414414
InlinedAtCache.insert({CS, llvm::TrackingMDNodeRef(InlinedAt)});
415415
return InlinedAt;
416416
}
417+
private:
417418

418419
#ifndef NDEBUG
419420
/// Perform a couple of sanity checks on scopes.
@@ -3105,16 +3106,17 @@ ArtificialLocation::ArtificialLocation(const SILDebugScope *DS,
31053106
if (DI) {
31063107
unsigned Line = 0;
31073108
auto *Scope = DI->getOrCreateScope(DS);
3108-
if (static_cast<IRGenDebugInfoImpl *>(DI)->getDebugInfoFormat() ==
3109-
IRGenDebugInfoFormat::CodeView) {
3109+
auto DII = static_cast<IRGenDebugInfoImpl *>(DI);
3110+
if (DII->getDebugInfoFormat() == IRGenDebugInfoFormat::CodeView) {
31103111
// In CodeView, line zero is not an artificial line location and so we
31113112
// try to use the location of the scope.
31123113
if (auto *LB = dyn_cast<llvm::DILexicalBlock>(Scope))
31133114
Line = LB->getLine();
31143115
else if (auto *SP = dyn_cast<llvm::DISubprogram>(Scope))
31153116
Line = SP->getLine();
31163117
}
3117-
auto DL = llvm::DILocation::get(Scope->getContext(), Line, 0, Scope);
3118+
auto DL = llvm::DILocation::get(Scope->getContext(), Line, 0, Scope,
3119+
DII->createInlinedAt(DS));
31183120
Builder.SetCurrentDebugLocation(DL);
31193121
}
31203122
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5889,6 +5889,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
58895889
// map and go on.
58905890
auto *DS = SI.getDebugScope();
58915891
assert(DS && "Each instruction should have a debug scope");
5892+
5893+
// We don't support this verification on inlined call sites yet.
5894+
if (DS->InlinedCallSite)
5895+
continue;
5896+
58925897
if (!AlreadySeenScopes.count(DS)) {
58935898
AlreadySeenScopes.insert(DS);
58945899
LastSeenScope = DS;

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5995,6 +5995,8 @@ RValue RValueEmitter::visitMacroExpansionExpr(MacroExpansionExpr *E,
59955995
SGFContext C) {
59965996
auto *rewritten = E->getRewritten();
59975997
assert(rewritten && "Macro should have been rewritten by SILGen");
5998+
MacroScope scope(SGF, CleanupLocation(rewritten), E, E->getMacroName(),
5999+
E->getMacroNameLoc());
59986000
return visit(rewritten, C);
59996001
}
60006002

lib/SILGen/SILGenFunction.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "SILGenFunction.h"
19+
#include "Cleanup.h"
1920
#include "RValue.h"
2021
#include "SILGenFunctionBuilder.h"
2122
#include "Scope.h"
@@ -157,6 +158,57 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
157158
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
158159
}
159160

161+
void SILGenFunction::enterDebugScope(SILLocation Loc, bool isBindingScope,
162+
Optional<SILLocation> MacroExpansion,
163+
DeclNameRef MacroName,
164+
DeclNameLoc MacroNameLoc) {
165+
auto *Parent = DebugScopeStack.size() ? DebugScopeStack.back().getPointer()
166+
: F.getDebugScope();
167+
auto *Scope = Parent;
168+
// Don't nest a scope for Loc under Parent unless it's actually different.
169+
if (RegularLocation(Parent->getLoc()) != RegularLocation(Loc)) {
170+
SILDebugScope *InlinedAt = nullptr;
171+
// Create an inline scope for a macro expansion.
172+
if (MacroExpansion && MacroName && MacroNameLoc.isValid()) {
173+
InlinedAt = new (SGM.M) SILDebugScope(RegularLocation(*MacroExpansion),
174+
&getFunction(), Parent);
175+
SILGenFunctionBuilder B(SGM);
176+
auto ExtInfo = SILFunctionType::ExtInfo::getThin();
177+
auto FunctionType = SILFunctionType::get(
178+
nullptr, ExtInfo, SILCoroutineKind::None,
179+
ParameterConvention::Direct_Unowned, /*Params*/ {}, /*yields*/ {},
180+
/*Results*/ {}, None, SubstitutionMap(), SubstitutionMap(),
181+
SGM.M.getASTContext());
182+
SILFunction *MacroFn = B.getOrCreateFunction(
183+
Loc, MacroName.getBaseIdentifier().str(),
184+
SILLinkage::DefaultForDeclaration, FunctionType, IsNotBare,
185+
IsNotTransparent, IsNotSerialized, IsNotDynamic, IsNotDistributed,
186+
IsNotRuntimeAccessible);
187+
auto MacroScope = new (SGM.M) SILDebugScope(Loc, MacroFn);
188+
Parent = MacroScope;
189+
}
190+
Scope = new (SGM.M)
191+
SILDebugScope(RegularLocation(Loc), &getFunction(), Parent, InlinedAt);
192+
}
193+
DebugScopeStack.emplace_back(Scope, isBindingScope);
194+
B.setCurrentDebugScope(Scope);
195+
}
196+
197+
/// Return to the previous debug scope.
198+
void SILGenFunction::leaveDebugScope() {
199+
// Pop any 'guard' scopes first.
200+
while (DebugScopeStack.back().getInt())
201+
DebugScopeStack.pop_back();
202+
203+
// Pop the scope we're leaving now.
204+
DebugScopeStack.pop_back();
205+
if (DebugScopeStack.size())
206+
B.setCurrentDebugScope(DebugScopeStack.back().getPointer());
207+
// Don't reset the debug scope after leaving the outermost scope,
208+
// because the debugger is not expecting the function epilogue to
209+
// be in a different scope.
210+
}
211+
160212
std::tuple<ManagedValue, SILType>
161213
SILGenFunction::emitSiblingMethodRef(SILLocation loc,
162214
SILValue selfValue,

lib/SILGen/SILGenFunction.h

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -598,31 +598,13 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
598598
/// \param isBindingScope If true, this is a scope for the bindings introduced
599599
/// by a let expression. This scope ends when the next innermost BraceStmt
600600
/// ends.
601-
void enterDebugScope(SILLocation Loc, bool isBindingScope = false) {
602-
auto *Parent = DebugScopeStack.size() ? DebugScopeStack.back().getPointer()
603-
: F.getDebugScope();
604-
auto *DS = Parent;
605-
// Don't nest a scope for Loc under Parent unless it's actually different.
606-
if (RegularLocation(DS->getLoc()) != RegularLocation(Loc))
607-
DS = new (SGM.M) SILDebugScope(RegularLocation(Loc), &getFunction(), DS);
608-
DebugScopeStack.emplace_back(DS, isBindingScope);
609-
B.setCurrentDebugScope(DS);
610-
}
601+
void enterDebugScope(SILLocation Loc, bool isBindingScope = false,
602+
Optional<SILLocation> MacroExpansion = {},
603+
DeclNameRef MacroName = {},
604+
DeclNameLoc MacroNameLoc = {});
611605

612606
/// Return to the previous debug scope.
613-
void leaveDebugScope() {
614-
// Pop any 'guard' scopes first.
615-
while (DebugScopeStack.back().getInt())
616-
DebugScopeStack.pop_back();
617-
618-
// Pop the scope we're leaving now.
619-
DebugScopeStack.pop_back();
620-
if (DebugScopeStack.size())
621-
B.setCurrentDebugScope(DebugScopeStack.back().getPointer());
622-
// Don't reset the debug scope after leaving the outermost scope,
623-
// because the debugger is not expecting the function epilogue to
624-
// be in a different scope.
625-
}
607+
void leaveDebugScope();
626608

627609
std::unique_ptr<Initialization>
628610
prepareIndirectResultInit(AbstractionPattern origResultType,

lib/SILGen/Scope.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,22 @@ class LLVM_LIBRARY_VISIBILITY DebugScope {
161161
~DebugScope() { SGF.leaveDebugScope(); }
162162
};
163163

164+
/// A scope that represents a Macro expansion.
165+
class LLVM_LIBRARY_VISIBILITY MacroScope {
166+
SILGenFunction &SGF;
167+
168+
public:
169+
explicit MacroScope(SILGenFunction &SGF, CleanupLocation loc,
170+
SILLocation MacroExpansion, DeclNameRef MacroName,
171+
DeclNameLoc MacroNameLoc)
172+
: SGF(SGF) {
173+
SGF.enterDebugScope(loc, false, MacroExpansion, MacroName, MacroNameLoc);
174+
}
175+
176+
~MacroScope() { SGF.leaveDebugScope(); }
177+
};
178+
179+
164180
} // end namespace Lowering
165181
} // end namespace swift
166182

test/Macros/macro_expand.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
// RUN: not %target-swift-frontend -typecheck -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s
99
// RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS %s
1010

11-
// Debug IR testing
12-
// RUN: %target-swift-frontend -emit-ir -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR %s
11+
// Debug info SIL testing
12+
// RUN: %target-swift-frontend -emit-sil -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
1313

14+
// Debug info IR testing
15+
// RUN: %target-swift-frontend -emit-ir -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR %s
1416

1517
// Execution testing
1618
// RUN: %target-build-swift -g -enable-experimental-feature Macros -enable-experimental-feature Macros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
@@ -28,7 +30,11 @@
2830
func testFileID(a: Int, b: Int) {
2931
// CHECK: MacroUser/macro_expand.swift
3032
print("Result is \(#customFileID)")
33+
// CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "{{.*}}":1:1 parent @customFileID {{.*}} }
34+
// CHECK-SIL: sil_scope [[SRC_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-2]]
35+
// CHECK-SIL: sil_scope {{[0-9]+}} { loc "{{.*}}":1:1 parent [[MACRO_SCOPE]] inlined_at [[SRC_SCOPE]] }
3136
37+
3238
// CHECK: Builtin result is MacroUser/macro_expand.swift
3339
// CHECK-AST: macro_expansion_expr type='String'{{.*}}name=line
3440
print("Builtin result is \(#fileID)")

0 commit comments

Comments
 (0)