diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
| commit | b1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch) | |
| tree | 7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | |
| parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) | |
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMapping.cpp')
| -rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 181 |
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() { |
