Skip to content

Commit 8ec7e75

Browse files
committed
[lldb/swift] Add swift type-system progress reporting
This patch reports progress events specific to the swift type-system. Currently, it covers 3 long-running operations: - Setting up the runtime reflection context - Loading implicit modules from the compile unit - Caching them in the expression persistent state It also includes a test a will listen for swift progress events and make sure it we receive them when fetching a swift variable. rdar://75803015 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent eb4c7ec commit 8ec7e75

File tree

5 files changed

+167
-26
lines changed

5 files changed

+167
-26
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "lldb/Core/Debugger.h"
2222
#include "lldb/Core/JITSection.h"
2323
#include "lldb/Core/PluginManager.h"
24+
#include "lldb/Core/Progress.h"
2425
#include "lldb/Core/Section.h"
2526
#include "lldb/Core/ValueObjectConstResult.h"
2627
#include "lldb/DataFormatters/StringPrinter.h"
@@ -461,36 +462,52 @@ void SwiftLanguageRuntimeImpl::SetupReflection() {
461462
return;
462463

463464
auto &target = m_process.GetTarget();
464-
if (auto exe_module = target.GetExecutableModule()) {
465-
bool objc_interop = (bool)findRuntime(m_process, RuntimeKind::ObjC);
466-
const char *objc_interop_msg =
467-
objc_interop ? "with Objective-C interopability" : "Swift only";
468-
469-
auto &triple = exe_module->GetArchitecture().GetTriple();
470-
if (triple.isArch64Bit()) {
471-
LLDB_LOGF(GetLog(LLDBLog::Types),
472-
"Initializing a 64-bit reflection context (%s) for \"%s\"",
473-
triple.str().c_str(), objc_interop_msg);
474-
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64(
475-
this->GetMemoryReader(), objc_interop);
476-
} else if (triple.isArch32Bit()) {
477-
LLDB_LOGF(GetLog(LLDBLog::Types),
478-
"Initializing a 32-bit reflection context (%s) for \"%s\"",
479-
triple.str().c_str(), objc_interop_msg);
480-
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32(
481-
this->GetMemoryReader(), objc_interop);
482-
} else {
483-
LLDB_LOGF(GetLog(LLDBLog::Types),
484-
"Could not initialize reflection context for \"%s\"",
485-
triple.str().c_str());
486-
}
465+
auto exe_module = target.GetExecutableModule();
466+
467+
if (!exe_module) {
468+
LLDB_LOGF(GetLog(LLDBLog::Types), "%s: Failed to get executable module",
469+
LLVM_PRETTY_FUNCTION);
470+
m_initialized_reflection_ctx = false;
471+
return;
487472
}
473+
474+
bool objc_interop = (bool)findRuntime(m_process, RuntimeKind::ObjC);
475+
const char *objc_interop_msg =
476+
objc_interop ? "with Objective-C interopability" : "Swift only";
477+
478+
auto &triple = exe_module->GetArchitecture().GetTriple();
479+
if (triple.isArch64Bit()) {
480+
LLDB_LOGF(GetLog(LLDBLog::Types),
481+
"Initializing a 64-bit reflection context (%s) for \"%s\"",
482+
triple.str().c_str(), objc_interop_msg);
483+
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64(
484+
this->GetMemoryReader(), objc_interop);
485+
} else if (triple.isArch32Bit()) {
486+
LLDB_LOGF(GetLog(LLDBLog::Types),
487+
"Initializing a 32-bit reflection context (%s) for \"%s\"",
488+
triple.str().c_str(), objc_interop_msg);
489+
m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32(
490+
this->GetMemoryReader(), objc_interop);
491+
} else {
492+
LLDB_LOGF(GetLog(LLDBLog::Types),
493+
"Could not initialize reflection context for \"%s\"",
494+
triple.str().c_str());
495+
}
496+
488497
m_initialized_reflection_ctx = true;
489498

499+
Progress progress(
500+
llvm::formatv("Setting up Swift reflection for '{0}'",
501+
exe_module->GetFileSpec().GetFilename().AsCString()),
502+
m_modules_to_add.GetSize());
503+
504+
size_t completion = 0;
505+
490506
// Add all defered modules to reflection context that were added to
491507
// the target since this SwiftLanguageRuntime was created.
492508
m_modules_to_add.ForEach([&](const ModuleSP &module_sp) -> bool {
493509
AddModuleToReflectionContext(module_sp);
510+
progress.Increment(++completion);
494511
return true;
495512
});
496513
m_modules_to_add.Clear();

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#include "lldb/Core/DumpDataExtractor.h"
9696
#include "lldb/Core/Module.h"
9797
#include "lldb/Core/ModuleSpec.h"
98+
#include "lldb/Core/Progress.h"
9899
#include "lldb/Core/Section.h"
99100
#include "lldb/Core/StreamFile.h"
100101
#include "lldb/Core/ThreadSafeDenseMap.h"
@@ -3999,9 +4000,20 @@ void SwiftASTContext::ValidateSectionModules(
39994000

40004001
Status error;
40014002

4003+
Progress progress(
4004+
llvm::formatv("Loading Swift module {0}",
4005+
module.GetFileSpec().GetFilename().AsCString()),
4006+
module_names.size());
4007+
4008+
size_t completion = 0;
4009+
40024010
for (const std::string &module_name : module_names) {
40034011
SourceModule module_info;
40044012
module_info.path.push_back(ConstString(module_name));
4013+
4014+
// We have to increment the completion value even if we can't get the module
4015+
// object to stay in-sync with the total progress reporting.
4016+
progress.Increment(++completion);
40054017
if (!GetModule(module_info, error))
40064018
module.ReportWarning("unable to load swift module \"%s\" (%s)",
40074019
module_name.c_str(), error.AsCString());
@@ -8253,9 +8265,17 @@ bool SwiftASTContext::CacheUserImports(SwiftASTContext &swift_ast_context,
82538265
auto *persistent_expression_state =
82548266
sc.target_sp->GetSwiftPersistentExpressionState(exe_scope);
82558267

8256-
for (const auto &attributed_import : source_file.getImports()) {
8257-
swift::ModuleDecl *module = attributed_import.module.importedModule;
8268+
auto src_file_imports = source_file.getImports();
8269+
8270+
Progress progress(llvm::formatv("Caching Swift user imports from '{0}'",
8271+
source_file.getFilename().data()),
8272+
src_file_imports.size());
82588273

8274+
size_t completion = 0;
8275+
8276+
for (const auto &attributed_import : src_file_imports) {
8277+
progress.Increment(++completion);
8278+
swift::ModuleDecl *module = attributed_import.module.importedModule;
82598279
if (module) {
82608280
std::string module_name;
82618281
GetNameFromModule(module, module_name);
@@ -8331,7 +8351,16 @@ bool SwiftASTContext::GetCompileUnitImportsImpl(
83318351
if (!compile_unit || compile_unit->GetLanguage() != lldb::eLanguageTypeSwift)
83328352
return true;
83338353

8334-
for (const SourceModule &module : compile_unit->GetImportedModules()) {
8354+
auto cu_imports = compile_unit->GetImportedModules();
8355+
8356+
Progress progress(
8357+
llvm::formatv("Getting Swift compile unit imports for '{0}'",
8358+
compile_unit->GetPrimaryFile().GetFilename()),
8359+
cu_imports.size());
8360+
8361+
size_t completion = 0;
8362+
for (const SourceModule &module : cu_imports) {
8363+
progress.Increment(++completion);
83358364
// When building the Swift stdlib with debug info these will
83368365
// show up in "Swift.o", but we already imported them and
83378366
// manually importing them will fail.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Test that we are able to broadcast and receive swift progress events from lldb
3+
"""
4+
import lldb
5+
6+
import lldbsuite.test.lldbutil as lldbutil
7+
8+
from lldbsuite.test.lldbtest import *
9+
from lldbsuite.test.decorators import *
10+
from lldbsuite.test.eventlistener import EventListenerTestBase
11+
12+
class TestSwiftProgressReporting(EventListenerTestBase):
13+
14+
mydir = TestBase.compute_mydir(__file__)
15+
event_mask = lldb.SBDebugger.eBroadcastBitProgress
16+
event_data_extractor = lldb.SBDebugger.GetProgressFromEvent
17+
18+
@swiftTest
19+
def test_swift_progress_report(self):
20+
"""Test that we are able to fetch swift type-system progress events"""
21+
self.build()
22+
23+
target, process, thread, _ = lldbutil.run_to_source_breakpoint(self, 'break here',
24+
lldb.SBFileSpec('main.swift'))
25+
26+
self.assertGreater(thread.GetNumFrames(), 0)
27+
frame = thread.GetSelectedFrame()
28+
self.assertTrue(frame, "Invalid frame.")
29+
30+
# Resolve variable to exercise the type-system
31+
self.runCmd("expr numbers")
32+
33+
self.assertGreater(len(self.events), 0)
34+
35+
beacons = [ "Loading Swift module",
36+
"Caching Swift user imports from",
37+
"Setting up Swift reflection for",
38+
"Getting Swift compile unit imports for"]
39+
40+
for beacon in beacons:
41+
filtered_events = list(filter(lambda event: beacon in event[0],
42+
self.events))
43+
self.assertGreater(len(filtered_events), 0)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
struct IntPair {
2+
var original: Int
3+
var opposite: Int
4+
5+
init(_ value: Int) {
6+
self.original = value
7+
self.opposite = -value
8+
}
9+
}
10+
11+
enum Toggle { case On; case Off }
12+
13+
enum ColorCode {
14+
case RGB(UInt8, UInt8, UInt8)
15+
case Hex(Int)
16+
}
17+
18+
protocol Flyable {
19+
var fly : String { get }
20+
}
21+
22+
struct Bird: Flyable {
23+
var fly: String = "🦅"
24+
}
25+
26+
struct Plane: Flyable {
27+
var fly: String = "🛩"
28+
}
29+
30+
class Number<T:Numeric> {
31+
var number_value : T
32+
33+
init (number value : T) {
34+
number_value = value
35+
}
36+
}
37+
38+
func main() {
39+
let structArray = [ IntPair(1), IntPair(-2), IntPair(3) ]
40+
var enumArray = [ Toggle.Off ]
41+
var colors = [ColorCode.RGB(155,219,255), ColorCode.Hex(0x4545ff)]
42+
var flyingObjects : [Flyable] = [ Bird(), Plane() ]
43+
let numbers = [ Number(number: 42), Number(number: 3.14)]
44+
let bytes = [UInt8](0...255)
45+
var bits : [UInt8] = [0,1]
46+
print("break here")
47+
}
48+
49+
main()

0 commit comments

Comments
 (0)