Skip to content

Commit d2b0977

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
1 parent 0551ad0 commit d2b0977

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
@@ -2689,16 +2689,14 @@ static lldb::ModuleSP GetUnitTestModule(lldb_private::ModuleList &modules) {
26892689
return ModuleSP();
26902690
}
26912691

2692-
lldb::TypeSystemSP
2693-
SwiftASTContext::CreateInstance(const SymbolContext &sc,
2694-
TypeSystemSwiftTypeRef &typeref_typesystem,
2695-
const char *extra_options) {
2696-
bool is_repl = extra_options;
2692+
lldb::TypeSystemSP SwiftASTContext::CreateInstance(
2693+
const SymbolContext &sc, TypeSystemSwiftTypeRef &typeref_typesystem,
2694+
bool repl, bool playground, const char *extra_options) {
26972695
bool for_expressions =
26982696
llvm::isa<TypeSystemSwiftTypeRefForExpressions>(&typeref_typesystem);
26992697
// REPL requires an expression type system.
2700-
assert(!is_repl || for_expressions);
2701-
if (is_repl && !for_expressions)
2698+
assert(!repl || for_expressions);
2699+
if (repl && !for_expressions)
27022700
return {};
27032701

27042702
if (!ModuleList::GetGlobalModuleListProperties()
@@ -2725,9 +2723,6 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27252723

27262724
LLDB_SCOPED_TIMERF("%s::CreateInstance", m_description.c_str());
27272725

2728-
if (is_repl)
2729-
LOG_PRINTF(GetLog(LLDBLog::Types), "REPL detected");
2730-
27312726
// This function can either create an expression/scratch/repl context,
27322727
// or a SwiftAST fallback context for a TypeSystemSwiftTyperef.
27332728
// - SwiftASTContexForExpressions: target=non-null, module=null.
@@ -2771,8 +2766,9 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27712766
if (ShouldEnableEmbeddedSwift(cu))
27722767
lang_opts.enableFeature(swift::Feature::Embedded);
27732768
}
2774-
auto defer_log = llvm::make_scope_exit(
2775-
[swift_ast_sp, is_repl] { swift_ast_sp->LogConfiguration(is_repl); });
2769+
auto defer_log = llvm::make_scope_exit([swift_ast_sp, repl, playground] {
2770+
swift_ast_sp->LogConfiguration(repl, playground);
2771+
});
27762772

27772773
LOG_PRINTF(GetLog(LLDBLog::Types), "(Target)");
27782774
auto logError = [&](const char *message) {
@@ -2798,8 +2794,12 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
27982794
ModuleList module_module;
27992795
if (!target_sp)
28002796
module_module.Append(module_sp);
2801-
ModuleList &modules =
2802-
(target_sp && swift_context) ? target_sp->GetImages() : module_module;
2797+
// Leave modules empty if not in a Swift context to avoid a fragile
2798+
// and expensive scan through all images. Unless this is a Playground, which
2799+
// has a non-Swift executable, and user code in a framework.
2800+
ModuleList &modules = (target_sp && (swift_context || playground))
2801+
? target_sp->GetImages()
2802+
: module_module;
28032803
const size_t num_images = modules.GetSize();
28042804

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

28722872
ArchSpec preferred_arch;
28732873
llvm::Triple preferred_triple;
2874-
if (is_repl) {
2874+
if (repl) {
28752875
LOG_PRINTF(GetLog(LLDBLog::Types), "REPL: prefer target triple.");
28762876
preferred_arch = target_arch;
28772877
preferred_triple = target_triple;
@@ -3135,7 +3135,7 @@ SwiftASTContext::CreateInstance(const SymbolContext &sc,
31353135
}
31363136
}
31373137
};
3138-
if (swift_context)
3138+
if (swift_context || playground)
31393139
scan_module(module_sp, 0);
31403140
for (size_t mi = 0; mi != num_images; ++mi) {
31413141
auto image_sp = modules.GetModuleAtIndex(mi);
@@ -5464,7 +5464,7 @@ void SwiftASTContext::ClearModuleDependentCaches() {
54645464
m_negative_type_cache.Clear();
54655465
}
54665466

5467-
void SwiftASTContext::LogConfiguration(bool is_repl) {
5467+
void SwiftASTContext::LogConfiguration(bool repl, bool playground) {
54685468
// It makes no sense to call VALID_OR_RETURN here. We specifically
54695469
// want the logs in the error case!
54705470
HEALTH_LOG_PRINTF("(SwiftASTContext*)%p:", static_cast<void *>(this));
@@ -5474,8 +5474,10 @@ void SwiftASTContext::LogConfiguration(bool is_repl) {
54745474
HEALTH_LOG_PRINTF(" (no AST context)");
54755475
return;
54765476
}
5477-
if (is_repl)
5477+
if (repl)
54785478
HEALTH_LOG_PRINTF(" REPL : true");
5479+
if (playground)
5480+
HEALTH_LOG_PRINTF(" Playground : true");
54795481
HEALTH_LOG_PRINTF(" Swift/C++ interop : %s",
54805482
ast_context->LangOpts.EnableCXXInterop ? "on" : "off");
54815483
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
@@ -1963,24 +1963,26 @@ TypeSystemSwiftTypeRef::TypeSystemSwiftTypeRef(Module &module) {
19631963
}
19641964

19651965
TypeSystemSwiftTypeRefForExpressions::TypeSystemSwiftTypeRefForExpressions(
1966-
lldb::LanguageType language, Target &target, const char *extra_options)
1966+
lldb::LanguageType language, Target &target, bool repl, bool playground,
1967+
const char *extra_options)
19671968
: m_target_wp(target.shared_from_this()),
19681969
m_persistent_state_up(new SwiftPersistentExpressionState) {
19691970
m_description = "TypeSystemSwiftTypeRefForExpressions";
19701971
LLDB_LOGF(GetLog(LLDBLog::Types),
19711972
"%s::TypeSystemSwiftTypeRefForExpressions()",
19721973
m_description.c_str());
19731974
// Is this a REPL or Playground?
1974-
if (extra_options) {
1975+
assert(!repl && !playground && !extra_options && "use SetCompilerOptions()");
1976+
if (repl || playground || extra_options) {
19751977
SymbolContext global_sc(target.shared_from_this(),
19761978
target.GetExecutableModule());
19771979
const char *key = DeriveKeyFor(global_sc);
19781980
m_swift_ast_context_map.insert(
19791981
{key,
19801982
{SwiftASTContext::CreateInstance(
19811983
global_sc,
1982-
*const_cast<TypeSystemSwiftTypeRefForExpressions *>(this),
1983-
extra_options),
1984+
*const_cast<TypeSystemSwiftTypeRefForExpressions *>(this), repl,
1985+
playground, extra_options),
19841986
0}});
19851987
}
19861988
}
@@ -2183,8 +2185,8 @@ SwiftASTContextSP TypeSystemSwiftTypeRefForExpressions::GetSwiftASTContext(
21832185

21842186
// Create a new SwiftASTContextForExpressions.
21852187
ts = SwiftASTContext::CreateInstance(
2186-
sc, *const_cast<TypeSystemSwiftTypeRefForExpressions *>(this),
2187-
m_compiler_options);
2188+
sc, *const_cast<TypeSystemSwiftTypeRefForExpressions *>(this), m_repl,
2189+
m_playground, m_compiler_options);
21882190
m_swift_ast_context_map.insert({key, {ts, retry_count}});
21892191
}
21902192

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

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

628628
TypeSystemSwiftTypeRefForExpressions(lldb::LanguageType language,
629-
Target &target,
629+
Target &target, bool repl,
630+
bool playground,
630631
const char *extra_options);
631632

632633
static TypeSystemSwiftTypeRefForExpressionsSP GetForTarget(Target &target);
@@ -638,7 +639,10 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
638639
GetSwiftASTContextOrNull(const SymbolContext &sc) const override;
639640
/// This API needs to be called for a REPL or Playground before the first call
640641
/// to GetSwiftASTContext is being made.
641-
void SetCompilerOptions(const char *compiler_options) {
642+
void SetCompilerOptions(bool repl, bool playground,
643+
const char *compiler_options) {
644+
m_repl = repl;
645+
m_playground = playground;
642646
m_compiler_options = compiler_options;
643647
}
644648
lldb::TargetWP GetTargetWP() const override { return m_target_wp; }
@@ -668,6 +672,8 @@ class TypeSystemSwiftTypeRefForExpressions : public TypeSystemSwiftTypeRef {
668672
protected:
669673
lldb::TargetWP m_target_wp;
670674
unsigned m_generation = 0;
675+
bool m_repl = false;
676+
bool m_playground = false;
671677
const char *m_compiler_options = nullptr;
672678

673679
/// 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)