summaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp1
-rw-r--r--clang/lib/Basic/CMakeLists.txt1
-rw-r--r--clang/lib/Basic/ProfileList.cpp113
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp28
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h4
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp8
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp4
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());