aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMapping.cpp')
-rw-r--r--llvm/lib/ProfileData/Coverage/CoverageMapping.cpp181
1 files changed, 135 insertions, 46 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 849ee80bfaa3..380a3aef9b14 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -15,7 +15,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallBitVector.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -167,43 +166,115 @@ void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
}
Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
- switch (C.getKind()) {
- case Counter::Zero:
- return 0;
- case Counter::CounterValueReference:
- if (C.getCounterID() >= CounterValues.size())
- return errorCodeToError(errc::argument_out_of_domain);
- return CounterValues[C.getCounterID()];
- case Counter::Expression: {
- if (C.getExpressionID() >= Expressions.size())
- return errorCodeToError(errc::argument_out_of_domain);
- const auto &E = Expressions[C.getExpressionID()];
- Expected<int64_t> LHS = evaluate(E.LHS);
- if (!LHS)
- return LHS;
- Expected<int64_t> RHS = evaluate(E.RHS);
- if (!RHS)
- return RHS;
- return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
- }
+ struct StackElem {
+ Counter ICounter;
+ int64_t LHS = 0;
+ enum {
+ KNeverVisited = 0,
+ KVisitedOnce = 1,
+ KVisitedTwice = 2,
+ } VisitCount = KNeverVisited;
+ };
+
+ std::stack<StackElem> CounterStack;
+ CounterStack.push({C});
+
+ int64_t LastPoppedValue;
+
+ while (!CounterStack.empty()) {
+ StackElem &Current = CounterStack.top();
+
+ switch (Current.ICounter.getKind()) {
+ case Counter::Zero:
+ LastPoppedValue = 0;
+ CounterStack.pop();
+ break;
+ case Counter::CounterValueReference:
+ if (Current.ICounter.getCounterID() >= CounterValues.size())
+ return errorCodeToError(errc::argument_out_of_domain);
+ LastPoppedValue = CounterValues[Current.ICounter.getCounterID()];
+ CounterStack.pop();
+ break;
+ case Counter::Expression: {
+ if (Current.ICounter.getExpressionID() >= Expressions.size())
+ return errorCodeToError(errc::argument_out_of_domain);
+ const auto &E = Expressions[Current.ICounter.getExpressionID()];
+ if (Current.VisitCount == StackElem::KNeverVisited) {
+ CounterStack.push(StackElem{E.LHS});
+ Current.VisitCount = StackElem::KVisitedOnce;
+ } else if (Current.VisitCount == StackElem::KVisitedOnce) {
+ Current.LHS = LastPoppedValue;
+ CounterStack.push(StackElem{E.RHS});
+ Current.VisitCount = StackElem::KVisitedTwice;
+ } else {
+ int64_t LHS = Current.LHS;
+ int64_t RHS = LastPoppedValue;
+ LastPoppedValue =
+ E.Kind == CounterExpression::Subtract ? LHS - RHS : LHS + RHS;
+ CounterStack.pop();
+ }
+ break;
+ }
+ }
}
- llvm_unreachable("Unhandled CounterKind");
+
+ return LastPoppedValue;
}
unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const {
- switch (C.getKind()) {
- case Counter::Zero:
- return 0;
- case Counter::CounterValueReference:
- return C.getCounterID();
- case Counter::Expression: {
- if (C.getExpressionID() >= Expressions.size())
- return 0;
- const auto &E = Expressions[C.getExpressionID()];
- return std::max(getMaxCounterID(E.LHS), getMaxCounterID(E.RHS));
- }
+ struct StackElem {
+ Counter ICounter;
+ int64_t LHS = 0;
+ enum {
+ KNeverVisited = 0,
+ KVisitedOnce = 1,
+ KVisitedTwice = 2,
+ } VisitCount = KNeverVisited;
+ };
+
+ std::stack<StackElem> CounterStack;
+ CounterStack.push({C});
+
+ int64_t LastPoppedValue;
+
+ while (!CounterStack.empty()) {
+ StackElem &Current = CounterStack.top();
+
+ switch (Current.ICounter.getKind()) {
+ case Counter::Zero:
+ LastPoppedValue = 0;
+ CounterStack.pop();
+ break;
+ case Counter::CounterValueReference:
+ LastPoppedValue = Current.ICounter.getCounterID();
+ CounterStack.pop();
+ break;
+ case Counter::Expression: {
+ if (Current.ICounter.getExpressionID() >= Expressions.size()) {
+ LastPoppedValue = 0;
+ CounterStack.pop();
+ } else {
+ const auto &E = Expressions[Current.ICounter.getExpressionID()];
+ if (Current.VisitCount == StackElem::KNeverVisited) {
+ CounterStack.push(StackElem{E.LHS});
+ Current.VisitCount = StackElem::KVisitedOnce;
+ } else if (Current.VisitCount == StackElem::KVisitedOnce) {
+ Current.LHS = LastPoppedValue;
+ CounterStack.push(StackElem{E.RHS});
+ Current.VisitCount = StackElem::KVisitedTwice;
+ } else {
+ int64_t LHS = Current.LHS;
+ int64_t RHS = LastPoppedValue;
+ LastPoppedValue = std::max(LHS, RHS);
+ CounterStack.pop();
+ }
+ }
+ break;
+ }
+ }
}
- llvm_unreachable("Unhandled CounterKind");
+
+ return LastPoppedValue;
}
void FunctionRecordIterator::skipOtherFiles() {
@@ -237,7 +308,8 @@ Error CoverageMapping::loadFunctionRecord(
IndexedInstrProfReader &ProfileReader) {
StringRef OrigFuncName = Record.FunctionName;
if (OrigFuncName.empty())
- return make_error<CoverageMapError>(coveragemap_error::malformed);
+ return make_error<CoverageMapError>(coveragemap_error::malformed,
+ "record function name is empty");
if (Record.Filenames.empty())
OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
@@ -342,7 +414,7 @@ static Error handleMaybeNoDataFoundError(Error E) {
std::move(E), [](const CoverageMapError &CME) {
if (CME.get() == coveragemap_error::no_data_found)
return static_cast<Error>(Error::success());
- return make_error<CoverageMapError>(CME.get());
+ return make_error<CoverageMapError>(CME.get(), CME.getMessage());
});
}
@@ -925,26 +997,43 @@ LineCoverageIterator &LineCoverageIterator::operator++() {
return *this;
}
-static std::string getCoverageMapErrString(coveragemap_error Err) {
+static std::string getCoverageMapErrString(coveragemap_error Err,
+ const std::string &ErrMsg = "") {
+ std::string Msg;
+ raw_string_ostream OS(Msg);
+
switch (Err) {
case coveragemap_error::success:
- return "Success";
+ OS << "success";
+ break;
case coveragemap_error::eof:
- return "End of File";
+ OS << "end of File";
+ break;
case coveragemap_error::no_data_found:
- return "No coverage data found";
+ OS << "no coverage data found";
+ break;
case coveragemap_error::unsupported_version:
- return "Unsupported coverage format version";
+ OS << "unsupported coverage format version";
+ break;
case coveragemap_error::truncated:
- return "Truncated coverage data";
+ OS << "truncated coverage data";
+ break;
case coveragemap_error::malformed:
- return "Malformed coverage data";
+ OS << "malformed coverage data";
+ break;
case coveragemap_error::decompression_failed:
- return "Failed to decompress coverage data (zlib)";
+ OS << "failed to decompress coverage data (zlib)";
+ break;
case coveragemap_error::invalid_or_missing_arch_specifier:
- return "`-arch` specifier is invalid or missing for universal binary";
+ OS << "`-arch` specifier is invalid or missing for universal binary";
+ break;
}
- llvm_unreachable("A value of coveragemap_error has no message.");
+
+ // If optional error message is not empty, append it to the message.
+ if (!ErrMsg.empty())
+ OS << ": " << ErrMsg;
+
+ return Msg;
}
namespace {
@@ -962,7 +1051,7 @@ class CoverageMappingErrorCategoryType : public std::error_category {
} // end anonymous namespace
std::string CoverageMapError::message() const {
- return getCoverageMapErrString(Err);
+ return getCoverageMapErrString(Err, Msg);
}
const std::error_category &llvm::coverage::coveragemap_category() {