Skip to content

Commit 2e65fab

Browse files
committed
[lldb] Restore Playground functionality
Playgrounds is setting a breakpoint in the PlaygroundStub executable, which has no debug info and is implemented in C. Before b5a1d34, LLDB would have done an expensive and fragile scan through all images to find any Swift modules and make them available. We stopped doing that because it caused performance and correctness problems in Objective-C code that interacted with Swift. However, avoiding the global scan also breaks Playground's ability to find auxiliary source code. This patch restores the original behavior when SwiftASTContextForExpressions is initialized for a Playground only. rdar://154373965 (cherry picked from commit d2b0977)
1 parent 3d664ab commit 2e65fab

File tree

12 files changed

+75
-40
lines changed

12 files changed

+75
-40
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftREPL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ Status SwiftREPL::DoInitialization() {
302302
return Status::FromError(type_system_or_err.takeError());
303303
std::static_pointer_cast<TypeSystemSwiftTypeRefForExpressions>(
304304
*type_system_or_err)
305-
->SetCompilerOptions(m_compiler_options.c_str());
305+
->SetCompilerOptions(/*repl=*/true, /*playgrounds=*/false,
306+
m_compiler_options.c_str());
306307

307308
std::string format_str = "${ansi.negative}Swift " +
308309
swift::version::getCompilerVersion() +

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,9 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
805805
"unknown error");
806806
// Notify SwiftASTContext that this is a Playground.
807807
if (m_options.GetPlaygroundTransformEnabled())
808-
m_swift_scratch_ctx->SetCompilerOptions("");
808+
m_swift_scratch_ctx->SetCompilerOptions(
809+
m_options.GetREPLEnabled(), m_options.GetPlaygroundTransformEnabled(),
810+
"");
809811

810812
// For playgrounds, the target triple should be used for expression
811813
// evaluation, not the current module. This requires disabling precise

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,16 +2685,14 @@ static lldb::ModuleSP GetUnitTestModule(lldb_private::ModuleList &modules) {
26852685
return ModuleSP();
26862686
}
26872687

2688-
lldb::TypeSystemSP
2689-
SwiftASTContext::CreateInstance(const SymbolContext &sc,
2690-
TypeSystemSwiftTypeRef &typeref_typesystem,
2691-
const char *extra_options) {
2692-
bool is_repl = extra_options;
2688+
lldb::TypeSystemSP SwiftASTContext::CreateInstance(
2689+
const SymbolContext &sc, TypeSystemSwiftTypeRef &typeref_typesystem,
2690+
bool repl, bool playground, const char *extra_options) {
26932691
bool for_expressions =
26942692
llvm::isa<TypeSystemSwiftTypeRefForExpressions>(&typeref_typesystem);
26952693
// REPL requires an expression type system.
2696-
assert(!is_repl || for_expressions);
2697-
if (is_repl && !for_expressions)
2694+
assert(!repl || for_expressions);
2695+
if (repl && !for_expressions)
26982696
return {};
26992697

27002698
if (!ModuleList::GetGlobalModuleListProperties()
@@ -2721,9 +2719,6 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27212719

27222720
LLDB_SCOPED_TIMERF("%s::CreateInstance", m_description.c_str());
27232721

2724-
if (is_repl)
2725-
LOG_PRINTF(GetLog(LLDBLog::Types), "REPL detected");
2726-
27272722
// This function can either create an expression/scratch/repl context,
27282723
// or a SwiftAST fallback context for a TypeSystemSwiftTyperef.
27292724
// - SwiftASTContexForExpressions: target=non-null, module=null.
@@ -2767,8 +2762,9 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27672762
if (ShouldEnableEmbeddedSwift(cu))
27682763
lang_opts.enableFeature(swift::Feature::Embedded);
27692764
}
2770-
auto defer_log = llvm::make_scope_exit(
2771-
[swift_ast_sp, is_repl] { swift_ast_sp->LogConfiguration(is_repl); });
2765+
auto defer_log = llvm::make_scope_exit([swift_ast_sp, repl, playground] {
2766+
swift_ast_sp->LogConfiguration(repl, playground);
2767+
});
27722768

27732769
LOG_PRINTF(GetLog(LLDBLog::Types), "(Target)");
27742770
auto logError = [&](const char *message) {
@@ -2794,8 +2790,12 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27942790
ModuleList module_module;
27952791
if (!target_sp)
27962792
module_module.Append(module_sp);
2797-
ModuleList &modules =
2798-
(target_sp && swift_context) ? target_sp->GetImages() : module_module;
2793+
// Leave modules empty if not in a Swift context to avoid a fragile
2794+
// and expensive scan through all images. Unless this is a Playground, which
2795+
// has a non-Swift executable, and user code in a framework.
2796+
ModuleList &modules = (target_sp && (swift_context || playground))
2797+
? target_sp->GetImages()
2798+
: module_module;
27992799
const size_t num_images = modules.GetSize();
28002800

28012801
// Set the SDK path prior to doing search paths. Otherwise when we
@@ -2867,7 +2867,7 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
28672867

28682868
ArchSpec preferred_arch;
28692869
llvm::Triple preferred_triple;
2870-
if (is_repl) {
2870+
if (repl) {
28712871
LOG_PRINTF(GetLog(LLDBLog::Types), "REPL: prefer target triple.");
28722872
preferred_arch = target_arch;
28732873
preferred_triple = target_triple;
@@ -3131,7 +3131,7 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
31313131
}
31323132
}
31333133
};
3134-
if (swift_context)
3134+
if (swift_context || playground)
31353135
scan_module(module_sp, 0);
31363136
for (size_t mi = 0; mi != num_images; ++mi) {
31373137
auto image_sp = modules.GetModuleAtIndex(mi);
@@ -5455,7 +5455,7 @@ void SwiftASTContext::ClearModuleDependentCaches() {
54555455
m_negative_type_cache.Clear();
54565456
}
54575457

5458-
void SwiftASTContext::LogConfiguration(bool is_repl) {
5458+
void SwiftASTContext::LogConfiguration(bool repl, bool playground) {
54595459
// It makes no sense to call VALID_OR_RETURN here. We specifically
54605460
// want the logs in the error case!
54615461
HEALTH_LOG_PRINTF("(SwiftASTContext*)%p:", static_cast<void *>(this));
@@ -5464,8 +5464,10 @@ void SwiftASTContext::LogConfiguration(bool is_repl) {
54645464
HEALTH_LOG_PRINTF(" (no AST context)");
54655465
return;
54665466
}
5467-
if (is_repl)
5467+
if (repl)
54685468
HEALTH_LOG_PRINTF(" REPL : true");
5469+
if (playground)
5470+
HEALTH_LOG_PRINTF(" Playground : true");
54695471
HEALTH_LOG_PRINTF(" Swift/C++ interop : %s",
54705472
m_ast_context_ap->LangOpts.EnableCXXInterop ? "on" : "off");
54715473
HEALTH_LOG_PRINTF(" Swift/Objective-C interop : %s",

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ class SwiftASTContext : public TypeSystemSwift {
207207
/// context.
208208
static lldb::TypeSystemSP
209209
CreateInstance(const SymbolContext &sc,
210-
TypeSystemSwiftTypeRef &typeref_typesystem,
211-
const char *extra_options = nullptr);
210+
TypeSystemSwiftTypeRef &typeref_typesystem, bool repl = false,
211+
bool playground = false, const char *extra_options = nullptr);
212212

213213
static void EnumerateSupportedLanguages(
214214
std::set<lldb::LanguageType> &languages_for_types,
@@ -539,7 +539,7 @@ class SwiftASTContext : public TypeSystemSwift {
539539
swift::TBDGenOptions &GetTBDGenOptions();
540540

541541
void ClearModuleDependentCaches() override;
542-
void LogConfiguration(bool is_repl = false);
542+
void LogConfiguration(bool repl = false, bool playground = false);
543543
bool HasTarget();
544544
bool HasExplicitModules() const { return m_has_explicit_modules; }
545545
bool CheckProcessChanged();

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwift.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ static lldb::TypeSystemSP CreateTypeSystemInstance(lldb::LanguageType language,
4545
} else if (target) {
4646
assert(!module);
4747
return std::shared_ptr<TypeSystemSwiftTypeRefForExpressions>(
48-
new TypeSystemSwiftTypeRefForExpressions(language, *target,
49-
extra_options));
48+
new TypeSystemSwiftTypeRefForExpressions(language, *target, false,
49+
false, extra_options));
5050
}
5151
llvm_unreachable("Neither type nor module given to CreateTypeSystemInstance");
5252
}

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,24 +1994,26 @@ TypeSystemSwiftTypeRef::TypeSystemSwiftTypeRef(Module &module) {
19941994
}
19951995

19961996
TypeSystemSwiftTypeRefForExpressions::TypeSystemSwiftTypeRefForExpressions(
1997-
lldb::LanguageType language, Target &target, const char *extra_options)
1997+
lldb::LanguageType language, Target &target, bool repl, bool playground,
1998+
const char *extra_options)
19981999
: m_target_wp(target.shared_from_this()),
19992000
m_persistent_state_up(new SwiftPersistentExpressionState) {
20002001
m_description = "TypeSystemSwiftTypeRefForExpressions";
20012002
LLDB_LOGF(GetLog(LLDBLog::Types),
20022003
"%s::TypeSystemSwiftTypeRefForExpressions()",
20032004
m_description.c_str());
20042005
// Is this a REPL or Playground?
2005-
if (extra_options) {
2006+
assert(!repl && !playground && !extra_options && "use SetCompilerOptions()");
2007+
if (repl || playground || extra_options) {
20062008
SymbolContext global_sc(target.shared_from_this(),
20072009
target.GetExecutableModule());
20082010
const char *key = DeriveKeyFor(global_sc);
20092011
m_swift_ast_context_map.insert(
20102012
{key,
20112013
{SwiftASTContext::CreateInstance(
20122014
global_sc,
2013-
*const_cast<TypeSystemSwiftTypeRefForExpressions *>(this),
2014-
extra_options),
2015+
*const_cast<TypeSystemSwiftTypeRefForExpressions *>(this), repl,
2016+
playground, extra_options),
20152017
0}});
20162018
}
20172019
}
@@ -2214,8 +2216,8 @@ SwiftASTContextSP TypeSystemSwiftTypeRefForExpressions::GetSwiftASTContext(
22142216

22152217
// Create a new SwiftASTContextForExpressions.
22162218
ts = SwiftASTContext::CreateInstance(
2217-
sc, *const_cast<TypeSystemSwiftTypeRefForExpressions *>(this),
2218-
m_compiler_options);
2219+
sc, *const_cast<TypeSystemSwiftTypeRefForExpressions *>(this), m_repl,
2220+
m_playground, m_compiler_options);
22192221
m_swift_ast_context_map.insert({key, {ts, retry_count}});
22202222
}
22212223

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
630630
/// \}
631631

632632
TypeSystemSwiftTypeRefForExpressions(lldb::LanguageType language,
633-
Target &target,
633+
Target &target, bool repl,
634+
bool playground,
634635
const char *extra_options);
635636

636637
static TypeSystemSwiftTypeRefForExpressionsSP GetForTarget(Target &target);
@@ -642,7 +643,10 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
642643
GetSwiftASTContextOrNull(const SymbolContext &sc) const override;
643644
/// This API needs to be called for a REPL or Playground before the first call
644645
/// to GetSwiftASTContext is being made.
645-
void SetCompilerOptions(const char *compiler_options) {
646+
void SetCompilerOptions(bool repl, bool playground,
647+
const char *compiler_options) {
648+
m_repl = repl;
649+
m_playground = playground;
646650
m_compiler_options = compiler_options;
647651
}
648652
lldb::TargetWP GetTargetWP() const override { return m_target_wp; }
@@ -673,6 +677,8 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
673677
protected:
674678
lldb::TargetWP m_target_wp;
675679
unsigned m_generation = 0;
680+
bool m_repl = false;
681+
bool m_playground = false;
676682
const char *m_compiler_options = nullptr;
677683

678684
/// This exists to implement the PerformCompileUnitImports
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// This file intentionally left blank.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import AuxSources
12
import Dylib
23
f()
34
let comment = "and back again"

lldb/test/API/lang/swift/playgrounds/Makefile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
EXE = PlaygroundStub
22
SWIFT_SOURCES = PlaygroundStub.swift
3+
# The real playground stub has no debug info and is written in C.
4+
SWIFTFLAGS_EXTRAS = -gnone
35

46
# The deployment target we set is pre-ABI stability. The Swift driver will not
57
# point the RPATH at the system library. Do it manually.
68
LD_EXTRAS := -Xlinker -rpath -Xlinker /usr/lib/swift
7-
LD_EXTRAS += -L. -lPlaygroundsRuntime
9+
LD_EXTRAS += -L. -lPlaygroundsRuntime -F. -framework AuxSources
810

9-
PlaygroundStub: libPlaygroundsRuntime.dylib Dylib.framework
11+
PlaygroundStub: libPlaygroundsRuntime.dylib Dylib.framework AuxSources.framework
1012

1113
include Makefile.rules
1214

@@ -21,3 +23,10 @@ Dylib.framework: Dylib.swift
2123
DYLIB_SWIFT_SOURCES=Dylib.swift \
2224
DYLIB_NAME=Dylib \
2325
SWIFTFLAGS_EXTRAS="-Xcc -DNEW_OPTION_FROM_DYLIB=1"
26+
27+
AuxSources.framework: AuxSources.swift
28+
"$(MAKE)" -f $(MAKEFILE_RULES) \
29+
FRAMEWORK=AuxSources \
30+
DYLIB_SWIFT_SOURCES=AuxSources.swift \
31+
DYLIB_NAME=AuxSources \
32+
SWIFTFLAGS_EXTRAS="-Xcc -DHAVE_AUXSOURCES=1"

0 commit comments

Comments
 (0)