Index: include/clang/Basic/Sanitizers.def =================================================================== --- include/clang/Basic/Sanitizers.def +++ include/clang/Basic/Sanitizers.def @@ -114,6 +114,11 @@ SANITIZER("local-bounds", LocalBounds) SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds) +// EfficiencySanitizer +SANITIZER("efficiency-cache-frag", EfficiencyCacheFrag) +// Meta-group only used internally. +SANITIZER_GROUP("efficiency-all", Efficiency, EfficiencyCacheFrag) + // Magic group, containing all sanitizers. For example, "-fno-sanitize=all" // can be used to disable all the sanitizers. SANITIZER_GROUP("all", All, ~0ULL) Index: include/clang/Driver/SanitizerArgs.h =================================================================== --- include/clang/Driver/SanitizerArgs.h +++ include/clang/Driver/SanitizerArgs.h @@ -58,6 +58,9 @@ bool needsCfiRt() const; bool needsCfiDiagRt() const; bool needsStatsRt() const { return Stats; } + bool needsEsanRt() const { + return Sanitizers.hasOneOf(SanitizerKind::Efficiency); + } bool requiresPIE() const; bool needsUnwindTables() const; Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -248,6 +248,17 @@ PM.add(createDataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles)); } +static void addEfficiencySanitizerPass(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const LangOptions &LangOpts = BuilderWrapper.getLangOpts(); + EfficiencySanitizerOptions Opts; + if (LangOpts.Sanitize.has(SanitizerKind::EfficiencyCacheFrag)) + Opts.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag; + PM.add(createEfficiencySanitizerPass(Opts)); +} + static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple, const CodeGenOptions &CodeGenOpts) { TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple); @@ -407,6 +418,13 @@ addDataFlowSanitizerPass); } + if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) { + PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast, + addEfficiencySanitizerPass); + PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, + addEfficiencySanitizerPass); + } + // Set up the per-function pass manager. legacy::FunctionPassManager *FPM = getPerFunctionPasses(); if (CodeGenOpts.VerifyModule) Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -693,6 +693,10 @@ if (A->getOption().matches(options::OPT_fsanitize_EQ) && 0 == strcmp("all", Value)) Kind = 0; + // Similarly, don't accept -fsanitize=efficiency-all. + else if (A->getOption().matches(options::OPT_fsanitize_EQ) && + 0 == strcmp("efficiency-all", Value)) + Kind = 0; else Kind = parseSanitizerValue(Value, /*AllowGroups=*/true); Index: lib/Driver/ToolChains.cpp =================================================================== --- lib/Driver/ToolChains.cpp +++ lib/Driver/ToolChains.cpp @@ -422,6 +422,8 @@ /*AlwaysLink=*/true); AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); } + if (Sanitize.needsEsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "esan"); // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. @@ -4149,6 +4151,8 @@ Res |= SanitizerKind::Thread; if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64) Res |= SanitizerKind::Memory; + if (IsX86_64) + Res |= SanitizerKind::Efficiency; if (IsX86 || IsX86_64) { Res |= SanitizerKind::Function; } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -3006,6 +3006,8 @@ NonWholeStaticRuntimes.push_back("stats"); RequiredSymbols.push_back("__sanitizer_stats_register"); } + if (SanArgs.needsEsanRt()) + StaticRuntimes.push_back("esan"); } // Should be called before we add system libraries (C++ ABI, libstdc++/libc++, Index: lib/Lex/PPMacroExpansion.cpp =================================================================== --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -1100,6 +1100,8 @@ .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory)) .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread)) .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) + .Case("efficiency_sanitizer", + LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) // Objective-C features .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? .Case("objc_arc", LangOpts.ObjCAutoRefCount)