diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1161,7 +1161,7 @@ CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator, DestructorKind)); MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( - CompileKernel, Recover, UseAfterScope, UseAfterReturn))); + {CompileKernel, Recover, UseAfterScope, UseAfterReturn}))); } }; ASanPass(SanitizerKind::Address, false); @@ -1171,8 +1171,8 @@ if (LangOpts.Sanitize.has(Mask)) { bool Recover = CodeGenOpts.SanitizeRecover.has(Mask); MPM.addPass(HWAddressSanitizerPass( - CompileKernel, Recover, - /*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0)); + {CompileKernel, Recover, + /*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0})); } }; HWASanPass(SanitizerKind::HWAddress, false); diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h @@ -89,6 +89,20 @@ static AnalysisKey Key; }; +struct AddressSanitizerOptions { + AddressSanitizerOptions() + : AddressSanitizerOptions(false, false, false, + AsanDetectStackUseAfterReturnMode::Runtime){}; + AddressSanitizerOptions(bool CompileKernel, bool Recover, bool UseAfterScope, + AsanDetectStackUseAfterReturnMode UseAfterReturn) + : CompileKernel(CompileKernel), Recover(Recover), + UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn){}; + bool CompileKernel; + bool Recover; + bool UseAfterScope; + AsanDetectStackUseAfterReturnMode UseAfterReturn; +}; + /// Public interface to the address sanitizer pass for instrumenting code to /// check for various memory errors at runtime. /// @@ -98,19 +112,13 @@ /// surrounding requested memory to be checked for invalid accesses. class AddressSanitizerPass : public PassInfoMixin { public: - explicit AddressSanitizerPass( - bool CompileKernel = false, bool Recover = false, - bool UseAfterScope = false, - AsanDetectStackUseAfterReturnMode UseAfterReturn = - AsanDetectStackUseAfterReturnMode::Runtime); + explicit AddressSanitizerPass(AddressSanitizerOptions Options) + : Options(Options){}; PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); static bool isRequired() { return true; } private: - bool CompileKernel; - bool Recover; - bool UseAfterScope; - AsanDetectStackUseAfterReturnMode UseAfterReturn; + AddressSanitizerOptions Options; }; /// Public interface to the address sanitizer module pass for instrumenting code diff --git a/llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h --- a/llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h +++ b/llvm/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h @@ -18,21 +18,30 @@ namespace llvm { +struct HWAddressSanitizerOptions { + HWAddressSanitizerOptions() + : HWAddressSanitizerOptions(false, false, false){}; + HWAddressSanitizerOptions(bool CompileKernel, bool Recover, + bool DisableOptimization) + : CompileKernel(CompileKernel), Recover(Recover), + DisableOptimization(DisableOptimization){}; + bool CompileKernel; + bool Recover; + bool DisableOptimization; +}; + /// This is a public interface to the hardware address sanitizer pass for /// instrumenting code to check for various memory errors at runtime, similar to /// AddressSanitizer but based on partial hardware assistance. class HWAddressSanitizerPass : public PassInfoMixin { public: - explicit HWAddressSanitizerPass(bool CompileKernel = false, - bool Recover = false, - bool DisableOptimization = false); + explicit HWAddressSanitizerPass(HWAddressSanitizerOptions Options) + : Options(Options){}; PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); static bool isRequired() { return true; } private: - bool CompileKernel; - bool Recover; - bool DisableOptimization; + HWAddressSanitizerOptions Options; }; FunctionPass * diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -453,6 +453,8 @@ if (PIC && shouldPopulateClassToPassNames()) { #define MODULE_PASS(NAME, CREATE_PASS) \ PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + PIC->addClassToPassName(CLASS, NAME); #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); #define FUNCTION_PASS(NAME, CREATE_PASS) \ @@ -2137,6 +2139,44 @@ return UnrollOpts; } +Expected parseASanPassOptions(StringRef Params) { + AddressSanitizerOptions Result; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName == "kernel") { + Result.CompileKernel = true; + } else { + return make_error( + formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName) + .str(), + inconvertibleErrorCode()); + } + } + return Result; +} + +Expected parseHWASanPassOptions(StringRef Params) { + HWAddressSanitizerOptions Result; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); + + if (ParamName == "recover") { + Result.Recover = true; + } else if (ParamName == "kernel") { + Result.CompileKernel = true; + } else { + return make_error( + formatv("invalid HWAddressSanitizer pass parameter '{0}' ", ParamName) + .str(), + inconvertibleErrorCode()); + } + } + return Result; +} + Expected parseMSanPassOptions(StringRef Params) { MemorySanitizerOptions Result; while (!Params.empty()) { @@ -2356,6 +2396,9 @@ #define MODULE_PASS(NAME, CREATE_PASS) \ if (Name == NAME) \ return true; +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + if (checkParametrizedPassName(Name, NAME)) \ + return true; #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ return true; @@ -2600,6 +2643,14 @@ MPM.addPass(CREATE_PASS); \ return Error::success(); \ } +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass(CREATE_PASS(Params.get())); \ + return Error::success(); \ + } #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ MPM.addPass( \ @@ -3176,6 +3227,11 @@ #define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS); #include "PassRegistry.def" + OS << "Module passes with params:\n"; +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + printPassName(NAME, PARAMS, OS); +#include "PassRegistry.def" + OS << "Module analyses:\n"; #define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS); #include "PassRegistry.def" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -60,8 +60,6 @@ MODULE_PASS("globalopt", GlobalOptPass()) MODULE_PASS("globalsplit", GlobalSplitPass()) MODULE_PASS("hotcoldsplit", HotColdSplittingPass()) -MODULE_PASS("hwasan", HWAddressSanitizerPass(false, false)) -MODULE_PASS("khwasan", HWAddressSanitizerPass(true, true)) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) MODULE_PASS("inliner-wrapper", ModuleInlinerWrapperPass()) MODULE_PASS("inliner-wrapper-no-mandatory-first", ModuleInlinerWrapperPass( @@ -123,6 +121,18 @@ MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass()) #undef MODULE_PASS +#ifndef MODULE_PASS_WITH_PARAMS +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) +#endif +MODULE_PASS_WITH_PARAMS("hwasan", + "HWAddressSanitizerPass", + [](HWAddressSanitizerOptions Opts) { + return HWAddressSanitizerPass(Opts); + }, + parseHWASanPassOptions, + "kernel;recover") +#undef MODULE_PASS_WITH_PARAMS + #ifndef CGSCC_ANALYSIS #define CGSCC_ANALYSIS(NAME, CREATE_PASS) #endif @@ -322,10 +332,7 @@ FUNCTION_PASS("view-cfg", CFGViewerPass()) FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass()) -FUNCTION_PASS("asan", AddressSanitizerPass(false, false, false)) -FUNCTION_PASS("kasan", AddressSanitizerPass(true, false, false)) FUNCTION_PASS("msan", MemorySanitizerPass({})) -FUNCTION_PASS("kmsan", MemorySanitizerPass({0, false, /*Kernel=*/true})) FUNCTION_PASS("tsan", ThreadSanitizerPass()) FUNCTION_PASS("memprof", MemProfilerPass()) #undef FUNCTION_PASS @@ -345,6 +352,13 @@ "no-profile-peeling;profile-peeling;" "no-runtime;runtime;" "no-upperbound;upperbound") +FUNCTION_PASS_WITH_PARAMS("asan", + "AddressSanitizerPass", + [](AddressSanitizerOptions Opts) { + return AddressSanitizerPass(Opts); + }, + parseASanPassOptions, + "kernel") FUNCTION_PASS_WITH_PARAMS("msan", "MemorySanitizerPass", [](MemorySanitizerOptions Opts) { diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1212,20 +1212,14 @@ return GlobalsMetadata(M); } -AddressSanitizerPass::AddressSanitizerPass( - bool CompileKernel, bool Recover, bool UseAfterScope, - AsanDetectStackUseAfterReturnMode UseAfterReturn) - : CompileKernel(CompileKernel), Recover(Recover), - UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) {} - PreservedAnalyses AddressSanitizerPass::run(Function &F, AnalysisManager &AM) { auto &MAMProxy = AM.getResult(F); Module &M = *F.getParent(); if (auto *R = MAMProxy.getCachedResult(M)) { const TargetLibraryInfo *TLI = &AM.getResult(F); - AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope, - UseAfterReturn); + AddressSanitizer Sanitizer(M, R, Options.CompileKernel, Options.Recover, + Options.UseAfterScope, Options.UseAfterReturn); if (Sanitizer.instrumentFunction(F, TLI)) return PreservedAnalyses::none(); return PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -471,19 +471,14 @@ DisableOptimization); } -HWAddressSanitizerPass::HWAddressSanitizerPass(bool CompileKernel, bool Recover, - bool DisableOptimization) - : CompileKernel(CompileKernel), Recover(Recover), - DisableOptimization(DisableOptimization) {} - PreservedAnalyses HWAddressSanitizerPass::run(Module &M, ModuleAnalysisManager &MAM) { const StackSafetyGlobalInfo *SSI = nullptr; auto TargetTriple = llvm::Triple(M.getTargetTriple()); - if (shouldUseStackSafetyAnalysis(TargetTriple, DisableOptimization)) + if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization)) SSI = &MAM.getResult(M); - HWAddressSanitizer HWASan(M, CompileKernel, Recover, SSI); + HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI); bool Modified = false; auto &FAM = MAM.getResult(M).getManager(); for (Function &F : M) { diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -339,18 +339,19 @@ PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager &MPM, ArrayRef) { + AddressSanitizerOptions Opts; if (Name == "asan-pipeline") { MPM.addPass( RequireAnalysisPass()); MPM.addPass( - createModuleToFunctionPassAdaptor(AddressSanitizerPass())); + createModuleToFunctionPassAdaptor(AddressSanitizerPass(Opts))); MPM.addPass(ModuleAddressSanitizerPass()); return true; } else if (Name == "asan-function-pipeline") { MPM.addPass( RequireAnalysisPass()); MPM.addPass( - createModuleToFunctionPassAdaptor(AddressSanitizerPass())); + createModuleToFunctionPassAdaptor(AddressSanitizerPass(Opts))); return true; } return false;