Fix the addition of Clang's profile runtime library to the link step
authorChandler Carruth <chandlerc@gmail.com>
Sun, 23 Jun 2013 11:28:48 +0000 (11:28 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 23 Jun 2013 11:28:48 +0000 (11:28 +0000)
when specifying --coverage (or related) flags.

The system for doing this was based on the old LLVM-hosted profile_rt
library, and hadn't been updated for Linux to use the new compiler-rt
library. Also, it couldn't possibly work on multiarch or biarch systems
in many cases. The whole thing now works much the same as the sanitizer
libraries that are built and used out of the compiler-rt repo.

Note that other target OSes haven't been updated because I don't know if
they're doing anything special with the installation path of profile_rt.
I suspect however that *all* of these are wrong and would encourage
maintainers of each target to take a hard look at how compiler-rt
runtime libraries are linked on their platforms.

llvm-svn: 184666

clang/lib/Driver/Tools.cpp
clang/test/Driver/coverage-ld.c [new file with mode: 0644]

index 87071742ba8d800df2cc9248e93daf8f42f382d7..050db6c0b1b36e01ce000a168546a26bc7d2269c 100644 (file)
@@ -1674,6 +1674,24 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, const ArgList &Args)
   }
 }
 
+static void addProfileRTLinux(
+    const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+  if (!(Args.hasArg(options::OPT_fprofile_arcs) ||
+        Args.hasArg(options::OPT_fprofile_generate) ||
+        Args.hasArg(options::OPT_fcreate_profile) ||
+        Args.hasArg(options::OPT_coverage)))
+    return;
+
+  // The profile runtime is located in the Linux library directory and has name
+  // "libclang_rt.profile-<ArchName>.a".
+  SmallString<128> LibProfile(TC.getDriver().ResourceDir);
+  llvm::sys::path::append(
+      LibProfile, "lib", "linux",
+      Twine("libclang_rt.profile-") + TC.getArchName() + ".a");
+
+  CmdArgs.push_back(Args.MakeArgString(LibProfile));
+}
+
 static void addSanitizerRTLinkFlagsLinux(
     const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
     const StringRef Sanitizer, bool BeforeLibStdCXX,
@@ -6244,7 +6262,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
-  addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
+  addProfileRTLinux(getToolChain(), Args, CmdArgs);
 
   C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs));
 }
diff --git a/clang/test/Driver/coverage-ld.c b/clang/test/Driver/coverage-ld.c
new file mode 100644 (file)
index 0000000..2ec0486
--- /dev/null
@@ -0,0 +1,19 @@
+// Test coverage ld flags.
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN:     -target i386-unknown-linux --coverage \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-LINUX-I386 %s
+//
+// CHECK-LINUX-I386: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-LINUX-I386: "{{.*}}/Inputs/resource_dir/lib/linux/libclang_rt.profile-i386.a"
+//
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN:     -target x86_64-unknown-linux --coverage \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-LINUX-X86-64 %s
+//
+// CHECK-LINUX-X86-64: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-LINUX-X86-64: "{{.*}}/Inputs/resource_dir/lib/linux/libclang_rt.profile-x86_64.a"