diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3623,6 +3623,7 @@ def single__module : Flag<["-"], "single_module">; def specs_EQ : Joined<["-", "--"], "specs=">, Group; def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>; +def experimental_link_llvmlibc : Flag<["-"], "experimental-link-llvmlibc">; def static_libgcc : Flag<["-"], "static-libgcc">; def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static : Flag<["-", "--"], "static">, Group, Flags<[NoArgumentUnused]>; diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -670,6 +670,23 @@ Args.AddAllArgs(CmdArgs, options::OPT_T); + if (Args.hasArg(options::OPT_experimental_link_llvmlibc)) { + // We should add -lllvmlibc after all other link args have been accumulated. + // This way, we can iterate over all the link args and add -lllvmlibc before + // each libc library. This will also ensure that we prepend -lllvmlibc + // before any used listed -lm options. + ArgStringList WithLLVMLibc; + for (StringRef Arg : CmdArgs) { + if (Arg == "-lm" || Arg == "-lc") { + // TODO: Add -lllvmlibc before -lpthread when LLVM libc has pthread + // functions available. + WithLLVMLibc.push_back("-lllvmlibc"); + } + WithLLVMLibc.push_back(Arg.data()); + } + CmdArgs = WithLLVMLibc; + } + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -232,7 +232,27 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-NOPIE %s // CHECK-CLANG-LD-STATIC-PIE-NOPIE: error: cannot specify 'nopie' along with 'static-pie' -// + +// RUN: %clang -experimental-link-llvmlibc -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=platform \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-LINK-LLVMLIBC %s +// CHECK-CLANG-LD-LINK-LLVMLIBC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-CLANG-LD-LINK-LLVMLIBC: "-m" "elf_x86_64" +// CHECK-CLANG-LD-LINK-LLVMLIBC: "-lllvmlibc" "-lc" + +// RUN: %clang -experimental-link-llvmlibc -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=platform \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: -lm \ +// RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-LINK-LLVMLIBC-LM %s +// CHECK-CLANG-LD-LINK-LLVMLIBC-LM: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-CLANG-LD-LINK-LLVMLIBC-LM: "-m" "elf_x86_64" +// CHECK-CLANG-LD-LINK-LLVMLIBC-LM: "-lllvmlibc" "-lm" +// CHECK-CLANG-LD-LINK-LLVMLIBC-LM: "-lllvmlibc" "-lc" + // RUN: %clang -dynamic -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform \ // RUN: --gcc-toolchain="" \