Skip to content

Commit cf9b272

Browse files
author
George Karpenkov
authored
Merge pull request #10232 from cheshire/sanitizer_driver_detection
Change driver logic for sanitizers support.
2 parents e40f6c2 + 0575326 commit cf9b272

File tree

12 files changed

+115
-49
lines changed

12 files changed

+115
-49
lines changed

include/swift/Driver/ToolChain.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ class ToolChain {
168168

169169
/// Return the default language type to use for the given extension.
170170
virtual types::ID lookupTypeForExtension(StringRef Ext) const;
171+
172+
/// Check whether a clang library with a given name exists.
173+
///
174+
/// \param args Invocation arguments.
175+
/// \param sanitizer Sanitizer name.
176+
virtual bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
177+
StringRef sanitizer) const;
178+
171179
};
172180
} // end namespace driver
173181
} // end namespace swift

include/swift/Option/SanitizerOptions.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#define SWIFT_OPTIONS_SANITIZER_OPTIONS_H
1515

1616
#include "swift/Basic/Sanitizers.h"
17+
#include "llvm/ADT/STLExtras.h"
18+
#include "llvm/ADT/StringRef.h"
1719
#include "llvm/ADT/Triple.h"
1820
#include "llvm/Option/Arg.h"
1921
// FIXME: This include is just for llvm::SanitizerCoverageOptions. We should
@@ -26,10 +28,14 @@ class DiagnosticEngine;
2628
/// \brief Parses a -sanitize= argument's values.
2729
///
2830
/// \param Diag If non null, the argument is used to diagnose invalid values.
31+
/// \param sanitizerRuntimeLibExists Function which checks for existance of a
32+
// sanitizer dylib with a given name.
2933
/// \return Returns a SanitizerKind.
30-
SanitizerKind parseSanitizerArgValues(const llvm::opt::Arg *A,
31-
const llvm::Triple &Triple,
32-
DiagnosticEngine &Diag);
34+
SanitizerKind parseSanitizerArgValues(
35+
const llvm::opt::Arg *A,
36+
const llvm::Triple &Triple,
37+
DiagnosticEngine &Diag,
38+
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists);
3339

3440
/// \brief Parses a -sanitize-coverage= argument's value.
3541
llvm::SanitizerCoverageOptions

lib/Driver/Driver.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,11 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
13171317

13181318
OI.SelectedSanitizer = SanitizerKind::None;
13191319
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ))
1320-
OI.SelectedSanitizer = parseSanitizerArgValues(A, TC.getTriple(), Diags);
1320+
OI.SelectedSanitizer = parseSanitizerArgValues(
1321+
A, TC.getTriple(), Diags,
1322+
[&](StringRef sanitizerName) {
1323+
return TC.sanitizerRuntimeLibExists(Args, sanitizerName);
1324+
});
13211325

13221326
// Check that the sanitizer coverage flags are supported if supplied.
13231327
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ))

lib/Driver/ToolChain.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,11 @@ ToolChain::findProgramRelativeToSwiftImpl(StringRef executableName) const {
149149
types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const {
150150
return types::lookupTypeForExtension(Ext);
151151
}
152+
153+
bool
154+
ToolChain::sanitizerRuntimeLibExists(const ArgList &args,
155+
StringRef sanitizerName) const {
156+
// Assume no sanitizers are supported by default.
157+
// This method should be overriden by a platform-specific subclass.
158+
return false;
159+
}

lib/Driver/ToolChains.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,15 @@ static void getRuntimeLibraryPath(SmallVectorImpl<char> &runtimeLibPath,
965965
getPlatformNameForTriple(TC.getTriple()));
966966
}
967967

968+
static void getClangLibraryPathOnDarwin(SmallVectorImpl<char> &libPath,
969+
const ArgList &args,
970+
const ToolChain &TC) {
971+
getRuntimeLibraryPath(libPath, args, TC);
972+
// Remove platform name.
973+
llvm::sys::path::remove_filename(libPath);
974+
llvm::sys::path::append(libPath, "clang", "lib", "darwin");
975+
}
976+
968977
/// Get the runtime library link path for static linking,
969978
/// which is platform-specific and found relative to the compiler.
970979
static void getRuntimeStaticLibraryPath(SmallVectorImpl<char> &runtimeLibPath,
@@ -1025,16 +1034,31 @@ getDarwinLibraryNameSuffixForTriple(const llvm::Triple &triple) {
10251034
llvm_unreachable("Unsupported Darwin platform");
10261035
}
10271036

1037+
static std::string
1038+
getSanitizerRuntimeLibNameForDarwin(StringRef Sanitizer, const llvm::Triple &Triple) {
1039+
return (Twine("libclang_rt.")
1040+
+ Sanitizer + "_"
1041+
+ getDarwinLibraryNameSuffixForTriple(Triple) + "_dynamic.dylib").str();
1042+
}
1043+
1044+
bool toolchains::Darwin::sanitizerRuntimeLibExists(
1045+
const ArgList &args, StringRef sanitizer) const {
1046+
SmallString<128> sanitizerLibPath;
1047+
getClangLibraryPathOnDarwin(sanitizerLibPath, args, *this);
1048+
llvm::sys::path::append(sanitizerLibPath,
1049+
getSanitizerRuntimeLibNameForDarwin(sanitizer, this->getTriple()));
1050+
return llvm::sys::fs::exists(sanitizerLibPath.str());
1051+
}
1052+
1053+
10281054
static void
10291055
addLinkRuntimeLibForDarwin(const ArgList &Args, ArgStringList &Arguments,
10301056
StringRef DarwinLibName, bool AddRPath,
10311057
const ToolChain &TC) {
1032-
SmallString<128> Dir;
1033-
getRuntimeLibraryPath(Dir, Args, TC);
1034-
// Remove platform name.
1035-
llvm::sys::path::remove_filename(Dir);
1036-
llvm::sys::path::append(Dir, "clang", "lib", "darwin");
1037-
SmallString<128> P(Dir);
1058+
SmallString<128> ClangLibraryPath;
1059+
getClangLibraryPathOnDarwin(ClangLibraryPath, Args, TC);
1060+
1061+
SmallString<128> P(ClangLibraryPath);
10381062
llvm::sys::path::append(P, DarwinLibName);
10391063
Arguments.push_back(Args.MakeArgString(P));
10401064

@@ -1053,7 +1077,7 @@ addLinkRuntimeLibForDarwin(const ArgList &Args, ArgStringList &Arguments,
10531077
// Add the path to the resource dir to rpath to support using the dylib
10541078
// from the default location without copying.
10551079
Arguments.push_back("-rpath");
1056-
Arguments.push_back(Args.MakeArgString(Dir));
1080+
Arguments.push_back(Args.MakeArgString(ClangLibraryPath));
10571081
}
10581082
}
10591083

@@ -1068,10 +1092,8 @@ addLinkSanitizerLibArgsForDarwin(const ArgList &Args,
10681092
Arguments.push_back("-lc++abi");
10691093

10701094
addLinkRuntimeLibForDarwin(Args, Arguments,
1071-
(Twine("libclang_rt.") + Sanitizer + "_" +
1072-
getDarwinLibraryNameSuffixForTriple(TC.getTriple()) +
1073-
"_dynamic.dylib").str(),
1074-
/*AddRPath*/ true, TC);
1095+
getSanitizerRuntimeLibNameForDarwin(Sanitizer, TC.getTriple()),
1096+
/*AddRPath=*/ true, TC);
10751097
}
10761098

10771099
ToolChain::InvocationInfo

lib/Driver/ToolChains.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
3333
public:
3434
Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
3535
~Darwin() = default;
36-
36+
bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
37+
StringRef sanitizerLibName)
38+
const override;
3739
};
3840

3941
class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,14 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
14201420
}
14211421

14221422
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ)) {
1423-
Opts.Sanitize = parseSanitizerArgValues(A, Triple, Diags);
1423+
Opts.Sanitize = parseSanitizerArgValues(
1424+
A, Triple, Diags,
1425+
/* sanitizerRuntimeLibExists= */[](StringRef libName) {
1426+
1427+
// The driver has checked the existence of the library
1428+
// already.
1429+
return true;
1430+
});
14241431
IRGenOpts.Sanitize = Opts.Sanitize;
14251432
}
14261433

lib/Option/SanitizerOptions.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
#include "swift/Basic/Platform.h"
2020
#include "swift/AST/DiagnosticEngine.h"
2121
#include "swift/AST/DiagnosticsFrontend.h"
22+
#include "llvm/ADT/Optional.h"
23+
#include "llvm/ADT/STLExtras.h"
24+
#include "llvm/ADT/StringRef.h"
2225
#include "llvm/ADT/StringSwitch.h"
26+
#include "llvm/ADT/Triple.h"
27+
2328
using namespace swift;
2429

2530
static StringRef toStringRef(const SanitizerKind kind) {
@@ -95,9 +100,17 @@ llvm::SanitizerCoverageOptions swift::parseSanitizerCoverageArgValue(
95100
return opts;
96101
}
97102

103+
static bool isTSanSupported(
104+
const llvm::Triple &Triple,
105+
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
106+
107+
return Triple.isArch64Bit() && sanitizerRuntimeLibExists("tsan");
108+
}
109+
98110
SanitizerKind swift::parseSanitizerArgValues(const llvm::opt::Arg *A,
99-
const llvm::Triple &Triple,
100-
DiagnosticEngine &Diags) {
111+
const llvm::Triple &Triple,
112+
DiagnosticEngine &Diags,
113+
llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
101114
SanitizerKind kind = SanitizerKind::None;
102115

103116
// Find the sanitizer kind.
@@ -137,11 +150,8 @@ SanitizerKind swift::parseSanitizerArgValues(const llvm::opt::Arg *A,
137150
(A->getOption().getPrefixedName() + toStringRef(kind)).toStringRef(b),
138151
Triple.getTriple());
139152
}
140-
// Thread Sanitizer only works on OS X and the simulators. It's only supported
141-
// on 64 bit architectures.
142-
if (kind == SanitizerKind::Thread &&
143-
(!(Triple.isMacOSX() || tripleIsAnySimulator(Triple)) ||
144-
!Triple.isArch64Bit())) {
153+
if (kind == SanitizerKind::Thread
154+
&& !isTSanSupported(Triple, sanitizerRuntimeLibExists)) {
145155
SmallString<128> b;
146156
Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
147157
(A->getOption().getPrefixedName() + toStringRef(kind)).toStringRef(b),

test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_osx_dynamic.dylib

Whitespace-only changes.

test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib

Whitespace-only changes.

0 commit comments

Comments
 (0)