From 41700b03da4a7e04d8889f17cb159926a53f32ff Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 9 May 2014 01:07:07 +0000 Subject: [PATCH] Add a new (hidden) option -autolink-force-load. This option puts a special symbol into the generated object files that other object files can reference to force the library to be loaded. The next commit will modify the way we serialize autolinking information so that importers of this module will always emit a reference to this symbol. This means the library will be linked into the final binary even if no other symbols are used (which happens for some of our overlays that just add category methods to Objective-C classes). Part of Swift SVN r17750 --- include/swift/AST/IRGenOptions.h | 6 +++++- include/swift/Driver/Options.td | 3 +++ lib/Driver/Tools.cpp | 3 +++ lib/Frontend/CompilerInvocation.cpp | 3 +++ lib/IRGen/IRGenModule.cpp | 23 +++++++++++++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index c4a7965e292..82c550a0ca1 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -59,6 +59,10 @@ public: /// The libraries and frameworks specified on the command line. SmallVector LinkLibraries; + /// If non-empty, the (unmangled) name of a dummy symbol to emit that can be + /// used to force-load this module. + std::string ForceLoadSymbolName; + /// The kind of compilation we should do. IRGenOutputKind OutputKind : 3; @@ -87,7 +91,7 @@ public: /// \brief Whether we should omit dynamic safety checks from the emitted IR. unsigned DisableAllRuntimeChecks : 1; - // Disable frame pointer elimination? + /// Disable frame pointer elimination? unsigned DisableFPElim : 1; IRGenOptions() : OutputKind(IRGenOutputKind::LLVMAssembly), Verify(true), diff --git a/include/swift/Driver/Options.td b/include/swift/Driver/Options.td index 62d38255620..d58f6b59186 100644 --- a/include/swift/Driver/Options.td +++ b/include/swift/Driver/Options.td @@ -151,6 +151,9 @@ def module_link_name : Separate<["-"], "module-link-name">, HelpText<"Library to link against when using this module">; def module_link_name_EQ : Joined<["-"], "module-link-name=">, Flags<[FrontendOption]>, Alias; +def autolink_force_load : Flag<["-"], "autolink-force-load">, + Flags<[FrontendOption, HelpHidden]>, + HelpText<"Force ld to link against this module even if no symbols are used">; def emit_module : Flag<["-"], "emit-module">, Flags<[FrontendOption]>, HelpText<"Emit an importable module">; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index d901156ac41..3aa7c799f13 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -263,6 +263,9 @@ Job *Swift::constructJob(const JobAction &JA, std::unique_ptr Inputs, 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/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1c0da9e6551..1ac6d504130 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -858,6 +858,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.EnableDynamicValueTypeLayout = true; } + if (Args.hasArg(OPT_autolink_force_load)) + Opts.ForceLoadSymbolName = Args.getLastArgValue(OPT_module_link_name); + if (const Arg *A = Args.getLastArg(OPT_target)) { Opts.Triple = llvm::Triple::normalize(A->getValue()); } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 5add6f23d7e..bb329ad2086 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -20,6 +20,7 @@ #include "swift/AST/IRGenOptions.h" #include "swift/ClangImporter/ClangImporter.h" #include "clang/AST/ASTContext.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CodeGenABITypes.h" #include "clang/CodeGen/ModuleBuilder.h" @@ -424,6 +425,19 @@ 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"; @@ -437,6 +451,15 @@ void IRGenModule::emitAutolinkInfo() { llvm::LLVMContext &ctx = Module.getContext(); Module.addModuleFlag(llvm::Module::AppendUnique, LinkerOptionsFlagName, llvm::MDNode::get(ctx, AutolinkEntries)); + + if (!Opts.ForceLoadSymbolName.empty()) { + llvm::SmallString<64> buf; + encodeForceLoadSymbolName(buf, Opts.ForceLoadSymbolName); + (void)new llvm::GlobalVariable(Module, Int1Ty, /*constant=*/true, + llvm::GlobalVariable::LinkOnceAnyLinkage, + llvm::Constant::getNullValue(Int1Ty), + buf.str()); + } } void IRGenModule::finalize() {