Skip to content

Commit d192bfc

Browse files
authored
Merge pull request #63125 from DougGregor/debug-info-dump-macro-expansion-buffers
2 parents edbee9e + ad49d2e commit d192bfc

File tree

14 files changed

+220
-51
lines changed

14 files changed

+220
-51
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ class GeneratedSourceInfo {
7272

7373
/// The custom attribute for an attached macro.
7474
CustomAttr *attachedMacroCustomAttr = nullptr;
75+
76+
/// The name of the source file on disk that was created to hold the
77+
/// contents of this file for external clients.
78+
StringRef onDiskBufferCopyFileName = StringRef();
7579
};
7680

7781
/// This class manages and owns source buffers.
@@ -253,11 +257,18 @@ class SourceManager {
253257
///
254258
/// \p BufferID must be a valid buffer ID.
255259
///
260+
/// \p ForceGeneratedSourceToDisk can be set to true to create a temporary
261+
/// file on-disk for buffers containing generated source code, returning the
262+
/// name of that temporary file.
263+
///
256264
/// This should not be used for displaying information about the \e contents
257265
/// of a buffer, since lines within the buffer may be marked as coming from
258266
/// other files using \c #sourceLocation. Use #getDisplayNameForLoc instead
259267
/// in that case.
260-
StringRef getIdentifierForBuffer(unsigned BufferID) const;
268+
StringRef getIdentifierForBuffer(
269+
unsigned BufferID,
270+
bool ForceGeneratedSourceToDisk = false
271+
) const;
261272

262273
/// Returns a SourceRange covering the entire specified buffer.
263274
///
@@ -289,10 +300,15 @@ class SourceManager {
289300
/// Returns a buffer identifier suitable for display to the user containing
290301
/// the given source location.
291302
///
303+
/// \p ForceGeneratedSourceToDisk can be set to true to create a temporary
304+
/// file on-disk for buffers containing generated source code, returning the
305+
/// name of that temporary file.
306+
///
292307
/// This respects \c #sourceLocation directives and the 'use-external-names'
293308
/// directive in VFS overlay files. If you need an on-disk file name, use
294309
/// #getIdentifierForBuffer instead.
295-
StringRef getDisplayNameForLoc(SourceLoc Loc) const;
310+
StringRef getDisplayNameForLoc(
311+
SourceLoc Loc, bool ForceGeneratedSourceToDisk = false) const;
296312

297313
/// Returns the line and column represented by the given source location.
298314
///

include/swift/SIL/SILLocation.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,12 @@ class SILLocation {
410410
}
411411

412412
/// Extract the line, column, and filename from \p Loc.
413-
static FilenameAndLocation decode(SourceLoc Loc, const SourceManager &SM);
413+
///
414+
/// \p ForceGeneratedSourceToDisk can be set to true to create a temporary
415+
/// file on-disk for buffers containing generated source code, returning the
416+
/// name of that temporary file.
417+
static FilenameAndLocation decode(SourceLoc Loc, const SourceManager &SM,
418+
bool ForceGeneratedSourceToDisk = false);
414419

415420
/// Return the decoded FilenameAndLocation.
416421
/// In case the location has a separate AST node for debugging, this node is

lib/AST/Attr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,15 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
13111311
break;
13121312
}
13131313

1314+
case DAK_Declaration: {
1315+
Printer.printAttrName("@declaration");
1316+
Printer << "(";
1317+
auto Attr = cast<DeclarationAttr>(this);
1318+
Printer << getMacroRoleString(Attr->getMacroRole());
1319+
Printer << ")";
1320+
break;
1321+
}
1322+
13141323
case DAK_Attached: {
13151324
Printer.printAttrName("@attached");
13161325
Printer << "(";

lib/Basic/SourceLoc.cpp

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
#include "swift/Basic/SourceLoc.h"
1414
#include "swift/Basic/SourceManager.h"
15+
#include "llvm/Support/FileSystem.h"
1516
#include "llvm/Support/MemoryBuffer.h"
1617
#include "llvm/Support/PrettyStackTrace.h"
1718
#include "llvm/Support/raw_ostream.h"
19+
#include "llvm/Support/Signals.h"
1820

1921
using namespace swift;
2022

@@ -43,13 +45,14 @@ SourceLoc SourceManager::getIDEInspectionTargetLoc() const {
4345
.getAdvancedLoc(IDEInspectionTargetOffset);
4446
}
4547

46-
StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc) const {
48+
StringRef SourceManager::getDisplayNameForLoc(SourceLoc Loc, bool ForceGeneratedSourceToDisk) const {
4749
// Respect #line first
4850
if (auto VFile = getVirtualFile(Loc))
4951
return VFile->Name;
5052

5153
// Next, try the stat cache
52-
auto Ident = getIdentifierForBuffer(findBufferContainingLoc(Loc));
54+
auto Ident = getIdentifierForBuffer(
55+
findBufferContainingLoc(Loc), ForceGeneratedSourceToDisk);
5356
auto found = StatusCache.find(Ident);
5457
if (found != StatusCache.end()) {
5558
return found->second.getName();
@@ -184,9 +187,56 @@ SourceManager::getIDForBufferIdentifier(StringRef BufIdentifier) const {
184187
return It->second;
185188
}
186189

187-
StringRef SourceManager::getIdentifierForBuffer(unsigned bufferID) const {
190+
/// Dump the contents of the given memory buffer to a file, returning the
191+
/// name of that file (when successful) and \c None otherwise.
192+
static Optional<std::string>
193+
dumpBufferToFile(const llvm::MemoryBuffer *buffer) {
194+
// Create file in the system temporary directory.
195+
SmallString<128> tempFileModel;
196+
llvm::sys::path::system_temp_directory(true, tempFileModel);
197+
llvm::sys::path::append(
198+
tempFileModel, "swift-generated-sources-%%%%%%.swift");
199+
200+
// Open up a unique file.
201+
int tempFD = 0;
202+
SmallString<128> tempFileName;
203+
if (llvm::sys::fs::createUniqueFile(tempFileModel, tempFD, tempFileName))
204+
return None;
205+
206+
// Dump the contents there.
207+
auto contents = buffer->getBuffer();
208+
llvm::raw_fd_ostream out(tempFD, true);
209+
out << contents;
210+
if (contents.empty() || contents.back() != '\n')
211+
out << "\n";
212+
out.flush();
213+
214+
llvm::sys::DontRemoveFileOnSignal(tempFileName);
215+
return tempFileName.str().str();
216+
}
217+
218+
StringRef SourceManager::getIdentifierForBuffer(
219+
unsigned bufferID, bool ForceGeneratedSourceToDisk
220+
) const {
188221
auto *buffer = LLVMSourceMgr.getMemoryBuffer(bufferID);
189222
assert(buffer && "invalid buffer ID");
223+
224+
// If this is generated source code, and we're supposed to force it to disk
225+
// so external clients can see it, do so now.
226+
if (ForceGeneratedSourceToDisk) {
227+
if (auto generatedInfo = getGeneratedSourceInfo(bufferID)) {
228+
if (generatedInfo->onDiskBufferCopyFileName.empty()) {
229+
if (auto newFileNameOpt = dumpBufferToFile(buffer)) {
230+
generatedInfo->onDiskBufferCopyFileName =
231+
strdup(newFileNameOpt->c_str());
232+
}
233+
}
234+
235+
if (!generatedInfo->onDiskBufferCopyFileName.empty())
236+
return generatedInfo->onDiskBufferCopyFileName;
237+
}
238+
}
239+
190240
return buffer->getBufferIdentifier();
191241
}
192242

lib/Frontend/PrintingDiagnosticConsumer.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -861,13 +861,14 @@ class AnnotatedSourceSnippet {
861861

862862
void render(raw_ostream &Out) {
863863
// Print the excerpt for each file.
864-
unsigned lineNumberIndent =
865-
std::max_element(FileExcerpts.begin(), FileExcerpts.end(),
866-
[](auto &a, auto &b) {
867-
return a.second.getPreferredLineNumberIndent() <
868-
b.second.getPreferredLineNumberIndent();
869-
})
870-
->second.getPreferredLineNumberIndent();
864+
unsigned lineNumberIndent = 0;
865+
if (!FileExcerpts.empty()) {
866+
lineNumberIndent = std::max_element(FileExcerpts.begin(), FileExcerpts.end(),
867+
[](auto &a, auto &b) {
868+
return a.second.getPreferredLineNumberIndent() <
869+
b.second.getPreferredLineNumberIndent();
870+
})->second.getPreferredLineNumberIndent();
871+
}
871872
for (auto excerpt : FileExcerpts)
872873
excerpt.second.render(lineNumberIndent, Out);
873874

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 10 additions & 6 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.
@@ -2951,8 +2952,10 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
29512952
SILLocation::FilenameAndLocation
29522953
IRGenDebugInfoImpl::decodeSourceLoc(SourceLoc SL) {
29532954
auto &Cached = FilenameAndLocationCache[SL.getOpaquePointerValue()];
2954-
if (Cached.filename.empty())
2955-
Cached = sanitizeCodeViewFilenameAndLocation(SILLocation::decode(SL, SM));
2955+
if (Cached.filename.empty()) {
2956+
Cached = sanitizeCodeViewFilenameAndLocation(
2957+
SILLocation::decode(SL, SM, /*ForceGeneratedSourceToDisk=*/true));
2958+
}
29562959
return Cached;
29572960
}
29582961

@@ -3103,16 +3106,17 @@ ArtificialLocation::ArtificialLocation(const SILDebugScope *DS,
31033106
if (DI) {
31043107
unsigned Line = 0;
31053108
auto *Scope = DI->getOrCreateScope(DS);
3106-
if (static_cast<IRGenDebugInfoImpl *>(DI)->getDebugInfoFormat() ==
3107-
IRGenDebugInfoFormat::CodeView) {
3109+
auto DII = static_cast<IRGenDebugInfoImpl *>(DI);
3110+
if (DII->getDebugInfoFormat() == IRGenDebugInfoFormat::CodeView) {
31083111
// In CodeView, line zero is not an artificial line location and so we
31093112
// try to use the location of the scope.
31103113
if (auto *LB = dyn_cast<llvm::DILexicalBlock>(Scope))
31113114
Line = LB->getLine();
31123115
else if (auto *SP = dyn_cast<llvm::DISubprogram>(Scope))
31133116
Line = SP->getLine();
31143117
}
3115-
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));
31163120
Builder.SetCurrentDebugLocation(DL);
31173121
}
31183122
}

lib/SIL/IR/SILLocation.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,11 @@ DeclContext *SILLocation::getAsDeclContext() const {
137137
}
138138

139139
SILLocation::FilenameAndLocation SILLocation::decode(SourceLoc Loc,
140-
const SourceManager &SM) {
140+
const SourceManager &SM,
141+
bool ForceGeneratedSourceToDisk) {
141142
FilenameAndLocation DL;
142143
if (Loc.isValid()) {
143-
DL.filename = SM.getDisplayNameForLoc(Loc);
144+
DL.filename = SM.getDisplayNameForLoc(Loc, ForceGeneratedSourceToDisk);
144145
std::tie(DL.line, DL.column) = SM.getPresumedLineAndColumnForLoc(Loc);
145146
}
146147
return DL;

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,

0 commit comments

Comments
 (0)