diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Basic/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | clang/lib/Basic/ProfileList.cpp | 113 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 28 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 4 |
10 files changed, 168 insertions, 1 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 44545f00b146..cb7f00abf9e9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -965,6 +965,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, LangOpts.XRayNeverInstrumentFiles, LangOpts.XRayAttrListFiles, SM)), + ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index b1c5003e172a..e5319484393a 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -59,6 +59,7 @@ add_clang_library(clangBasic OpenCLOptions.cpp OpenMPKinds.cpp OperatorPrecedence.cpp + ProfileList.cpp SanitizerBlacklist.cpp SanitizerSpecialCaseList.cpp Sanitizers.cpp diff --git a/clang/lib/Basic/ProfileList.cpp b/clang/lib/Basic/ProfileList.cpp new file mode 100644 index 000000000000..56bc37a79301 --- /dev/null +++ b/clang/lib/Basic/ProfileList.cpp @@ -0,0 +1,113 @@ +//===--- ProfileList.h - ProfileList filter ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// User-provided filters include/exclude profile instrumentation in certain +// functions or files. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/ProfileList.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/SpecialCaseList.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +namespace clang { + +class ProfileSpecialCaseList : public llvm::SpecialCaseList { +public: + static std::unique_ptr<ProfileSpecialCaseList> + create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &VFS, + std::string &Error); + + static std::unique_ptr<ProfileSpecialCaseList> + createOrDie(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS); + + bool isEmpty() const { return Sections.empty(); } + + bool hasPrefix(StringRef Prefix) const { + for (auto &SectionIter : Sections) + if (SectionIter.Entries.count(Prefix) > 0) + return true; + return false; + } +}; + +std::unique_ptr<ProfileSpecialCaseList> +ProfileSpecialCaseList::create(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS, + std::string &Error) { + auto PSCL = std::make_unique<ProfileSpecialCaseList>(); + if (PSCL->createInternal(Paths, VFS, Error)) + return PSCL; + return nullptr; +} + +std::unique_ptr<ProfileSpecialCaseList> +ProfileSpecialCaseList::createOrDie(const std::vector<std::string> &Paths, + llvm::vfs::FileSystem &VFS) { + std::string Error; + if (auto PSCL = create(Paths, VFS, Error)) + return PSCL; + llvm::report_fatal_error(Error); +} + +} + +ProfileList::ProfileList(ArrayRef<std::string> Paths, SourceManager &SM) + : SCL(ProfileSpecialCaseList::createOrDie( + Paths, SM.getFileManager().getVirtualFileSystem())), + Empty(SCL->isEmpty()), + Default(SCL->hasPrefix("fun") || SCL->hasPrefix("src")), SM(SM) {} + +ProfileList::~ProfileList() = default; + +static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { + switch (Kind) { + case CodeGenOptions::ProfileNone: + return ""; + case CodeGenOptions::ProfileClangInstr: + return "clang"; + case CodeGenOptions::ProfileIRInstr: + return "llvm"; + case CodeGenOptions::ProfileCSIRInstr: + return "csllvm"; + } +} + +llvm::Optional<bool> +ProfileList::isFunctionExcluded(StringRef FunctionName, + CodeGenOptions::ProfileInstrKind Kind) const { + StringRef Section = getSectionName(Kind); + if (SCL->inSection(Section, "!fun", FunctionName)) + return true; + if (SCL->inSection(Section, "fun", FunctionName)) + return false; + return None; +} + +llvm::Optional<bool> +ProfileList::isLocationExcluded(SourceLocation Loc, + CodeGenOptions::ProfileInstrKind Kind) const { + return isFileExcluded(SM.getFilename(SM.getFileLoc(Loc)), Kind); +} + +llvm::Optional<bool> +ProfileList::isFileExcluded(StringRef FileName, + CodeGenOptions::ProfileInstrKind Kind) const { + StringRef Section = getSectionName(Kind); + if (SCL->inSection(Section, "!src", FileName)) + return true; + if (SCL->inSection(Section, "src", FileName)) + return false; + return None; +} diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2c302ae48d61..b393c88f7751 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -839,6 +839,10 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } } + if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone) + if (CGM.isProfileInstrExcluded(Fn, Loc)) + Fn->addFnAttr(llvm::Attribute::NoProfile); + unsigned Count, Offset; if (const auto *Attr = D ? D->getAttr<PatchableFunctionEntryAttr>() : nullptr) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9d11466f69ce..8eb7adbc8fcb 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1442,7 +1442,8 @@ public: /// Increment the profiler's counter for the given statement by \p StepV. /// If \p StepV is null, the default increment is 1. void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) { - if (CGM.getCodeGenOpts().hasProfileClangInstr()) + if (CGM.getCodeGenOpts().hasProfileClangInstr() && + !CurFn->hasFnAttribute(llvm::Attribute::NoProfile)) PGO.emitCounterIncrement(Builder, S, StepV); PGO.setCurrentStmt(S); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d93c9690cfb2..31afbc6b4262 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2563,6 +2563,34 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, return true; } +bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn, + SourceLocation Loc) const { + const auto &ProfileList = getContext().getProfileList(); + // If the profile list is empty, then instrument everything. + if (ProfileList.isEmpty()) + return false; + CodeGenOptions::ProfileInstrKind Kind = getCodeGenOpts().getProfileInstr(); + // First, check the function name. + Optional<bool> V = ProfileList.isFunctionExcluded(Fn->getName(), Kind); + if (V.hasValue()) + return *V; + // Next, check the source location. + if (Loc.isValid()) { + Optional<bool> V = ProfileList.isLocationExcluded(Loc, Kind); + if (V.hasValue()) + return *V; + } + // If location is unknown, this may be a compiler-generated function. Assume + // it's located in the main file. + auto &SM = Context.getSourceManager(); + if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { + Optional<bool> V = ProfileList.isFileExcluded(MainFile->getName(), Kind); + if (V.hasValue()) + return *V; + } + return ProfileList.getDefault(); +} + bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) { // Never defer when EmitAllDecls is specified. if (LangOpts.EmitAllDecls) diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c59570598b0d..618e2f857b07 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1277,6 +1277,10 @@ public: bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, StringRef Category = StringRef()) const; + /// Returns true if function at the given location should be excluded from + /// profile instrumentation. + bool isProfileInstrExcluded(llvm::Function *Fn, SourceLocation Loc) const; + SanitizerMetadata *getSanitizerMetadata() { return SanitizerMD.get(); } diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 052d58a04a14..08ae87785065 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -811,6 +811,9 @@ void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) return; + if (Fn->hasFnAttribute(llvm::Attribute::NoProfile)) + return; + CGM.ClearUnusedCoverageMapping(D); setFuncName(Fn); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a1f0e2cb9b29..fdb8a58cd1b3 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5531,6 +5531,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const XRayArgs &XRay = TC.getXRayArgs(); XRay.addArgs(TC, Args, CmdArgs, InputType); + for (const auto &Filename : + Args.getAllArgValues(options::OPT_fprofile_list_EQ)) { + if (D.getVFS().exists(Filename)) + CmdArgs.push_back(Args.MakeArgString("-fprofile-list=" + Filename)); + else + D.Diag(clang::diag::err_drv_no_such_file) << Filename; + } + if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) { StringRef S0 = A->getValue(), S = S0; unsigned Size, Offset = 0; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f7f36d04f33f..d8be4ea14868 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1358,6 +1358,10 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, } } + // -fprofile-list= dependencies. + for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ)) + Opts.ExtraDeps.push_back(Filename); + // Propagate the extra dependencies. for (const auto *A : Args.filtered(OPT_fdepfile_entry)) { Opts.ExtraDeps.push_back(A->getValue()); |
