Skip to content

Commit 3901219

Browse files
committed
Add support for nested ASTScopes inside of macro expansions.
Before this patch the parents of SILDebugScopes representing macro expansions were missing the inlinedAt field, which resulted in incorrent LLVM IR being produced. This is fixed by first computing the inlined call site for a macro expansion and then computing the nested SILDebugScope for the ASTScope of the expanded nodes; adding the inlinedAt field to all of levels of parent scopes. rdar://108323748
1 parent 286b2e0 commit 3901219

File tree

5 files changed

+95
-67
lines changed

5 files changed

+95
-67
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ class ASTSourceFileScope final : public ASTScopeImpl {
413413
NullablePtr<const void> addressForPrinting() const override { return SF; }
414414

415415
ASTContext &getASTContext() const override;
416+
bool ignoreInDebugInfo() const override { return true; }
416417

417418
protected:
418419
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,6 +2171,14 @@ void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder,
21712171
assert(parentScopesAreSane(DS) && "parent scope sanity check failed");
21722172
auto DL = llvm::DILocation::get(IGM.getLLVMContext(), L.line, L.column, Scope,
21732173
InlinedAt);
2174+
#ifndef NDEBUG
2175+
{
2176+
llvm::DILocalScope *Scope = DL->getInlinedAtScope();
2177+
llvm::DISubprogram *SP = Scope->getSubprogram();
2178+
llvm::Function *F = Builder.GetInsertBlock()->getParent();
2179+
assert((!F || SP->describes(F)) && "location points to different function");
2180+
}
2181+
#endif
21742182
Builder.SetCurrentDebugLocation(DL);
21752183
}
21762184

lib/SILGen/SILGenFunction.cpp

Lines changed: 77 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F,
5757
SourceLoc SLoc = F.getLocation().getSourceLoc();
5858
if (SF && SLoc) {
5959
FnASTScope = ast_scope::ASTScopeImpl::findStartingScopeForLookup(SF, SLoc);
60-
ScopeMap.insert({FnASTScope, F.getDebugScope()});
60+
ScopeMap.insert({{FnASTScope, nullptr}, F.getDebugScope()});
6161
}
6262
}
6363

@@ -215,47 +215,49 @@ const SILDebugScope *SILGenFunction::getOrCreateScope(SourceLoc SLoc) {
215215
if (!astScope->getParent())
216216
return nullptr;
217217

218-
const SILDebugScope *Scope = getOrCreateScope(astScope);
218+
const SILDebugScope *Scope = getOrCreateScope(astScope, F.getDebugScope());
219219
assert(Scope && "failed to construct SILDebugScope from ASTScope");
220220
return Scope;
221221
}
222222

223223
namespace {
224224
struct MacroInfo {
225-
MacroInfo(SourceLoc SLoc) : Loc(SLoc) {}
226-
RegularLocation Loc;
227-
std::string Name;
225+
MacroInfo(SourceLoc SLoc, SourceLoc ExpansionSLoc)
226+
: SLoc(SLoc), ExpansionSLoc(ExpansionSLoc) {}
227+
SourceLoc SLoc;
228+
SourceLoc ExpansionSLoc;
229+
RegularLocation ExpansionLoc = RegularLocation((Decl*)nullptr);
230+
std::string Name = "__unknown_macro__";
228231
bool Freestanding = false;
229232
};
230233
}
231234

235+
/// Return location of the macro expansion and the macro name.
232236
static MacroInfo getMacroInfo(GeneratedSourceInfo &Info) {
233-
SourceLoc MacroSLoc = Info.generatedSourceRange.getStart();
234-
MacroInfo Result(MacroSLoc);
235-
Result.Name = "__unknown_macro__";
237+
MacroInfo Result(Info.generatedSourceRange.getStart(),
238+
Info.originalSourceRange.getStart());
236239
if (!Info.astNode)
237240
return Result;
238-
239241
// Keep this in sync with ASTMangler::appendMacroExpansionContext().
240242
Mangle::ASTMangler mangler;
241243
switch (Info.kind) {
242244
case GeneratedSourceInfo::ExpressionMacroExpansion: {
243245
auto parent = ASTNode::getFromOpaqueValue(Info.astNode);
244246
if (auto expr =
245247
cast_or_null<MacroExpansionExpr>(parent.dyn_cast<Expr *>())) {
246-
Result.Loc = RegularLocation(expr);
248+
Result.ExpansionLoc = RegularLocation(expr);
247249
Result.Name = mangler.mangleMacroExpansion(expr);
248250
} else {
249251
auto decl = cast<MacroExpansionDecl>(parent.get<Decl *>());
250-
Result.Loc = RegularLocation(decl);
252+
Result.ExpansionLoc = RegularLocation(decl);
251253
Result.Name = mangler.mangleMacroExpansion(decl);
252254
}
253255
break;
254256
}
255257
case GeneratedSourceInfo::FreestandingDeclMacroExpansion: {
256258
auto expansion = cast<MacroExpansionDecl>(
257259
ASTNode::getFromOpaqueValue(Info.astNode).get<Decl *>());
258-
Result.Loc = RegularLocation(expansion);
260+
Result.ExpansionLoc = RegularLocation(expansion);
259261
Result.Name = mangler.mangleMacroExpansion(expansion);
260262
Result.Freestanding = true;
261263
break;
@@ -268,7 +270,7 @@ static MacroInfo getMacroInfo(GeneratedSourceInfo &Info) {
268270
auto decl = ASTNode::getFromOpaqueValue(Info.astNode).get<Decl *>();
269271
auto attr = Info.attachedMacroCustomAttr;
270272
if (auto *macroDecl = decl->getResolvedMacro(attr)) {
271-
Result.Loc = RegularLocation(macroDecl);
273+
Result.ExpansionLoc = RegularLocation(macroDecl);
272274
Result.Name = macroDecl->getBaseName().userFacingName();
273275
Result.Freestanding = true;
274276
}
@@ -297,61 +299,67 @@ const SILDebugScope *SILGenFunction::getMacroScope(SourceLoc SLoc) {
297299
if (Macro.Freestanding)
298300
return nullptr;
299301

300-
SourceLoc OrigSLoc = GeneratedSourceInfo->originalSourceRange.getStart();
301-
if (!OrigSLoc)
302-
return nullptr;
303-
302+
const SILDebugScope *TopLevelScope;
304303
auto It = InlinedScopeMap.find(BufferID);
305304
if (It != InlinedScopeMap.end())
306-
return It->second;
305+
TopLevelScope = It->second;
306+
else {
307+
// Recursively create one inlined function + scope per layer of generated
308+
// sources. Chains of Macro expansions are representad as flat
309+
// function-level scopes.
310+
SILGenFunctionBuilder B(SGM);
311+
auto &ASTContext = SGM.M.getASTContext();
312+
auto ExtInfo = SILFunctionType::ExtInfo::getThin();
313+
auto FunctionType = SILFunctionType::get(
314+
nullptr, ExtInfo, SILCoroutineKind::None,
315+
ParameterConvention::Direct_Unowned, /*Params*/ {},
316+
/*yields*/
317+
{},
318+
/*Results*/ {}, None, SubstitutionMap(), SubstitutionMap(), ASTContext);
319+
StringRef MacroName = ASTContext.getIdentifier(Macro.Name).str();
320+
RegularLocation MacroLoc(Macro.SLoc);
321+
// Use the ExpansionLoc as the location so IRGenDebugInfo can extract the
322+
// human-readable macro name from the MacroExpansionDecl.
323+
SILFunction *MacroFn = B.getOrCreateFunction(
324+
Macro.ExpansionLoc, MacroName,
325+
SILLinkage::DefaultForDeclaration, FunctionType, IsNotBare,
326+
IsNotTransparent, IsNotSerialized, IsNotDynamic, IsNotDistributed,
327+
IsNotRuntimeAccessible);
328+
// At the end of the chain ExpansionLoc should be a macro expansion node.
329+
const SILDebugScope *InlinedAt = nullptr;
330+
const SILDebugScope *ExpansionScope = getOrCreateScope(Macro.ExpansionSLoc);
331+
332+
// Inject an extra scope to hold the inlined call site.
333+
if (ExpansionScope)
334+
InlinedAt = new (SGM.M)
335+
SILDebugScope(Macro.ExpansionLoc, nullptr, ExpansionScope,
336+
ExpansionScope->InlinedCallSite);
337+
338+
TopLevelScope =
339+
new (SGM.M) SILDebugScope(MacroLoc, MacroFn, nullptr, InlinedAt);
340+
341+
InlinedScopeMap.insert({BufferID, TopLevelScope});
342+
}
307343

308-
// Recursively create one inlined function + scope per layer of generated
309-
// sources. Chains of Macro expansions are representad as flat function-level
310-
// scopes.
311-
SILGenFunctionBuilder B(SGM);
312-
auto &ASTContext = SGM.M.getASTContext();
313-
auto ExtInfo = SILFunctionType::ExtInfo::getThin();
314-
auto FunctionType = SILFunctionType::get(
315-
nullptr, ExtInfo, SILCoroutineKind::None,
316-
ParameterConvention::Direct_Unowned, /*Params*/ {},
317-
/*yields*/
318-
{},
319-
/*Results*/ {}, None, SubstitutionMap(), SubstitutionMap(), ASTContext);
320-
StringRef MacroName = ASTContext.getIdentifier(Macro.Name).str();
321-
322-
SILFunction *MacroFn = B.getOrCreateFunction(
323-
Macro.Loc, MacroName, SILLinkage::DefaultForDeclaration, FunctionType,
324-
IsNotBare, IsNotTransparent, IsNotSerialized, IsNotDynamic,
325-
IsNotDistributed, IsNotRuntimeAccessible);
326-
// At the end of the chain OrigSLoc should be a macro expansion node.
327-
const SILDebugScope *InlinedAt = nullptr;
328-
const SILDebugScope *OrigScope = getOrCreateScope(OrigSLoc);
329-
RegularLocation OrigLoc(OrigSLoc);
330-
// Inject an extra scope to hold the inlined call site.
331-
if (OrigScope)
332-
InlinedAt = new (SGM.M)
333-
SILDebugScope(Macro.Freestanding ? Macro.Loc : OrigLoc, nullptr,
334-
OrigScope, OrigScope->InlinedCallSite);
335-
336-
const SILDebugScope *Scope =
337-
new (SGM.M) SILDebugScope(Macro.Loc, MacroFn, nullptr, InlinedAt);
338-
339-
InlinedScopeMap.insert({BufferID, Scope});
340-
return Scope;
344+
// Create the scope hierarchy inside the macro expansion.
345+
auto *MacroAstScope =
346+
ast_scope::ASTScopeImpl::findStartingScopeForLookup(SF, Macro.SLoc);
347+
return getOrCreateScope(MacroAstScope, TopLevelScope,
348+
TopLevelScope->InlinedCallSite);
341349
}
342350

343351
const SILDebugScope *
344-
SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope) {
345-
const SILDebugScope *FnScope = F.getDebugScope();
346-
352+
SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope,
353+
const SILDebugScope *FnScope,
354+
const SILDebugScope *InlinedAt) {
347355
if (!ASTScope)
348356
return FnScope;
349357

350358
// Top-level function scope?
351359
if (ASTScope == FnASTScope)
352360
return FnScope;
353361

354-
auto It = ScopeMap.find(ASTScope);
362+
auto It = ScopeMap.find({ASTScope, InlinedAt});
355363
if (It != ScopeMap.end())
356364
return It->second;
357365

@@ -374,20 +382,21 @@ SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope) {
374382
// Since the arguments to Constructor aren't marked as implicit,
375383
// argument b is in the scope of v, but the call to Constructor
376384
// isn't, which correctly triggers the scope hole verifier.
377-
return B.getCurrentDebugScope();
385+
auto *CurScope = B.getCurrentDebugScope();
386+
return CurScope->InlinedCallSite != InlinedAt ? FnScope : CurScope;
378387
}
379388

380389
// Collapse BraceStmtScopes whose parent is a .*BodyScope.
381390
if (auto Parent = ASTScope->getParent().getPtrOrNull())
382391
if (Parent->getSourceRangeOfThisASTNode() ==
383392
ASTScope->getSourceRangeOfThisASTNode())
384-
return getOrCreateScope(Parent);
393+
return getOrCreateScope(Parent, FnScope, InlinedAt);
385394

386395
// The calls to defer closures have cleanup source locations pointing to the
387396
// defer. Reparent them into the current debug scope.
388397
auto *AncestorScope = ASTScope->getParent().getPtrOrNull();
389398
while (AncestorScope && AncestorScope != FnASTScope &&
390-
!ScopeMap.count(AncestorScope)) {
399+
!ScopeMap.count({AncestorScope, InlinedAt})) {
391400
if (auto *FD = dyn_cast_or_null<FuncDecl>(
392401
AncestorScope->getDeclIfAny().getPtrOrNull())) {
393402
if (cast<DeclContext>(FD) != FunctionDC)
@@ -404,10 +413,16 @@ SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope) {
404413
};
405414

406415
const SILDebugScope *Parent =
407-
getOrCreateScope(ASTScope->getParent().getPtrOrNull());
408-
RegularLocation Loc(ASTScope->getSourceRangeOfThisASTNode().Start);
409-
SILScope = new (SGM.M) SILDebugScope(Loc, &F, Parent);
410-
ScopeMap.insert({ASTScope, SILScope});
416+
getOrCreateScope(ASTScope->getParent().getPtrOrNull(), FnScope, InlinedAt);
417+
SourceLoc SLoc = ASTScope->getSourceRangeOfThisASTNode().Start;
418+
RegularLocation Loc(SLoc);
419+
SILScope = new (SGM.M)
420+
SILDebugScope(Loc, FnScope->getParentFunction(), Parent, InlinedAt);
421+
ScopeMap.insert({{ASTScope, InlinedAt}, SILScope});
422+
423+
assert(SILScope->getParentFunction() == &F &&
424+
"inlinedAt points to other function");
425+
411426
return SILScope;
412427
}
413428

lib/SILGen/SILGenFunction.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
367367
using ASTScopeTy = ast_scope::ASTScopeImpl;
368368
const ASTScopeTy *FnASTScope = nullptr;
369369
/// Caches one SILDebugScope for each ASTScope.
370-
llvm::SmallDenseMap<const ASTScopeTy *, const SILDebugScope *, 16> ScopeMap;
371-
/// Caches one inline SILDebugScope for each macro BufferID.
370+
llvm::SmallDenseMap<std::pair<const ASTScopeTy *, const SILDebugScope *>,
371+
const SILDebugScope *, 16>
372+
ScopeMap;
373+
/// Caches one toplevel inline SILDebugScope for each macro BufferID.
372374
llvm::SmallDenseMap<unsigned, const SILDebugScope *, 16> InlinedScopeMap;
373375

374376
/// The cleanup depth and BB for when the operand of a
@@ -720,7 +722,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
720722
const SILDebugScope *getOrCreateScope(SourceLoc SLoc);
721723
const SILDebugScope *getMacroScope(SourceLoc SLoc);
722724
const SILDebugScope *
723-
getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope);
725+
getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope,
726+
const SILDebugScope *FnScope,
727+
const SILDebugScope *InlinedAt = nullptr);
724728

725729
public:
726730
/// Enter the debug scope for \p Loc, creating it if necessary.

test/Macros/macro_expand.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ struct Bad {}
9898
func testFileID(a: Int, b: Int) {
9999
// CHECK: MacroUser/macro_expand.swift
100100
print("Result is \(#customFileID)")
101-
// CHECK-SIL: sil_scope [[SRC_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-3]]
101+
// CHECK-SIL: sil_scope [[SRC_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-3]]:6 parent {{.*}}testFileID
102102
// CHECK-SIL: sil_scope [[EXPANSION_SCOPE:[0-9]+]] { loc "{{.*}}macro_expand.swift":[[@LINE-2]]:22 parent [[SRC_SCOPE]]
103-
// CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "{{.*}}":[[@LINE-3]]:22 parent @$s9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_ {{.*}} inlined_at [[EXPANSION_SCOPE]] }
103+
// CHECK-SIL: sil_scope [[MACRO_SCOPE:[0-9]+]] { loc "@__swiftmacro{{.*}}":1:1 parent @$s9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_ {{.*}} inlined_at [[EXPANSION_SCOPE]] }
104104
// CHECK-SIL: string_literal utf8 "MacroUser/macro_expand.swift", loc "@__swiftmacro_9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_.swift":1:1, scope [[MACRO_SCOPE]]
105105
// CHECK-IR-DAG: !DISubprogram(name: "customFileID", linkageName: "$s9MacroUser10testFileID1a1bySi_SitF06customdE0fMf_"
106106

0 commit comments

Comments
 (0)