diff --git a/include/swift/AST/LinkLibrary.h b/include/swift/AST/LinkLibrary.h index a4234809105..df359296a94 100644 --- a/include/swift/AST/LinkLibrary.h +++ b/include/swift/AST/LinkLibrary.h @@ -31,13 +31,18 @@ enum class LibraryKind { class LinkLibrary { private: std::string Name; - LibraryKind Kind; + unsigned Kind : 1; + unsigned ForceLoad : 1; public: - LinkLibrary(StringRef N, LibraryKind K) : Name(N), Kind(K) {} + LinkLibrary(StringRef N, LibraryKind K, bool forceLoad = false) + : Name(N), Kind(static_cast(K)), ForceLoad(forceLoad) { + assert(getKind() == K && "not enough bits for the kind"); + } - LibraryKind getKind() const { return Kind; } + LibraryKind getKind() const { return static_cast(Kind); } StringRef getName() const { return Name; } + bool shouldForceLoad() const { return ForceLoad; } }; } // end namespace swift diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 9abe54fabef..f5bd4197a96 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0; /// Serialized module format minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = 91; +const uint16_t VERSION_MINOR = 92; using DeclID = Fixnum<31>; using DeclIDField = BCFixed<31>; @@ -348,6 +348,7 @@ namespace input_block { using LinkLibraryLayout = BCRecordLayout< LINK_LIBRARY, LibraryKindField, // kind + BCFixed<1>, // forced? BCBlob // library name >; diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 27fdb3a7dde..e42b7b66e04 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -160,8 +160,9 @@ namespace swift { const SILModule *M = nullptr, bool serializeAllSIL = false, ArrayRef inputFilenames = {}, + StringRef importedHeader = {}, StringRef moduleLinkName = {}, - StringRef importedHeader = {}); + bool autolinkForceLoad = false); /// Turn the given Swift module into either LLVM IR or native code /// and return the generated LLVM IR module. diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 3aa7c799f13..ac69d22c58b 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -100,6 +100,8 @@ static void addCommonFrontendArgs(const ToolChain &TC, inputArgs.AddLastArg(arguments, options::OPT_module_cache_path); inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension); inputArgs.AddLastArg(arguments, options::OPT_import_objc_header); + inputArgs.AddLastArg(arguments, options::OPT_module_link_name); + inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load); // Pass through the values passed to -Xfrontend. inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend); @@ -260,12 +262,7 @@ Job *Swift::constructJob(const JobAction &JA, std::unique_ptr Inputs, addCommonFrontendArgs(getToolChain(), OI, Output.get(), Args, Arguments); - Args.AddLastArg(Arguments, options::OPT_module_link_name); Args.AddLastArg(Arguments, options::OPT_import_underlying_module); - - // FIXME: Warn if -module-link-name is not present. - Args.AddLastArg(Arguments, options::OPT_autolink_force_load); - Args.AddLastArg(Arguments, options::OPT_split_objc_selectors); Args.AddLastArg(Arguments, options::OPT_implicit_objc_with); Args.AddLastArg(Arguments, options::OPT_strict_keyword_arguments); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index bb329ad2086..170fcca9664 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -388,6 +388,19 @@ llvm::Constant *IRGenModule::getSize(Size size) { return llvm::ConstantInt::get(SizeTy, size.getValue()); } +static StringRef encodeForceLoadSymbolName(llvm::SmallVectorImpl &buf, + StringRef name) { + llvm::raw_svector_ostream os{buf}; + os << "_swift_FORCE_LOAD_$"; + if (clang::isValidIdentifier(name)) { + os << "_" << name; + } else { + for (auto c : name) + os.write_hex(static_cast(c)); + } + return os.str(); +} + void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { llvm::LLVMContext &ctx = Module.getContext(); @@ -410,6 +423,22 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { AutolinkEntries.push_back(llvm::MDNode::get(ctx, args)); break; } + + if (linkLib.shouldForceLoad()) { + llvm::SmallString<64> buf; + encodeForceLoadSymbolName(buf, linkLib.getName()); + auto symbolAddr = Module.getOrInsertGlobal(buf.str(), Int1Ty); + + buf += "_$_"; + buf += Opts.ModuleName; + + if (!Module.getGlobalVariable(buf.str())) { + (void)new llvm::GlobalVariable(Module, symbolAddr->getType(), + /*constant=*/true, + llvm::GlobalAlias::LinkOnceAnyLinkage, + symbolAddr, buf.str()); + } + } } // FIXME: This should just be the implementation of @@ -425,19 +454,6 @@ static int pointerPODSortComparator(T * const *lhs, T * const *rhs) { return 0; } -static StringRef encodeForceLoadSymbolName(llvm::SmallVectorImpl &buf, - StringRef name) { - llvm::raw_svector_ostream os{buf}; - os << "_swift_FORCE_LOAD_$"; - if (clang::isValidIdentifier(name)) { - os << "_" << name; - } else { - for (auto c : name) - os.write_hex(static_cast(c)); - } - return os.str(); -} - void IRGenModule::emitAutolinkInfo() { // FIXME: This constant should be vended by LLVM somewhere. static const char * const LinkerOptionsFlagName = "Linker Options"; diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index eaf0e923a76..7c88d48abae 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -586,9 +586,11 @@ ModuleFile::ModuleFile( } case input_block::LINK_LIBRARY: { uint8_t rawKind; - input_block::ImportedModuleLayout::readRecord(scratch, rawKind); + bool shouldForceLink; + input_block::LinkLibraryLayout::readRecord(scratch, rawKind, + shouldForceLink); if (auto libKind = getActualLibraryKind(rawKind)) - LinkLibraries.push_back({blobData, *libKind}); + LinkLibraries.push_back({blobData, *libKind, shouldForceLink}); // else ignore the dependency...it'll show up as a linker error. break; } diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 60cbf9bc6a3..91065f6c9cc 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -424,8 +424,9 @@ static void flattenImportPath(const Module::ImportedModule &import, } void Serializer::writeInputFiles(FilenamesTy inputFiles, + StringRef importedHeader, StringRef moduleLinkName, - StringRef importedHeader) { + bool autolinkForceLoad) { BCBlockRAII restoreBlock(Out, INPUT_BLOCK_ID, 3); input_block::SourceFileLayout SourceFile(Out); input_block::ImportedModuleLayout ImportedModule(Out); @@ -480,7 +481,7 @@ void Serializer::writeInputFiles(FilenamesTy inputFiles, if (!moduleLinkName.empty()) { LinkLibrary.emit(ScratchRecord, serialization::LibraryKind::Library, - moduleLinkName); + autolinkForceLoad, moduleLinkName); } } @@ -2841,9 +2842,9 @@ Serializer::Serializer(const unsigned char (&signature)[N], void Serializer::writeToStream(raw_ostream &os, ModuleOrSourceFile DC, const SILModule *SILMod, bool serializeAllSIL, - FilenamesTy inputFiles, + FilenamesTy inputFiles, StringRef importedHeader, StringRef moduleLinkName, - StringRef importedHeader) { + bool autolinkForceLoad) { Serializer S{MODULE_SIGNATURE, DC}; // FIXME: This is only really needed for debugging. We don't actually use it. @@ -2852,7 +2853,8 @@ void Serializer::writeToStream(raw_ostream &os, ModuleOrSourceFile DC, { BCBlockRAII moduleBlock(S.Out, MODULE_BLOCK_ID, 2); S.writeHeader(); - S.writeInputFiles(inputFiles, moduleLinkName, importedHeader); + S.writeInputFiles(inputFiles, importedHeader, moduleLinkName, + autolinkForceLoad); S.writeSIL(SILMod, serializeAllSIL); S.writeAST(DC); } @@ -2883,8 +2885,8 @@ void Serializer::writeDocToStream(raw_ostream &os, ModuleOrSourceFile DC) { void swift::serialize(ModuleOrSourceFile DC, const char *outputPath, const char *docOutputPath, const SILModule *M, bool serializeAllSIL, - FilenamesTy inputFiles, StringRef moduleLinkName, - StringRef importedHeader) { + FilenamesTy inputFiles, StringRef importedHeader, + StringRef moduleLinkName, bool autolinkForceLoad) { assert(outputPath && outputPath[0] != '\0'); std::string errorInfo; @@ -2898,7 +2900,7 @@ void swift::serialize(ModuleOrSourceFile DC, const char *outputPath, } Serializer::writeToStream(out, DC, M, serializeAllSIL, inputFiles, - moduleLinkName, importedHeader); + importedHeader, moduleLinkName, autolinkForceLoad); if (docOutputPath && docOutputPath[0] != '\0') { std::string errorInfo; diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index f7424e33cf3..208b7206a33 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -176,8 +176,8 @@ private: /// Writes the dependencies used to build this module: its imported /// modules and its source files. - void writeInputFiles(FilenamesTy inputFiles, StringRef moduleLinkName, - StringRef importedHeader); + void writeInputFiles(FilenamesTy inputFiles, StringRef importedHeader, + StringRef moduleLinkName, bool autolinkForceLoad); /// Writes the given pattern, recursively. void writePattern(const Pattern *pattern); @@ -286,8 +286,8 @@ public: /// Serialize a module to the given stream. static void writeToStream(raw_ostream &os, ModuleOrSourceFile DC, const SILModule *M, bool serializeAllSIL, - FilenamesTy inputFiles, StringRef moduleLinkName, - StringRef importedHeader); + FilenamesTy inputFiles, StringRef importedHeader, + StringRef moduleLinkName, bool autolinkForceLoad); /// Serialize module documentation to the given stream. static void writeDocToStream(raw_ostream &os, ModuleOrSourceFile DC); diff --git a/tools/driver/frontend_main.cpp b/tools/driver/frontend_main.cpp index 8cce5f0ece5..70b79cc15a3 100644 --- a/tools/driver/frontend_main.cpp +++ b/tools/driver/frontend_main.cpp @@ -190,7 +190,8 @@ static bool performCompile(CompilerInstance &Instance, serialize(DC, opts.ModuleOutputPath.c_str(), opts.ModuleDocOutputPath.c_str(), SM.get(), opts.SILSerializeAll, opts.InputFilenames, - opts.ModuleLinkName, opts.ImplicitObjCHeaderPath); + opts.ImplicitObjCHeaderPath, opts.ModuleLinkName, + !IRGenOpts.ForceLoadSymbolName.empty()); if (Action == FrontendOptions::EmitModuleOnly) return false;