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 @@ -353,7 +353,8 @@ static void addMemTagOptimizationPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createStackSafetyGlobalInfoWrapperPass(/*SetMetadata=*/true)); + PM.add(createStackSafetyGlobalInfoWrapperPass(/*SetMetadata=*/true, + /*Optional=*/true)); } static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, @@ -1346,7 +1347,7 @@ if (CodeGenOpts.OptimizationLevel > 0 && LangOpts.Sanitize.has(SanitizerKind::MemTag)) { - MPM.addPass(StackSafetyGlobalAnnotatorPass()); + MPM.addPass(StackSafetyGlobalAnnotatorPass(/*Optional=*/true)); } if (CodeGenOpts.OptimizationLevel == 0) { diff --git a/clang/test/Driver/memtag_lto.c b/clang/test/Driver/memtag_lto.c --- a/clang/test/Driver/memtag_lto.c +++ b/clang/test/Driver/memtag_lto.c @@ -75,8 +75,7 @@ // RUN: -r %t.lto1.bc,w, \ // RUN: -r %t.lto2.bc,use,plx \ // RUN: -r %t.lto2.bc,z, -// FIXME: Must be -check-prefixes=XSAFE,YSAFE -// RUN: llvm-dis %t.lto.0.5.precodegen.bc -o - | FileCheck %s -check-prefixes=XUNSAFE,YSAFE +// RUN: llvm-dis %t.lto.0.5.precodegen.bc -o - | FileCheck %s -check-prefixes=XSAFE,YSAFE // Full LTO, new PM: both are safe. // RUN: %clang -fexperimental-new-pass-manager -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=full -o %t.ltonewpm1.bc @@ -88,8 +87,7 @@ // RUN: -r %t.ltonewpm1.bc,w, \ // RUN: -r %t.ltonewpm2.bc,use,plx \ // RUN: -r %t.ltonewpm2.bc,z, -// FIXME: Must be -check-prefixes=XSAFE,YSAFE -// RUN: llvm-dis %t.ltonewpm.0.5.precodegen.bc -o - | FileCheck %s -check-prefixes=XUNSAFE,YSAFE +// RUN: llvm-dis %t.ltonewpm.0.5.precodegen.bc -o - | FileCheck %s -check-prefixes=XSAFE,YSAFE // Thin LTO: both are safe. // RUN: %clang -fno-experimental-new-pass-manager -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=thin -o %t.thinlto1.bc diff --git a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h --- a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h +++ b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h @@ -98,11 +98,16 @@ PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; +// Attaches StackSafety metadata to allocas. class StackSafetyGlobalAnnotatorPass : public PassInfoMixin { + bool Optional = false; + public: - explicit StackSafetyGlobalAnnotatorPass() {} + // When Optional is true the pass does nothing if no consumers of meta + // information is expected. + explicit StackSafetyGlobalAnnotatorPass(bool Optional) : Optional(Optional) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; @@ -111,11 +116,13 @@ class StackSafetyGlobalInfoWrapperPass : public ModulePass { StackSafetyGlobalInfo SSGI; bool SetMetadata; + bool Optional; public: static char ID; - StackSafetyGlobalInfoWrapperPass(bool SetMetadata = false); + explicit StackSafetyGlobalInfoWrapperPass(bool SetMetadata = false, + bool Optional = false); const StackSafetyGlobalInfo &getResult() const { return SSGI; } @@ -125,7 +132,11 @@ bool runOnModule(Module &M) override; }; -ModulePass *createStackSafetyGlobalInfoWrapperPass(bool SetMetadata); +// Attaches StackSafety metadata to allocas. +// When Optional is true the pass does nothing if no consumers of meta +// information is expected. +ModulePass *createStackSafetyGlobalInfoWrapperPass(bool SetMetadata, + bool Optional); } // end namespace llvm diff --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp --- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp +++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp @@ -603,6 +603,13 @@ return Changed; } +bool hasInterestingFunctions(const Module &M) { + for (auto &F : M.functions()) + if (F.hasFnAttribute(Attribute::SanitizeMemTag)) + return true; + return false; +} + } // end anonymous namespace StackSafetyInfo::StackSafetyInfo() = default; @@ -676,6 +683,8 @@ PreservedAnalyses StackSafetyGlobalAnnotatorPass::run(Module &M, ModuleAnalysisManager &AM) { + if (Optional && !hasInterestingFunctions(M)) + return PreservedAnalyses::all(); auto &SSGI = AM.getResult(M); (void)setStackSafetyMetadata(M, SSGI); return PreservedAnalyses::all(); @@ -684,8 +693,8 @@ char StackSafetyGlobalInfoWrapperPass::ID = 0; StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass( - bool SetMetadata) - : ModulePass(ID), SetMetadata(SetMetadata) { + bool SetMetadata, bool Optional) + : ModulePass(ID), SetMetadata(SetMetadata), Optional(Optional) { initializeStackSafetyGlobalInfoWrapperPassPass( *PassRegistry::getPassRegistry()); } @@ -701,6 +710,9 @@ } bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) { + if (Optional && !hasInterestingFunctions(M)) + return false; + StackSafetyDataFlowAnalysis SSDFA( M, [this](Function &F) -> const StackSafetyInfo & { return getAnalysis(F).getResult(); @@ -709,8 +721,9 @@ return SetMetadata ? setStackSafetyMetadata(M, SSGI) : false; } -ModulePass *llvm::createStackSafetyGlobalInfoWrapperPass(bool SetMetadata) { - return new StackSafetyGlobalInfoWrapperPass(SetMetadata); +ModulePass *llvm::createStackSafetyGlobalInfoWrapperPass(bool SetMetadata, + bool Optional) { + return new StackSafetyGlobalInfoWrapperPass(SetMetadata, Optional); } static const char LocalPassArg[] = "stack-safety-local"; 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 @@ -1288,6 +1288,9 @@ // is fixed. MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr)); + // Add stack safety metatada if needed. + MPM.addPass(StackSafetyGlobalAnnotatorPass(true)); + // Stop here at -O1. if (Level == OptimizationLevel::O1) { // The LowerTypeTestsPass needs to run to lower type metadata and the 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 @@ -96,7 +96,7 @@ MODULE_PASS("kasan-module", ModuleAddressSanitizerPass(/*CompileKernel=*/true, false, true, false)) MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass()) MODULE_PASS("poison-checking", PoisonCheckingPass()) -MODULE_PASS("stack-safety-annotator", StackSafetyGlobalAnnotatorPass()) +MODULE_PASS("stack-safety-annotator", StackSafetyGlobalAnnotatorPass(/*Optional=*/false)) #undef MODULE_PASS #ifndef CGSCC_ANALYSIS diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/DataLayout.h" @@ -916,6 +917,10 @@ // Apply whole-program devirtualization and virtual constant propagation. PM.add(createWholeProgramDevirtPass(ExportSummary, nullptr)); + // Add stack safety metatada if needed. + PM.add(createStackSafetyGlobalInfoWrapperPass( + /*SetMetadata=*/true, /*Optional=*/true)); + // That's all we need at opt level 1. if (OptLevel == 1) return;