diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index be355091b29d6..12a96849ed722 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -14,8 +14,8 @@ #define SWIFT_AST_SEARCHPATHOPTIONS_H #include "swift/Basic/ArrayRefView.h" +#include "swift/Basic/ExternalUnion.h" #include "swift/Basic/PathRemapper.h" -#include "swift/Basic/TaggedUnion.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" @@ -187,25 +187,81 @@ struct ExternalPluginSearchPathAndServerPath { std::string ServerPath; }; -namespace PluginSearchOption { -struct LoadPluginLibrary { - std::string LibraryPath; -}; -struct LoadPluginExecutable { - std::string ExecutablePath; - std::vector ModuleNames; -}; -struct PluginPath { - std::string SearchPath; -}; -struct ExternalPluginPath { - std::string SearchPath; - std::string ServerPath; -}; +class PluginSearchOption { +public: + struct LoadPluginLibrary { + std::string LibraryPath; + }; + struct LoadPluginExecutable { + std::string ExecutablePath; + std::vector ModuleNames; + }; + struct PluginPath { + std::string SearchPath; + }; + struct ExternalPluginPath { + std::string SearchPath; + std::string ServerPath; + }; + + enum class Kind : uint8_t { + LoadPluginLibrary, + LoadPluginExecutable, + PluginPath, + ExternalPluginPath, + }; -using Value = TaggedUnion; -} // namespace PluginSearchOption +private: + using Members = ExternalUnionMembers; + static Members::Index getIndexForKind(Kind kind) { + switch (kind) { + case Kind::LoadPluginLibrary: + return Members::indexOf(); + case Kind::LoadPluginExecutable: + return Members::indexOf(); + case Kind::PluginPath: + return Members::indexOf(); + case Kind::ExternalPluginPath: + return Members::indexOf(); + } + }; + using Storage = ExternalUnion; + + Kind kind; + Storage storage; + +public: + PluginSearchOption(const LoadPluginLibrary &v) + : kind(Kind::LoadPluginLibrary) { + storage.emplace(kind, v); + } + PluginSearchOption(const LoadPluginExecutable &v) + : kind(Kind::LoadPluginExecutable) { + storage.emplace(kind, v); + } + PluginSearchOption(const PluginPath &v) : kind(Kind::PluginPath) { + storage.emplace(kind, v); + } + PluginSearchOption(const ExternalPluginPath &v) + : kind(Kind::ExternalPluginPath) { + storage.emplace(kind, v); + } + + Kind getKind() const { return kind; } + + template + const T *dyn_cast() const { + if (Members::indexOf() != getIndexForKind(kind)) + return nullptr; + return &storage.get(kind); + } + + template + const T &get() const { + return storage.get(kind); + } +}; /// Options for controlling search path behavior. class SearchPathOptions { @@ -383,7 +439,7 @@ class SearchPathOptions { std::vector RuntimeLibraryPaths; /// Plugin search path options. - std::vector PluginSearchOpts; + std::vector PluginSearchOpts; /// Don't look in for compiler-provided modules. bool SkipRuntimeLibraryImportPaths = false; diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index d3e4f49f2441d..d38467eca23d8 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -13,6 +13,7 @@ #ifndef SWIFT_SERIALIZATION_SERIALIZATIONOPTIONS_H #define SWIFT_SERIALIZATION_SERIALIZATIONOPTIONS_H +#include "swift/AST/SearchPathOptions.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/PathRemapper.h" #include "llvm/Support/VersionTuple.h" @@ -43,10 +44,7 @@ namespace swift { StringRef ModuleLinkName; StringRef ModuleInterface; std::vector ExtraClangOptions; - std::vector PluginSearchPaths; - std::vector ExternalPluginSearchPaths; - std::vector CompilerPluginLibraryPaths; - std::vector CompilerPluginExecutablePaths; + std::vector PluginSearchOptions; /// Path prefixes that should be rewritten in debug info. PathRemapper DebuggingOptionsPrefixMap; diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index a82380e74963a..9ba02485ae973 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -111,10 +111,8 @@ struct ValidationInfo { class ExtendedValidationInfo { SmallVector ExtraClangImporterOpts; - SmallVector PluginSearchPaths; - SmallVector ExternalPluginSearchPaths; - SmallVector CompilerPluginLibraryPaths; - SmallVector CompilerPluginExecutablePaths; + SmallVector, 2> + PluginSearchOptions; std::string SDKPath; StringRef ModuleABIName; @@ -149,32 +147,13 @@ class ExtendedValidationInfo { ExtraClangImporterOpts.push_back(option); } - ArrayRef getPluginSearchPaths() const { - return PluginSearchPaths; + ArrayRef> + getPluginSearchOptions() const { + return PluginSearchOptions; } - void addPluginSearchPath(StringRef path) { - PluginSearchPaths.push_back(path); - } - - ArrayRef getExternalPluginSearchPaths() const { - return ExternalPluginSearchPaths; - } - void addExternalPluginSearchPath(StringRef path) { - ExternalPluginSearchPaths.push_back(path); - } - - ArrayRef getCompilerPluginLibraryPaths() const { - return CompilerPluginLibraryPaths; - } - void addCompilerPluginLibraryPath(StringRef path) { - CompilerPluginLibraryPaths.push_back(path); - } - - ArrayRef getCompilerPluginExecutablePaths() const { - return CompilerPluginExecutablePaths; - } - void addCompilerPluginExecutablePath(StringRef path) { - CompilerPluginExecutablePaths.push_back(path); + void addPluginSearchOption( + const std::pair &opt) { + PluginSearchOptions.push_back(opt); } bool isSIB() const { return Bits.IsSIB; } diff --git a/lib/AST/PluginLoader.cpp b/lib/AST/PluginLoader.cpp index 1bdfc95b1e7ef..49368dd9a0fa6 100644 --- a/lib/AST/PluginLoader.cpp +++ b/lib/AST/PluginLoader.cpp @@ -61,27 +61,31 @@ PluginLoader::lookupPluginByModuleName(Identifier moduleName) { // FIXME: Should we create a lookup table keyed by module name? for (auto &entry : Ctx.SearchPathOpts.PluginSearchOpts) { - using namespace PluginSearchOption; + switch (entry.getKind()) { // Try '-load-plugin-library'. - if (auto *val = entry.dyn_cast()) { - if (llvm::sys::path::filename(val->LibraryPath) == pluginLibBasename) { - return {val->LibraryPath, ""}; + case PluginSearchOption::Kind::LoadPluginLibrary: { + auto &val = entry.get(); + if (llvm::sys::path::filename(val.LibraryPath) == pluginLibBasename) { + return {val.LibraryPath, ""}; } continue; } // Try '-load-plugin-executable'. - if (auto *v = entry.dyn_cast()) { + case PluginSearchOption::Kind::LoadPluginExecutable: { + auto &val = entry.get(); auto found = ExecutablePluginPaths.find(moduleName); - if (found != ExecutablePluginPaths.end()) { - return {"", std::string(found->second)}; + if (found != ExecutablePluginPaths.end() && + found->second == val.ExecutablePath) { + return {"", val.ExecutablePath}; } continue; } // Try '-plugin-path'. - if (auto *v = entry.dyn_cast()) { - SmallString<128> fullPath(v->SearchPath); + case PluginSearchOption::Kind::PluginPath: { + auto &val = entry.get(); + SmallString<128> fullPath(val.SearchPath); llvm::sys::path::append(fullPath, pluginLibBasename); if (fs->exists(fullPath)) { return {std::string(fullPath), ""}; @@ -90,14 +94,16 @@ PluginLoader::lookupPluginByModuleName(Identifier moduleName) { } // Try '-external-plugin-path'. - if (auto *v = entry.dyn_cast()) { - SmallString<128> fullPath(v->SearchPath); + case PluginSearchOption::Kind::ExternalPluginPath: { + auto &val = entry.get(); + SmallString<128> fullPath(val.SearchPath); llvm::sys::path::append(fullPath, pluginLibBasename); if (fs->exists(fullPath)) { - return {std::string(fullPath), v->ServerPath}; + return {std::string(fullPath), val.ServerPath}; } continue; } + } } return {}; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index f96f80fc9647e..a1cfd21092870 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -209,36 +209,8 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs; } - // FIXME: Preserve the order of these options. - for (auto &elem : getSearchPathOptions().PluginSearchOpts) { - // '-plugin-path' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.PluginSearchPaths.push_back(arg->SearchPath); - continue; - } - - // '-external-plugin-path' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.ExternalPluginSearchPaths.push_back( - arg->SearchPath + "#" + arg->ServerPath); - continue; - } - - // '-load-plugin-library' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.CompilerPluginLibraryPaths.push_back(arg->LibraryPath); - continue; - } - - // '-load-plugin-executable' options. - if (auto *arg = elem.dyn_cast()) { - std::string optStr = arg->ExecutablePath + "#"; - llvm::interleave( - arg->ModuleNames, [&](auto &name) { optStr += name; }, - [&]() { optStr += ","; }); - serializationOpts.CompilerPluginExecutablePaths.push_back(optStr); - } - } + serializationOpts.PluginSearchOptions = + getSearchPathOptions().PluginSearchOpts; serializationOpts.DisableCrossModuleIncrementalInfo = opts.DisableCrossModuleIncrementalBuild; diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index d4c325e22c6ea..34bfe05c186e5 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -126,18 +126,27 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor, case options_block::XCC: extendedInfo.addExtraClangImporterOption(blobData); break; - case options_block::PLUGIN_SEARCH_PATH: - extendedInfo.addPluginSearchPath(blobData); - break; - case options_block::EXTERNAL_SEARCH_PLUGIN_PATH: - extendedInfo.addExternalPluginSearchPath(blobData); - break; - case options_block::COMPILER_PLUGIN_LIBRARY_PATH: - extendedInfo.addCompilerPluginLibraryPath(blobData); - break; - case options_block::COMPILER_PLUGIN_EXECUTABLE_PATH: - extendedInfo.addCompilerPluginExecutablePath(blobData); + case options_block::PLUGIN_SEARCH_OPTION: { + unsigned kind; + options_block::ResilienceStrategyLayout::readRecord(scratch, kind); + PluginSearchOption::Kind optKind; + switch (PluginSearchOptionKind(kind)) { + case PluginSearchOptionKind::PluginPath: + optKind = PluginSearchOption::Kind::PluginPath; + break; + case PluginSearchOptionKind::ExternalPluginPath: + optKind = PluginSearchOption::Kind::ExternalPluginPath; + break; + case PluginSearchOptionKind::LoadPluginLibrary: + optKind = PluginSearchOption::Kind::LoadPluginLibrary; + break; + case PluginSearchOptionKind::LoadPluginExecutable: + optKind = PluginSearchOption::Kind::LoadPluginExecutable; + break; + } + extendedInfo.addPluginSearchOption({optKind, blobData}); break; + } case options_block::IS_SIB: bool IsSIB; options_block::IsSIBLayout::readRecord(scratch, IsSIB); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 12beebdf5f15a..b8ec1c1c180e9 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 792; // removed select_value +const uint16_t SWIFTMODULE_VERSION_MINOR = 793; // PluginSearchOption /// A standard hash seed used for all string hashes in a serialized module. /// @@ -651,6 +651,16 @@ enum class MacroIntroducedDeclNameKind : uint8_t { }; using MacroIntroducedDeclNameKindField = BCFixed<4>; +// These IDs must \em not be renumbered or reordered without incrementing +// the module version. +enum class PluginSearchOptionKind : uint8_t { + PluginPath, + ExternalPluginPath, + LoadPluginLibrary, + LoadPluginExecutable, +}; +using PluginSearchOptionKindField = BCFixed<3>; + // Encodes a VersionTuple: // // Major @@ -884,10 +894,7 @@ namespace options_block { IS_CONCURRENCY_CHECKED, MODULE_PACKAGE_NAME, MODULE_EXPORT_AS_NAME, - PLUGIN_SEARCH_PATH, - EXTERNAL_SEARCH_PLUGIN_PATH, - COMPILER_PLUGIN_LIBRARY_PATH, - COMPILER_PLUGIN_EXECUTABLE_PATH, + PLUGIN_SEARCH_OPTION, HAS_CXX_INTEROPERABILITY_ENABLED, }; @@ -901,24 +908,10 @@ namespace options_block { BCBlob // -Xcc flag, as string >; - using PluginSearchPathLayout = BCRecordLayout< - PLUGIN_SEARCH_PATH, - BCBlob // -plugin-path value - >; - - using ExternalPluginSearchPathLayout = BCRecordLayout< - EXTERNAL_SEARCH_PLUGIN_PATH, - BCBlob // -external-plugin-path value - >; - - using CompilerPluginLibraryPathLayout = BCRecordLayout< - COMPILER_PLUGIN_LIBRARY_PATH, - BCBlob // -load-plugin-library value - >; - - using CompilerPluginExecutablePathLayout = BCRecordLayout< - COMPILER_PLUGIN_EXECUTABLE_PATH, - BCBlob // -load-plugin-executable value + using PluginSearchOptionLayout = BCRecordLayout< + PLUGIN_SEARCH_OPTION, + PluginSearchOptionKindField, // kind + BCBlob // option value string >; using IsSIBLayout = BCRecordLayout< diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 8f1758049b6cb..d243dc2ad0cd8 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -846,10 +846,7 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(options_block, HAS_CXX_INTEROPERABILITY_ENABLED); BLOCK_RECORD(options_block, MODULE_PACKAGE_NAME); BLOCK_RECORD(options_block, MODULE_EXPORT_AS_NAME); - BLOCK_RECORD(options_block, PLUGIN_SEARCH_PATH); - BLOCK_RECORD(options_block, EXTERNAL_SEARCH_PLUGIN_PATH); - BLOCK_RECORD(options_block, COMPILER_PLUGIN_LIBRARY_PATH); - BLOCK_RECORD(options_block, COMPILER_PLUGIN_EXECUTABLE_PATH); + BLOCK_RECORD(options_block, PLUGIN_SEARCH_OPTION); BLOCK(INPUT_BLOCK); BLOCK_RECORD(input_block, IMPORTED_MODULE); @@ -1138,27 +1135,44 @@ void Serializer::writeHeader(const SerializationOptions &options) { } // Macro plugins - options_block::PluginSearchPathLayout PluginSearchPath(Out); - for (auto Arg : options.PluginSearchPaths) { - PluginSearchPath.emit(ScratchRecord, Arg); - } - - options_block::ExternalPluginSearchPathLayout - ExternalPluginSearchPath(Out); - for (auto Arg : options.ExternalPluginSearchPaths) { - ExternalPluginSearchPath.emit(ScratchRecord, Arg); - } - - options_block::CompilerPluginLibraryPathLayout - CompilerPluginLibraryPath(Out); - for (auto Arg : options.CompilerPluginLibraryPaths) { - CompilerPluginLibraryPath.emit(ScratchRecord, Arg); - } - - options_block::CompilerPluginExecutablePathLayout - CompilerPluginExecutablePath(Out); - for (auto Arg : options.CompilerPluginExecutablePaths) { - CompilerPluginExecutablePath.emit(ScratchRecord, Arg); + options_block::PluginSearchOptionLayout PluginSearchOpt(Out); + for (auto &elem : options.PluginSearchOptions) { + switch (elem.getKind()) { + case PluginSearchOption::Kind::PluginPath: { + auto &opt = elem.get(); + PluginSearchOpt.emit(ScratchRecord, + uint8_t(PluginSearchOptionKind::PluginPath), + opt.SearchPath); + continue; + } + case PluginSearchOption::Kind::ExternalPluginPath: { + auto &opt = elem.get(); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::ExternalPluginPath), + opt.SearchPath + "#" + opt.ServerPath); + continue; + } + case PluginSearchOption::Kind::LoadPluginLibrary: { + auto &opt = elem.get(); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::LoadPluginLibrary), + opt.LibraryPath); + continue; + } + case PluginSearchOption::Kind::LoadPluginExecutable: { + auto &opt = elem.get(); + std::string optStr = opt.ExecutablePath + "#"; + llvm::interleave( + opt.ModuleNames, [&](auto &name) { optStr += name; }, + [&]() { optStr += ","; }); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::LoadPluginExecutable), optStr); + continue; + } + } } } } diff --git a/test/Macros/serialize_plugin_search_paths.swift b/test/Macros/serialize_plugin_search_paths.swift index ef9c5c8d7ee88..cd4b53fc4725f 100644 --- a/test/Macros/serialize_plugin_search_paths.swift +++ b/test/Macros/serialize_plugin_search_paths.swift @@ -11,10 +11,10 @@ // RUN: -load-plugin-executable %t/mock-plugin#TestPlugin // RUN: %lldb-moduleimport-test -verbose -dump-module %t/a.out | %FileCheck %s -// CHECK: - Macro Search Paths: -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -external-plugin-path: {{.*}}plugins#{{.*}}swift-plugin-server -// CHECK: -load-plugin-library: {{.*}}MacroDefinition.{{dylib|so|dll}} -// CHECK: -load-plugin-executable: {{.*}}mock-plugin#TestPlugin +// CHECK: - Plugin Search Options: +// CHECK: -plugin-path {{.*}}plugins +// CHECK: -external-plugin-path {{.*}}plugins#{{.*}}swift-plugin-server +// CHECK: -load-plugin-library {{.*}}MacroDefinition.{{dylib|so|dll}} +// CHECK: -load-plugin-executable {{.*}}mock-plugin#TestPlugin +// CHECK: -plugin-path {{.*}}plugins +// CHECK: -plugin-path {{.*}}plugins diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp index 6d9314b3ecd3a..4f0c4a44acd42 100644 --- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp +++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp @@ -89,15 +89,25 @@ static bool validateModule( llvm::outs() << ", system=" << (searchPath.IsSystem ? "true" : "false") << "\n"; } - llvm::outs() << "- Macro Search Paths:\n"; - for (auto path : extendedInfo.getPluginSearchPaths()) - llvm::outs() << " -plugin-path: " << path << "\n"; - for (auto path : extendedInfo.getExternalPluginSearchPaths()) - llvm::outs() << " -external-plugin-path: " << path << "\n"; - for (auto path : extendedInfo.getCompilerPluginLibraryPaths()) - llvm::outs() << " -load-plugin-library: " << path << "\n"; - for (auto path : extendedInfo.getCompilerPluginExecutablePaths()) - llvm::outs() << " -load-plugin-executable: " << path << "\n"; + llvm::outs() << "- Plugin Search Options:\n"; + for (auto opt : extendedInfo.getPluginSearchOptions()) { + StringRef optStr; + switch (opt.first) { + case swift::PluginSearchOption::Kind::PluginPath: + optStr = "-plugin-path"; + break; + case swift::PluginSearchOption::Kind::ExternalPluginPath: + optStr = "-external-plugin-path"; + break; + case swift::PluginSearchOption::Kind::LoadPluginLibrary: + optStr = "-load-plugin-library"; + break; + case swift::PluginSearchOption::Kind::LoadPluginExecutable: + optStr = "-load-plugin-executable"; + break; + } + llvm::outs() << " " << optStr << " " << opt.second << "\n"; + } } return true;