Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 103 additions & 42 deletions lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ static void printASTValidationError(
llvm::raw_ostream &errs,
const swift::serialization::ValidationInfo &ast_info,
const swift::serialization::ExtendedValidationInfo &ext_ast_info,
Module &module, StringRef module_buf, bool invalid_name,
StringRef module_name, StringRef module_buf, bool invalid_name,
bool invalid_size) {
const char *error = getImportFailureString(ast_info.status);
errs << "AST validation error";
Expand All @@ -1111,9 +1111,9 @@ static void printASTValidationError(
- SDK path: {7}
- Clang Importer Options:
)",
ast_info.name, module.GetSpecificationDescription(), error,
ast_info.targetTriple, ast_info.shortVersion, ast_info.bytes,
module_buf.size(), ext_ast_info.getSDKPath());
ast_info.name, module_name, error, ast_info.targetTriple,
ast_info.shortVersion, ast_info.bytes, module_buf.size(),
ext_ast_info.getSDKPath());
for (StringRef ExtraOpt : ext_ast_info.getExtraClangImporterOptions())
LLDB_LOG(log, " -- {0}", ExtraOpt);
}
Expand Down Expand Up @@ -1171,21 +1171,16 @@ static std::string GetPluginServerForSDK(llvm::StringRef sdk_path) {
/// invocation with the concatenated search paths from the blobs.
/// \returns true if an error was encountered.
static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
Module &module,
llvm::StringRef module_name,
llvm::ArrayRef<StringRef> buffers,
const PathMappingList &path_map,
bool discover_implicit_search_paths,
const std::string &m_description,
llvm::raw_ostream &error,
bool &got_serialized_options,
bool &found_swift_modules) {
bool found_validation_errors = false;
got_serialized_options = false;
auto ast_file_datas = module.GetASTData(eLanguageTypeSwift);
LOG_PRINTF(GetLog(LLDBLog::Types), "Found %d AST file data entries.",
(int)ast_file_datas.size());

// If no N_AST symbols exist, this is not an error.
if (ast_file_datas.empty())
return false;

auto &search_path_options = invocation.getSearchPathOptions();
auto get_override_server = [&](llvm::StringRef plugin_path) -> std::string {
Expand Down Expand Up @@ -1258,9 +1253,7 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,

// An AST section consists of one or more AST modules, optionally
// with headers. Iterate over all AST modules.
for (auto ast_file_data_sp : ast_file_datas) {
llvm::StringRef buf((const char *)ast_file_data_sp->GetBytes(),
ast_file_data_sp->GetByteSize());
for (auto buf : buffers) {
swift::serialization::ValidationInfo info;
for (; !buf.empty(); buf = buf.substr(info.bytes)) {
llvm::SmallVector<swift::serialization::SearchPath> searchPaths;
Expand All @@ -1275,8 +1268,8 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,
if (invalid_ast || invalid_size || invalid_name) {
// Validation errors are diagnosed, but not fatal for the context.
found_validation_errors = true;
printASTValidationError(error, info, extended_validation_info, module,
buf, invalid_name, invalid_size);
printASTValidationError(error, info, extended_validation_info,
module_name, buf, invalid_name, invalid_size);
// If there's a size error, quit the loop early, otherwise try the next.
if (invalid_size)
break;
Expand All @@ -1288,8 +1281,7 @@ static bool DeserializeAllCompilerFlags(swift::CompilerInvocation &invocation,

auto remap = [&](const std::string &path) {
ConstString remapped;
if (module.GetSourceMappingList().RemapPath(ConstString(path),
remapped))
if (path_map.RemapPath(ConstString(path), remapped))
return remapped.GetStringRef().str();
return path;
};
Expand Down Expand Up @@ -1762,17 +1754,37 @@ static std::string GetSDKPathFromDebugInfo(std::string m_description,
return GetSDKPath(m_description, sdk);
}

static std::vector<llvm::StringRef>
GetASTBuffersFromModule(const std::string &m_description,
llvm::ArrayRef<lldb::DataBufferSP> ast_file_datas,
std::string &module_name) {
LOG_PRINTF(GetLog(LLDBLog::Types), "Found %d AST file data entries in %s.",
(int)ast_file_datas.size(), module_name.c_str());
std::vector<llvm::StringRef> buffers;
for (auto &data : ast_file_datas)
if (data)
buffers.push_back(
StringRef((const char *)data->GetBytes(), data->GetByteSize()));
return buffers;
}

/// Detect whether a Swift module was "imported" by DWARFImporter.
/// All this *really* means is that it couldn't be loaded through any
/// other mechanism.
static bool IsDWARFImported(swift::ModuleDecl &module) {
return std::any_of(module.getFiles().begin(), module.getFiles().end(),
[](swift::FileUnit *file_unit) {
return (file_unit->getKind() ==
swift::FileUnitKind::DWARFModule);
});
return llvm::any_of(module.getFiles(), [](swift::FileUnit *file_unit) {
return (file_unit->getKind() == swift::FileUnitKind::DWARFModule);
});
}

/// Detect whether this is a proper Swift module.
static bool IsSerializedAST(swift::ModuleDecl &module) {
return llvm::any_of(module.getFiles(), [](swift::FileUnit *file_unit) {
return (file_unit->getKind() == swift::FileUnitKind::SerializedAST);
});
}


lldb::TypeSystemSP
SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
TypeSystemSwiftTypeRef &typeref_typesystem,
Expand Down Expand Up @@ -1879,15 +1891,24 @@ SwiftASTContext::CreateInstance(lldb::LanguageType language, Module &module,
bool got_serialized_options = false;
llvm::SmallString<0> error;
llvm::raw_svector_ostream errs(error);
// Implicit search paths will be discoverd by ValidateSecionModules().
// Implicit search paths will be discovered by ValidateSecionModules().
bool discover_implicit_search_paths = false;
if (DeserializeAllCompilerFlags(swift_ast_sp->GetCompilerInvocation(),
module, discover_implicit_search_paths,
m_description, errs, got_serialized_options,
found_swift_modules)) {
// Validation errors are not fatal for the context.
swift_ast_sp->AddDiagnostic(eDiagnosticSeverityError, errs.str());
}
auto ast_file_datas = module.GetASTData(eLanguageTypeSwift);
std::string module_name = module.GetSpecificationDescription();
std::vector<llvm::StringRef> buffers =
GetASTBuffersFromModule(m_description, ast_file_datas, module_name);

// If no N_AST symbols exist, this is not an error.
if (!buffers.empty())
if (DeserializeAllCompilerFlags(
swift_ast_sp->GetCompilerInvocation(),
module_name, buffers,
module.GetSourceMappingList(), discover_implicit_search_paths,
m_description, errs, got_serialized_options,
found_swift_modules)) {
// Validation errors are not fatal for the context.
swift_ast_sp->AddDiagnostic(eDiagnosticSeverityError, errs.str());
}

llvm::StringRef serialized_triple =
swift_ast_sp->GetCompilerInvocation().getTargetTriple();
Expand Down Expand Up @@ -2194,13 +2215,21 @@ static void ProcessModule(
llvm::SmallString<0> error;
llvm::raw_svector_ostream errs(error);
swift::CompilerInvocation invocation;
if (DeserializeAllCompilerFlags(
invocation, *module_sp, discover_implicit_search_paths, m_description,
errs, got_serialized_options, found_swift_modules)) {
// TODO: After removing DeserializeAllCompilerFlags from
// CreateInstance(per-Module), errs will need to be
// collected here and surfaced.
}
auto ast_file_datas = module_sp->GetASTData(eLanguageTypeSwift);
std::string module_name = module_sp->GetSpecificationDescription();
std::vector<llvm::StringRef> buffers =
GetASTBuffersFromModule(m_description, ast_file_datas, module_name);

// If no N_AST symbols exist, this is not an error.
if (!buffers.empty())
if (DeserializeAllCompilerFlags(
invocation, module_name, buffers, module_sp->GetSourceMappingList(),
discover_implicit_search_paths, m_description, errs,
got_serialized_options, found_swift_modules)) {
// TODO: After removing DeserializeAllCompilerFlags from
// CreateInstance(per-Module), errs will need to be
// collected here and surfaced.
}

// Copy the interesting deserialized flags to the out parameters.
const auto &opts = invocation.getSearchPathOptions();
Expand Down Expand Up @@ -8342,10 +8371,42 @@ bool SwiftASTContextForExpressions::CacheUserImports(
LOG_PRINTF(GetLog(LLDBLog::Types | LLDBLog::Expressions),
"Performing auto import on found module: %s.\n",
module_name.c_str());
if (!LoadOneModule(module_info, *this, process_sp,
/*import_dylibs=*/true, error))
auto *module_decl = LoadOneModule(module_info, *this, process_sp,
/*import_dylibs=*/true, error);
if (!module_decl)
return false;

if (IsSerializedAST(*module_decl)) {
// Parse additional search paths from the module.
StringRef ast_file = module_decl->getModuleLoadedFilename();
if (llvm::sys::path::is_absolute(ast_file)) {
auto file_or_err =
llvm::MemoryBuffer::getFile(ast_file, /*IsText=*/false,
/*RequiresNullTerminator=*/false);
if (!file_or_err.getError() && file_or_err->get()) {
PathMappingList path_remap;
llvm::SmallString<0> error;
bool found_swift_modules = false;
bool got_serialized_options = false;
llvm::raw_svector_ostream errs(error);
bool discover_implicit_search_paths = false;
swift::CompilerInvocation &invocation = GetCompilerInvocation();

LOG_PRINTF(GetLog(LLDBLog::Types),
"Scanning for search paths in %s",
ast_file.str().c_str());
if (DeserializeAllCompilerFlags(
invocation, ast_file, {file_or_err->get()->getBuffer()},
path_remap, discover_implicit_search_paths,
m_description.str().str(), errs, got_serialized_options,
found_swift_modules)) {
LOG_PRINTF(GetLog(LLDBLog::Types), "Could not parse %s: %s",
ast_file.str().c_str(), error.str().str().c_str());
}
if (got_serialized_options)
LogConfiguration();
}
}
}
// How do we tell we are in REPL or playground mode?
AddHandLoadedModule(module_const_str, attributed_import);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,6 @@ def test_swift_deployment_target_from_macho(self):
self, "break here", lldb.SBFileSpec("main.swift")
)
self.expect("expression f", substrs=["i = 23"])

found_no_ast = False
found_triple = False
import io

logfile = io.open(log, "r", encoding="utf-8")
for line in logfile:
if (
'SwiftASTContextForModule("a.out")::DeserializeAllCompilerFlags() -- Found 0 AST file data entries.'
in line
):
found_no_ast = True
if (
'SwiftASTContextForModule("a.out")::SetTriple(' in line
and "apple-macosx11.0" in line
):
found_triple = True
self.assertTrue(found_no_ast)
self.assertTrue(found_triple)
self.filecheck('platform shell cat ""%s"' % log, __file__)
# CHECK: SwiftASTContextForExpressions::SetTriple({{.*}}apple-macosx11.0.0
# CHECK: SwiftASTContextForExpressions::RegisterSectionModules("a.out") retrieved 0 AST Data blobs
1 change: 1 addition & 0 deletions lldb/test/API/lang/swift/macro/Macro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@freestanding(expression) public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroImpl", type: "StringifyMacro")
26 changes: 22 additions & 4 deletions lldb/test/API/lang/swift/macro/Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
SWIFT_SOURCES := main.swift
SWIFTFLAGS_EXTRAS = -enable-experimental-feature Macros \
-load-plugin-library $(BUILDDIR)/libMacroImpl.dylib
SWIFTFLAGS_EXTRAS = -I.

all: libMacroImpl.dylib $(EXE)
ifneq "$(SWIFT_SOURCES)" "empty.swift"

SWIFTFLAGS_EXTRAS += -load-plugin-library $(BUILDDIR)/libMacroImpl.dylib
LD_EXTRAS = -L$(BUILDDIR) -lMacro

endif

all: libMacro.dylib libMacroImpl.dylib $(EXE)

include Makefile.rules

libMacro.dylib:
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
VPATH=$(SRCDIR) -I $(SRCDIR) \
-f $(THIS_FILE_DIR)/Makefile.rules \
DYLIB_SWIFT_SOURCES=Macro.swift \
DYLIB_NAME=Macro \
DYLIB_ONLY=YES \
SWIFT_SOURCES= \
SWIFTFLAGS_EXTRAS="-load-plugin-library $(BUILDDIR)/libMacroImpl.dylib" \
all
$(RM) $(BUILDDIR)/Macro.swiftinterface

libMacroImpl.dylib:
$(MAKE) MAKE_DSYM=$(MAKE_DSYM) CC=$(CC) SWIFTC=$(SWIFTC) \
ARCH=$(ARCH) DSYMUTIL=$(DSYMUTIL) \
Expand Down
39 changes: 31 additions & 8 deletions lldb/test/API/lang/swift/macro/TestSwiftMacro.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,7 @@
class TestSwiftMacro(lldbtest.TestBase):

NO_DEBUG_INFO_TESTCASE = True

@swiftTest
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
@expectedFailureAll(oslist=["linux"])
def test(self):
"""Test Swift macros"""
self.build()

def setupPluginServerForTesting(self):
# Find the path to the just-built swift-plugin-server.
# FIXME: this is not very robust.
def replace_last(old, new, string):
Expand All @@ -33,6 +26,15 @@ def replace_last(old, new, string):
'settings set target.experimental.swift-plugin-server-for-path %s=%s'
% (self.getBuildDir(), swift_plugin_server))


@swiftTest
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
@expectedFailureAll(oslist=["linux"])
def testDebugging(self):
"""Test Swift macros"""
self.build(dictionary={'SWIFT_SOURCES': 'main.swift'})
self.setupPluginServerForTesting()

target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.swift")
)
Expand All @@ -53,3 +55,24 @@ def replace_last(old, new, string):
# Make sure we can set a symbolic breakpoint on a macro.
b = target.BreakpointCreateByName("stringify")
self.assertGreaterEqual(b.GetNumLocations(), 1)

@swiftTest
# At the time of writing swift/test/Macros/macro_expand.swift is also disabled.
@expectedFailureAll(oslist=["linux"])
def testInteractive(self):
"""Test Swift macros that are loaded via a user-initiated import"""
self.build(dictionary={'SWIFT_SOURCES': 'empty.swift'})
self.setupPluginServerForTesting()
target, process, thread, bkpt = lldbutil.run_to_name_breakpoint(
self, "main"
)

types_log = self.getBuildArtifact('types.log')
self.expect('log enable lldb types -f "%s"' % types_log)
self.expect('expression -- import Macro')
self.expect('expression -- #stringify(1)', substrs=['0 = 1', '1 = "1"'])
self.filecheck('platform shell cat "%s"' % types_log, __file__)
# CHECK: CacheUserImports(){{.*}}: Macro.
# CHECK: SwiftASTContextForExpressions::LoadOneModule(){{.*}}Imported module Macro from {kind = Serialized Swift AST, filename = "{{.*}}Macro.swiftmodule";}
# CHECK: CacheUserImports(){{.*}}Scanning for search paths in{{.*}}Macro.swiftmodule
# CHECK: SwiftASTContextForExpressions::LogConfiguration(){{.*}} -external-plugin-path {{.*}}/lang/swift/macro/{{.*}}#{{.*}}/swift-plugin-server
1 change: 1 addition & 0 deletions lldb/test/API/lang/swift/macro/empty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print("Hello World")
2 changes: 1 addition & 1 deletion lldb/test/API/lang/swift/macro/main.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@freestanding(expression) macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroImpl", type: "StringifyMacro")
import Macro

func testStringify(a: Int, b: Int) {
print("break here")
Expand Down