Index: lib/Driver/ToolChains/Darwin.h =================================================================== --- lib/Driver/ToolChains/Darwin.h +++ lib/Driver/ToolChains/Darwin.h @@ -152,8 +152,12 @@ llvm::opt::ArgStringList &CmdArgs) const {} /// Add the linker arguments to link the compiler runtime library. + /// + /// FIXME: This API is intended for use with embedded libraries only, and is + /// misleadingly named. virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + virtual void AddFuzzerLinkArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; @@ -171,10 +175,26 @@ /// Is the target either iOS or an iOS simulator? bool isTargetIOSBased() const { return false; } + /// Options to control how a runtime library is linked. + enum RuntimeLinkOptions : unsigned { + // Link the library in even if it can't be found in the VFS. + RLO_AlwaysLink = 1 << 0, + + // Use the embedded runtime from the macho_embedded directory. + RLO_IsEmbedded = 1 << 1, + + // Emit rpaths for @executable_path as well as the resource directory. + RLO_AddRPath = 1 << 2, + + //< Link the library in before any others. + RLO_FirstLink = 1 << 3, + }; + + /// Add a runtime library to the list of items to link. void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, - StringRef DarwinLibName, bool AlwaysLink = false, - bool IsEmbedded = false, bool AddRPath = false) const; + StringRef DarwinLibName, + RuntimeLinkOptions Opts = RuntimeLinkOptions()) const; /// Add any profiling runtime libraries that are needed. This is essentially a /// MachO specific version of addProfileRT in Tools.cpp. Index: lib/Driver/ToolChains/Darwin.cpp =================================================================== --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -493,7 +493,7 @@ if (getToolChain().getSanitizerArgs().needsSafeStackRt()) { getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.safestack_osx.a", - /*AlwaysLink=*/true); + toolchains::Darwin::RLO_AlwaysLink); } Args.AddAllArgs(CmdArgs, options::OPT_L); @@ -897,10 +897,11 @@ } void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, - StringRef DarwinLibName, bool AlwaysLink, - bool IsEmbedded, bool AddRPath) const { + StringRef DarwinLibName, + RuntimeLinkOptions Opts) const { SmallString<128> Dir(getDriver().ResourceDir); - llvm::sys::path::append(Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin"); + llvm::sys::path::append( + Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin"); SmallString<128> P(Dir); llvm::sys::path::append(P, DarwinLibName); @@ -908,14 +909,19 @@ // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build (unless // we explicitly force linking with this library). - if (AlwaysLink || getVFS().exists(P)) - CmdArgs.push_back(Args.MakeArgString(P)); + if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) { + const char *LibArg = Args.MakeArgString(P); + if (Opts & RLO_FirstLink) + CmdArgs.insert(CmdArgs.begin(), LibArg); + else + CmdArgs.push_back(LibArg); + } // Adding the rpaths might negatively interact when other rpaths are involved, // so we should make sure we add the rpaths last, after all user-specified // rpaths. This is currently true from this place, but we need to be // careful if this function is ever called before user's rpaths are emitted. - if (AddRPath) { + if (Opts & RLO_AddRPath) { assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library"); // Add @executable_path to rpath to support having the dylib copied with @@ -996,20 +1002,20 @@ ArgStringList &CmdArgs) const { if (!needsProfileRT(Args)) return; - AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.profile_") + - getOSLibraryNameSuffix() + ".a").str(), - /*AlwaysLink*/ true); + AddLinkRuntimeLib( + Args, CmdArgs, + (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(), + RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink)); } void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer) const { - AddLinkRuntimeLib( - Args, CmdArgs, - (Twine("libclang_rt.") + Sanitizer + "_" + - getOSLibraryNameSuffix() + "_dynamic.dylib").str(), - /*AlwaysLink*/ true, /*IsEmbedded*/ false, - /*AddRPath*/ true); + AddLinkRuntimeLib(Args, CmdArgs, + (Twine("libclang_rt.") + Sanitizer + "_" + + getOSLibraryNameSuffix() + "_dynamic.dylib") + .str(), + RuntimeLinkOptions(RLO_AlwaysLink | RLO_AddRPath)); } ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( @@ -1059,7 +1065,7 @@ StringRef OS = isTargetMacOS() ? "osx" : "iossim"; AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.stats_client_") + OS + ".a").str(), - /*AlwaysLink=*/true); + RLO_AlwaysLink); AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); } if (Sanitize.needsEsanRt()) @@ -1709,7 +1715,7 @@ : "soft"; CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a"; - AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true); + AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded); } bool Darwin::isAlignedAllocationUnavailable() const { Index: test/Driver/darwin-ld.c =================================================================== --- test/Driver/darwin-ld.c +++ test/Driver/darwin-ld.c @@ -341,3 +341,13 @@ // RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -fprofile-instr-use=blah -### -o foo/bar.out 2> %t.log // RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS %s < %t.log // PASS_REMARKS_WITH_HOTNESS: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness" + +// RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log +// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log +// RUN: %clang -target i386-apple-darwin9 -fprofile-instr-generate -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log +// RUN: %clang -target arm64-apple-ios5.0 -miphoneos-version-min=5.0 -fprofile-instr-generate -### %t.o 2> %t.log +// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log +// LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a"