Skip to content

Commit 3761174

Browse files
ro-iaadeshps-mcw
authored andcommitted
[AMDGPU][clang] Fix clang driver check for multiple sanitizer arguments (llvm#166851)
`-fsanitize=address,fuzzer` should be rejected like `-fsanitize=fuzzer,address`. The address sanitizer enables the device sanitizer pipeline. The fuzzer implicitly turns on LLVMs SanitizerCoverage, which the driver then forwards to the device cc1. SanitizerCoverage is not supported on amdgcn.
1 parent 3553833 commit 3761174

File tree

8 files changed

+254
-56
lines changed

8 files changed

+254
-56
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,23 @@ def err_drv_bad_offload_arch_combo : Error<
126126
"invalid offload arch combinations: '%0' and '%1' (for a specific processor, "
127127
"a feature should either exist in all offload archs, or not exist in any "
128128
"offload archs)">;
129+
def err_drv_unsupported_option_for_offload_arch_req_feature : Error<
130+
"'%0' option for offload arch '%1' is not currently supported "
131+
"there. Use it with an offload arch containing '%2' instead">;
129132
def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
130133
"ignoring '%0' option for offload arch '%1' as it is not currently supported "
131134
"there. Use it with an offload arch containing '%2' instead">,
132135
InGroup<OptionIgnored>;
133136
def warn_drv_unsupported_option_for_target : Warning<
134137
"ignoring '%0' option as it is not currently supported for target '%1'">,
135138
InGroup<OptionIgnored>;
139+
def err_drv_unsupported_option_for_target : Error<
140+
"'%0' option is not currently supported for target '%1'">;
141+
def warn_drv_unsupported_option_part_for_target : Warning<
142+
"ignoring '%0' in '%1' option as it is not currently supported for target '%2'">,
143+
InGroup<OptionIgnored>;
144+
def err_drv_unsupported_option_part_for_target : Error<
145+
"'%0' in '%1' option is not currently supported for target '%2'">;
136146
def warn_drv_invalid_argument_for_flang : Warning<
137147
"'%0' is not valid for Fortran">,
138148
InGroup<OptionIgnored>;

clang/include/clang/Options/Options.td

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ def hlsl_Group : OptionGroup<"<HLSL group>">, Group<f_Group>,
201201
DocName<"HLSL options">,
202202
Visibility<[ClangOption]>;
203203

204+
def fsan_cov_Group : OptionGroup<"<-fsanitize-coverage group>">,
205+
Group<f_clang_Group>,
206+
DocName<"Sanitizer Coverage options">;
207+
204208
// Feature groups - these take command line options that correspond directly to
205209
// target specific features and can be translated directly from command line
206210
// options.
@@ -2407,26 +2411,26 @@ def : Flag<["-"], "fno-sanitize-blacklist">,
24072411
Group<f_clang_Group>, Flags<[HelpHidden]>, Alias<fno_sanitize_ignorelist>;
24082412

24092413
def fsanitize_coverage : CommaJoined<["-"], "fsanitize-coverage=">,
2410-
Group<f_clang_Group>,
2414+
Group<fsan_cov_Group>,
24112415
HelpText<"Specify the type of coverage instrumentation for Sanitizers">;
24122416
def fno_sanitize_coverage : CommaJoined<["-"], "fno-sanitize-coverage=">,
2413-
Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
2417+
Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
24142418
HelpText<"Disable features of coverage instrumentation for Sanitizers">,
24152419
Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,"
24162420
"8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters,"
24172421
"inline-bool-flag">;
24182422
def fsanitize_coverage_allowlist : Joined<["-"], "fsanitize-coverage-allowlist=">,
2419-
Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
2423+
Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
24202424
HelpText<"Restrict sanitizer coverage instrumentation exclusively to modules and functions that match the provided special case list, except the blocked ones">,
24212425
MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageAllowlistFiles">>;
24222426
def fsanitize_coverage_ignorelist : Joined<["-"], "fsanitize-coverage-ignorelist=">,
2423-
Group<f_clang_Group>, Visibility<[ClangOption, CLOption]>,
2427+
Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
24242428
HelpText<"Disable sanitizer coverage instrumentation for modules and functions "
24252429
"that match the provided special case list, even the allowed ones">,
24262430
MarshallingInfoStringVector<CodeGenOpts<"SanitizeCoverageIgnorelistFiles">>;
24272431
def fsanitize_coverage_stack_depth_callback_min_EQ
24282432
: Joined<["-"], "fsanitize-coverage-stack-depth-callback-min=">,
2429-
Group<f_clang_Group>,
2433+
Group<fsan_cov_Group>,
24302434
MetaVarName<"<M>">,
24312435
HelpText<"Use callback for max stack depth tracing with minimum stack "
24322436
"depth M">,
@@ -7901,70 +7905,87 @@ def linker_option : Joined<["--"], "linker-option=">,
79017905
HelpText<"Add linker option">,
79027906
MarshallingInfoStringVector<CodeGenOpts<"LinkerOptions">>;
79037907
def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">,
7908+
Group<fsan_cov_Group>,
79047909
HelpText<"Sanitizer coverage type">,
79057910
MarshallingInfoInt<CodeGenOpts<"SanitizeCoverageType">>;
79067911
def fsanitize_coverage_indirect_calls
79077912
: Flag<["-"], "fsanitize-coverage-indirect-calls">,
7913+
Group<fsan_cov_Group>,
79087914
HelpText<"Enable sanitizer coverage for indirect calls">,
79097915
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageIndirectCalls">>;
79107916
def fsanitize_coverage_trace_bb
79117917
: Flag<["-"], "fsanitize-coverage-trace-bb">,
7918+
Group<fsan_cov_Group>,
79127919
HelpText<"Enable basic block tracing in sanitizer coverage">,
79137920
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceBB">>;
79147921
def fsanitize_coverage_trace_cmp
79157922
: Flag<["-"], "fsanitize-coverage-trace-cmp">,
7923+
Group<fsan_cov_Group>,
79167924
HelpText<"Enable cmp instruction tracing in sanitizer coverage">,
79177925
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceCmp">>;
79187926
def fsanitize_coverage_trace_div
79197927
: Flag<["-"], "fsanitize-coverage-trace-div">,
7928+
Group<fsan_cov_Group>,
79207929
HelpText<"Enable div instruction tracing in sanitizer coverage">,
79217930
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceDiv">>;
79227931
def fsanitize_coverage_trace_gep
79237932
: Flag<["-"], "fsanitize-coverage-trace-gep">,
7933+
Group<fsan_cov_Group>,
79247934
HelpText<"Enable gep instruction tracing in sanitizer coverage">,
79257935
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceGep">>;
79267936
def fsanitize_coverage_8bit_counters
79277937
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
7938+
Group<fsan_cov_Group>,
79287939
HelpText<"Enable frequency counters in sanitizer coverage">,
79297940
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverage8bitCounters">>;
79307941
def fsanitize_coverage_inline_8bit_counters
79317942
: Flag<["-"], "fsanitize-coverage-inline-8bit-counters">,
7943+
Group<fsan_cov_Group>,
79327944
HelpText<"Enable inline 8-bit counters in sanitizer coverage">,
79337945
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageInline8bitCounters">>;
79347946
def fsanitize_coverage_inline_bool_flag
79357947
: Flag<["-"], "fsanitize-coverage-inline-bool-flag">,
7948+
Group<fsan_cov_Group>,
79367949
HelpText<"Enable inline bool flag in sanitizer coverage">,
79377950
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageInlineBoolFlag">>;
79387951
def fsanitize_coverage_pc_table
79397952
: Flag<["-"], "fsanitize-coverage-pc-table">,
7953+
Group<fsan_cov_Group>,
79407954
HelpText<"Create a table of coverage-instrumented PCs">,
79417955
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoveragePCTable">>;
79427956
def fsanitize_coverage_control_flow
79437957
: Flag<["-"], "fsanitize-coverage-control-flow">,
7958+
Group<fsan_cov_Group>,
79447959
HelpText<"Collect control flow of function">,
79457960
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageControlFlow">>;
79467961
def fsanitize_coverage_trace_pc
79477962
: Flag<["-"], "fsanitize-coverage-trace-pc">,
7963+
Group<fsan_cov_Group>,
79487964
HelpText<"Enable PC tracing in sanitizer coverage">,
79497965
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePC">>;
79507966
def fsanitize_coverage_trace_pc_guard
79517967
: Flag<["-"], "fsanitize-coverage-trace-pc-guard">,
7968+
Group<fsan_cov_Group>,
79527969
HelpText<"Enable PC tracing with guard in sanitizer coverage">,
79537970
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePCGuard">>;
79547971
def fsanitize_coverage_no_prune
79557972
: Flag<["-"], "fsanitize-coverage-no-prune">,
7973+
Group<fsan_cov_Group>,
79567974
HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">,
79577975
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageNoPrune">>;
79587976
def fsanitize_coverage_stack_depth
79597977
: Flag<["-"], "fsanitize-coverage-stack-depth">,
7978+
Group<fsan_cov_Group>,
79607979
HelpText<"Enable max stack depth tracing">,
79617980
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageStackDepth">>;
79627981
def fsanitize_coverage_trace_loads
79637982
: Flag<["-"], "fsanitize-coverage-trace-loads">,
7983+
Group<fsan_cov_Group>,
79647984
HelpText<"Enable tracing of loads">,
79657985
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceLoads">>;
79667986
def fsanitize_coverage_trace_stores
79677987
: Flag<["-"], "fsanitize-coverage-trace-stores">,
7988+
Group<fsan_cov_Group>,
79687989
HelpText<"Enable tracing of stores">,
79697990
MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTraceStores">>;
79707991
def fexperimental_sanitize_metadata_EQ_covered

clang/lib/Driver/ToolChains/AMDGPU.cpp

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,24 +1074,9 @@ ROCMToolChain::getCommonDeviceLibNames(
10741074
bool AMDGPUToolChain::shouldSkipSanitizeOption(
10751075
const ToolChain &TC, const llvm::opt::ArgList &DriverArgs,
10761076
StringRef TargetID, const llvm::opt::Arg *A) const {
1077-
// For actions without targetID, do nothing.
1078-
if (TargetID.empty())
1079-
return false;
1080-
Option O = A->getOption();
1081-
1082-
if (!O.matches(options::OPT_fsanitize_EQ))
1083-
return false;
1084-
1085-
if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
1086-
options::OPT_fno_gpu_sanitize, true))
1087-
return true;
1088-
10891077
auto &Diags = TC.getDriver().getDiags();
1090-
1091-
// For simplicity, we only allow -fsanitize=address
1092-
SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
1093-
if (K != SanitizerKind::Address)
1094-
return true;
1078+
bool IsExplicitDevice =
1079+
A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
10951080

10961081
// Check 'xnack+' availability by default
10971082
llvm::StringRef Processor =
@@ -1112,10 +1097,17 @@ bool AMDGPUToolChain::shouldSkipSanitizeOption(
11121097
(void)OptionalGpuArch;
11131098
auto Loc = FeatureMap.find("xnack");
11141099
if (Loc == FeatureMap.end() || !Loc->second) {
1115-
Diags.Report(
1116-
clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
1117-
<< A->getAsString(DriverArgs) << TargetID << "xnack+";
1100+
if (IsExplicitDevice) {
1101+
Diags.Report(
1102+
clang::diag::err_drv_unsupported_option_for_offload_arch_req_feature)
1103+
<< A->getAsString(DriverArgs) << TargetID << "xnack+";
1104+
} else {
1105+
Diags.Report(
1106+
clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
1107+
<< A->getAsString(DriverArgs) << TargetID << "xnack+";
1108+
}
11181109
return true;
11191110
}
1111+
11201112
return false;
11211113
}

clang/lib/Driver/ToolChains/AMDGPU.h

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
101101
/// Needed for translating LTO options.
102102
const char *getDefaultLinker() const override { return "ld.lld"; }
103103

104-
/// Should skip sanitize options.
104+
/// Should skip sanitize option.
105105
bool shouldSkipSanitizeOption(const ToolChain &TC,
106106
const llvm::opt::ArgList &DriverArgs,
107107
StringRef TargetID,
@@ -155,18 +155,79 @@ class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
155155
return SanitizerKind::Address;
156156
}
157157

158-
void diagnoseUnsupportedSanitizers(const llvm::opt::ArgList &Args) const {
159-
if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
160-
true))
161-
return;
158+
bool diagnoseUnsupportedOption(const llvm::opt::Arg *A,
159+
const llvm::opt::DerivedArgList &DAL,
160+
const llvm::opt::ArgList &DriverArgs,
161+
const char *Value = nullptr) const {
162162
auto &Diags = getDriver().getDiags();
163-
for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
164-
SanitizerMask K =
165-
parseSanitizerValue(A->getValue(), /*Allow Groups*/ false);
166-
if (K != SanitizerKind::Address)
167-
Diags.Report(clang::diag::warn_drv_unsupported_option_for_target)
168-
<< A->getAsString(Args) << getTriple().str();
163+
bool IsExplicitDevice =
164+
A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
165+
166+
if (Value) {
167+
unsigned DiagID =
168+
IsExplicitDevice
169+
? clang::diag::err_drv_unsupported_option_part_for_target
170+
: clang::diag::warn_drv_unsupported_option_part_for_target;
171+
Diags.Report(DiagID) << Value << A->getAsString(DriverArgs)
172+
<< getTriple().str();
173+
} else {
174+
unsigned DiagID =
175+
IsExplicitDevice
176+
? clang::diag::err_drv_unsupported_option_for_target
177+
: clang::diag::warn_drv_unsupported_option_for_target;
178+
Diags.Report(DiagID) << A->getAsString(DAL) << getTriple().str();
169179
}
180+
return true;
181+
}
182+
183+
bool handleSanitizeOption(const ToolChain &TC, llvm::opt::DerivedArgList &DAL,
184+
const llvm::opt::ArgList &DriverArgs,
185+
StringRef TargetID, const llvm::opt::Arg *A) const {
186+
if (TargetID.empty())
187+
return false;
188+
// If we shouldn't do sanitizing, skip it.
189+
if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
190+
options::OPT_fno_gpu_sanitize, true))
191+
return true;
192+
const llvm::opt::Option &Opt = A->getOption();
193+
// Sanitizer coverage is currently not supported for AMDGPU, so warn/error
194+
// on every related option.
195+
if (Opt.matches(options::OPT_fsan_cov_Group)) {
196+
diagnoseUnsupportedOption(A, DAL, DriverArgs);
197+
}
198+
// If this isn't a sanitizer option, don't handle it.
199+
if (!Opt.matches(options::OPT_fsanitize_EQ))
200+
return false;
201+
202+
SmallVector<const char *, 4> SupportedSanitizers;
203+
SmallVector<const char *, 4> UnSupportedSanitizers;
204+
205+
for (const char *Value : A->getValues()) {
206+
SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ false);
207+
if (K & ROCMToolChain::getSupportedSanitizers())
208+
SupportedSanitizers.push_back(Value);
209+
else
210+
UnSupportedSanitizers.push_back(Value);
211+
}
212+
213+
// If there are no supported sanitizers, drop the whole argument.
214+
if (SupportedSanitizers.empty()) {
215+
diagnoseUnsupportedOption(A, DAL, DriverArgs);
216+
return true;
217+
}
218+
// If only some sanitizers are unsupported, report each one individually.
219+
if (!UnSupportedSanitizers.empty()) {
220+
for (const char *Value : UnSupportedSanitizers) {
221+
diagnoseUnsupportedOption(A, DAL, DriverArgs, Value);
222+
}
223+
}
224+
// If we know the target arch, check if the sanitizer is supported for it.
225+
if (shouldSkipSanitizeOption(TC, DriverArgs, TargetID, A))
226+
return true;
227+
228+
// Add a new argument with only the supported sanitizers.
229+
DAL.AddJoinedArg(A, A->getOption(), llvm::join(SupportedSanitizers, ","));
230+
return true;
170231
}
171232
};
172233

clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D,
2828
// Lookup binaries into the driver directory, this is used to
2929
// discover the 'amdgpu-arch' executable.
3030
getProgramPaths().push_back(getDriver().Dir);
31-
// Diagnose unsupported sanitizer options only once.
32-
diagnoseUnsupportedSanitizers(Args);
3331
}
3432

3533
void AMDGPUOpenMPToolChain::addClangTargetOptions(
@@ -66,16 +64,11 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
6664

6765
const OptTable &Opts = getDriver().getOpts();
6866

69-
// Skip sanitize options passed from the HostTC. Claim them early.
70-
// The decision to sanitize device code is computed only by
71-
// 'shouldSkipSanitizeOption'.
72-
if (DAL->hasArg(options::OPT_fsanitize_EQ))
73-
DAL->claimAllArgs(options::OPT_fsanitize_EQ);
74-
75-
for (Arg *A : Args)
76-
if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A) &&
77-
!llvm::is_contained(*DAL, A))
67+
for (Arg *A : Args) {
68+
// Filter unsupported sanitizers passed from the HostTC.
69+
if (!handleSanitizeOption(*this, *DAL, Args, BoundArch, A))
7870
DAL->append(A);
71+
}
7972

8073
if (!BoundArch.empty()) {
8174
DAL->eraseArg(options::OPT_march_EQ);
@@ -115,9 +108,8 @@ void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
115108
SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
116109
// The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
117110
// allows sanitizer arguments on the command line if they are supported by the
118-
// host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
119-
// line arguments for any of these "supported" sanitizers. That means that no
120-
// sanitization of device code is actually supported at this time.
111+
// host toolchain. The AMDGPUOpenMPToolChain will later filter unsupported
112+
// sanitizers from the command line arguments.
121113
//
122114
// This behavior is necessary because the host and device toolchains
123115
// invocations often share the command line, so the device toolchain must

clang/lib/Driver/ToolChains/HIPAMD.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,6 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
219219
// Lookup binaries into the driver directory, this is used to
220220
// discover the clang-offload-bundler executable.
221221
getProgramPaths().push_back(getDriver().Dir);
222-
// Diagnose unsupported sanitizer options only once.
223-
diagnoseUnsupportedSanitizers(Args);
224222
}
225223

226224
void HIPAMDToolChain::addClangTargetOptions(
@@ -292,7 +290,8 @@ HIPAMDToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
292290
const OptTable &Opts = getDriver().getOpts();
293291

294292
for (Arg *A : Args) {
295-
if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A))
293+
// Filter unsupported sanitizers passed from the HostTC.
294+
if (!handleSanitizeOption(*this, *DAL, Args, BoundArch, A))
296295
DAL->append(A);
297296
}
298297

@@ -348,9 +347,8 @@ void HIPAMDToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
348347
SanitizerMask HIPAMDToolChain::getSupportedSanitizers() const {
349348
// The HIPAMDToolChain only supports sanitizers in the sense that it allows
350349
// sanitizer arguments on the command line if they are supported by the host
351-
// toolchain. The HIPAMDToolChain will actually ignore any command line
352-
// arguments for any of these "supported" sanitizers. That means that no
353-
// sanitization of device code is actually supported at this time.
350+
// toolchain. The HIPAMDToolChain will later filter unsupported sanitizers
351+
// from the command line arguments.
354352
//
355353
// This behavior is necessary because the host and device toolchains
356354
// invocations often share the command line, so the device toolchain must

0 commit comments

Comments
 (0)