diff options
author | shen3qing1 <145069838+shen3qing1@users.noreply.github.com> | 2023-10-02 13:40:43 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-02 13:40:43 -0700 |
commit | 3f417a7096ce2a4e886c020329eb68df01ce3389 (patch) | |
tree | 1258b2aa40672b4044100402fff66bdc638bdbcd /llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | |
parent | d0d608383e76ea8931860fb12af7005ab69230cb (diff) | |
download | llvm-3f417a7096ce2a4e886c020329eb68df01ce3389.zip llvm-3f417a7096ce2a4e886c020329eb68df01ce3389.tar.gz llvm-3f417a7096ce2a4e886c020329eb68df01ce3389.tar.bz2 |
[NFC] [Coverage] Do not use recursion for getMaxCounterID (#67870)
This causes stack overflows for real-world coverage reports.
Tested with build/bin/llvm-lit -a llvm/test/tools/llvm-cov
Co-authored-by: Qing Shen <qingshen@google.com>
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMapping.cpp')
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index e46b735..2a4ed54 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -223,19 +223,59 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { } 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() { |