From 32c866a8f94ac128425f238c81aa6f3c174ef32f Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Fri, 15 Apr 2016 16:41:35 +1000 Subject: [PATCH] OutfixInfo: use boost::variant for engines --- src/rose/rose_build_add.cpp | 14 ++++-- src/rose/rose_build_bytecode.cpp | 39 +++++++-------- src/rose/rose_build_compile.cpp | 4 +- src/rose/rose_build_impl.h | 82 +++++++++++++++++++++++--------- src/rose/rose_build_merge.cpp | 57 ++++++++++++---------- src/rose/rose_build_misc.cpp | 54 ++++++++++++--------- 6 files changed, 154 insertions(+), 96 deletions(-) diff --git a/src/rose/rose_build_add.cpp b/src/rose/rose_build_add.cpp index 5cf45dcc..f2ef2ca9 100644 --- a/src/rose/rose_build_add.cpp +++ b/src/rose/rose_build_add.cpp @@ -1776,11 +1776,13 @@ bool RoseBuildImpl::addOutfix(const NGHolder &h, const raw_som_dfa &haig) { bool RoseBuildImpl::addOutfix(const raw_puff &rp) { if (!mpv_outfix) { - mpv_outfix = make_unique(); + mpv_outfix = make_unique(MpvProto()); mpv_outfix->chained = true; } - mpv_outfix->mpv.puffettes.push_back(rp); + auto *mpv = mpv_outfix->mpv(); + assert(mpv); + mpv->puffettes.push_back(rp); mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */ mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats)); @@ -1800,11 +1802,13 @@ bool RoseBuildImpl::addOutfix(const raw_puff &rp) { bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out, u32 *event_out) { if (!mpv_outfix) { - mpv_outfix = make_unique(); + mpv_outfix = make_unique(MpvProto()); mpv_outfix->chained = true; } - mpv_outfix->mpv.triggered_puffettes.push_back(rp); + auto *mpv = mpv_outfix->mpv(); + assert(mpv); + mpv->triggered_puffettes.push_back(rp); mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */ mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats)); @@ -1816,7 +1820,7 @@ bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out, * the caller */ *queue_out = mpv_outfix->get_queue(qif); - *event_out = MQE_TOP_FIRST + mpv_outfix->mpv.triggered_puffettes.size() - 1; + *event_out = MQE_TOP_FIRST + mpv->triggered_puffettes.size() - 1; return true; /* failure is not yet an option */ } diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 1cd150c0..6c3b1844 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -1264,14 +1264,14 @@ aligned_unique_ptr buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) { const ReportManager &rm = tbi.rm; aligned_unique_ptr n; - if (outfix.rdfa) { + if (auto *rdfa = outfix.rdfa()) { // Unleash the McClellan! - n = mcclellanCompile(*outfix.rdfa, cc); - } else if (outfix.haig) { + n = mcclellanCompile(*rdfa, cc); + } else if (auto *haig = outfix.haig()) { // Unleash the Goughfish! - n = goughCompile(*outfix.haig, tbi.ssm.somPrecision(), cc); - } else if (outfix.holder) { - NGHolder &h = *outfix.holder; + n = goughCompile(*haig, tbi.ssm.somPrecision(), cc); + } else if (auto *holder = outfix.holder()) { + NGHolder &h = *holder; assert(h.kind == NFA_OUTFIX); // Build NFA. @@ -1294,8 +1294,8 @@ aligned_unique_ptr buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) { } } } - } else if (!outfix.mpv.puffettes.empty()) { - assert(0); + } else if (auto *mpv = outfix.mpv()) { + assert(mpv->puffettes.empty()); } if (n && tbi.cc.grey.reverseAccelerate) { @@ -1310,34 +1310,36 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired, bool *mpv_as_outfix) { assert(bc.engineOffsets.empty()); // MPV should be first *mpv_as_outfix = false; - OutfixInfo *mpv = nullptr; + OutfixInfo *mpv_outfix = nullptr; /* assume outfixes are just above chain tails in queue indices */ for (auto &out : tbi.outfixes) { if (out.is_nonempty_mpv()) { - assert(!mpv); - mpv = &out; + assert(!mpv_outfix); + mpv_outfix = &out; } else { assert(!out.chained); } } - if (!mpv) { + if (!mpv_outfix) { return; } - assert(mpv->chained); - auto nfa = mpvCompile(mpv->mpv.puffettes, mpv->mpv.triggered_puffettes); + assert(mpv_outfix->chained); + auto *mpv = mpv_outfix->mpv(); + auto nfa = mpvCompile(mpv->puffettes, mpv->triggered_puffettes); assert(nfa); if (!nfa) { throw CompileError("Unable to generate bytecode."); } if (tbi.cc.grey.reverseAccelerate) { - buildReverseAcceleration(nfa.get(), mpv->rev_info, mpv->minWidth); + buildReverseAcceleration(nfa.get(), mpv_outfix->rev_info, + mpv_outfix->minWidth); } - u32 qi = mpv->get_queue(tbi.qif); + u32 qi = mpv_outfix->get_queue(tbi.qif); nfa->queueIndex = qi; DEBUG_PRINTF("built mpv\n"); @@ -1347,7 +1349,7 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired, } add_nfa_to_blob(bc, *nfa); - *mpv_as_outfix = !mpv->mpv.puffettes.empty(); + *mpv_as_outfix = !mpv->puffettes.empty(); } static @@ -1387,8 +1389,7 @@ bool prepOutfixes(RoseBuildImpl &tbi, build_context &bc, if (out.chained) { continue; /* already done */ } - DEBUG_PRINTF("building outfix %zd (holder %p rdfa %p)\n", - &out - &tbi.outfixes[0], out.holder.get(), out.rdfa.get()); + DEBUG_PRINTF("building outfix %zd\n", &out - &tbi.outfixes[0]); auto n = buildOutfix(tbi, out); if (!n) { assert(0); diff --git a/src/rose/rose_build_compile.cpp b/src/rose/rose_build_compile.cpp index 477335ca..12500599 100644 --- a/src/rose/rose_build_compile.cpp +++ b/src/rose/rose_build_compile.cpp @@ -1904,8 +1904,8 @@ bool extractSEPLiterals(const OutfixInfo &outfix, const ReportManager &rm, // SEP cases should always become DFAs, so that's the only extract code we // have implemented here. - if (outfix.rdfa) { - return extractSEPLiterals(*outfix.rdfa, lits_out); + if (outfix.rdfa()) { + return extractSEPLiterals(*outfix.rdfa(), lits_out); } DEBUG_PRINTF("cannot extract literals from outfix type\n"); diff --git a/src/rose/rose_build_impl.h b/src/rose/rose_build_impl.h index d2a19f78..4b9f6f10 100644 --- a/src/rose/rose_build_impl.h +++ b/src/rose/rose_build_impl.h @@ -48,6 +48,7 @@ #include #include #include +#include struct RoseEngine; @@ -302,17 +303,11 @@ struct MpvProto { std::vector triggered_puffettes; }; -struct OutfixInfo { /* TODO: poly */ - OutfixInfo() {} - explicit OutfixInfo(std::unique_ptr r) : rdfa(std::move(r)) { - assert(rdfa); - } - explicit OutfixInfo(std::unique_ptr h) : holder(std::move(h)) { - assert(holder); - } - explicit OutfixInfo(std::unique_ptr r) : haig(std::move(r)) { - assert(haig); - } +struct OutfixInfo { + template + explicit OutfixInfo(std::unique_ptr x) : proto(std::move(x)) {} + + explicit OutfixInfo(MpvProto mpv) : proto(std::move(mpv)) {} u32 get_queue(QueueIndexFactory &qif); @@ -322,25 +317,68 @@ struct OutfixInfo { /* TODO: poly */ } bool is_nonempty_mpv() const { - return !mpv.empty(); + auto *mpv = boost::get(&proto); + return mpv && !mpv->empty(); } bool is_dead() const { - return !holder && !rdfa && !haig && mpv.empty(); + auto *mpv = boost::get(&proto); + if (mpv) { + return mpv->empty(); + } + return boost::get(&proto) != nullptr; } void clear() { - holder.reset(); - rdfa.reset(); - haig.reset(); - mpv.reset(); - assert(is_dead()); + proto = boost::blank(); } - std::unique_ptr holder; - std::unique_ptr rdfa; - std::unique_ptr haig; - MpvProto mpv; + // Convenience accessor functions. + + NGHolder *holder() { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + raw_dfa *rdfa() { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + raw_som_dfa *haig() { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + MpvProto *mpv() { + return boost::get(&proto); + } + + // Convenience const accessor functions. + + const NGHolder *holder() const { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + const raw_dfa *rdfa() const { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + const raw_som_dfa *haig() const { + auto *up = boost::get>(&proto); + return up ? up->get() : nullptr; + } + const MpvProto *mpv() const { + return boost::get(&proto); + } + + /** + * \brief Variant wrapping the various engine types. If this is + * boost::blank, it means that this outfix is unused (dead). + */ + boost::variant< + boost::blank, + std::unique_ptr, + std::unique_ptr, + std::unique_ptr, + MpvProto> proto = boost::blank(); RevAccInfo rev_info; u32 maxBAWidth = 0; //!< max bi-anchored width diff --git a/src/rose/rose_build_merge.cpp b/src/rose/rose_build_merge.cpp index fd15e396..664aaef7 100644 --- a/src/rose/rose_build_merge.cpp +++ b/src/rose/rose_build_merge.cpp @@ -2451,8 +2451,9 @@ void mergeOutfixNfas(RoseBuildImpl &tbi, vector &nfas) { map nfa_mapping; for (size_t i = 0; i < outfixes.size(); i++) { - if (outfixes[i].holder) { - nfa_mapping[outfixes[i].holder.get()] = i; + auto *holder = outfixes[i].holder(); + if (holder) { + nfa_mapping[holder] = i; } } @@ -2485,7 +2486,7 @@ struct MergeMcClellan { } static void transfer(OutfixInfo &outfix, unique_ptr d) { - outfix.rdfa = move(d); + outfix.proto = move(d); } private: @@ -2503,7 +2504,7 @@ struct MergeHaig { } static void transfer(OutfixInfo &outfix, unique_ptr d) { - outfix.haig = move(d); + outfix.proto = move(d); } private: @@ -2602,8 +2603,9 @@ void mergeOutfixDfas(RoseBuildImpl &tbi, vector &dfas) { * element addition. */ ue2::unordered_map dfa_mapping; for (size_t i = 0; i < outfixes.size(); i++) { - if (outfixes[i].rdfa) { - dfa_mapping[outfixes[i].rdfa.get()] = i; + auto *rdfa = outfixes[i].rdfa(); + if (rdfa) { + dfa_mapping[rdfa] = i; } } @@ -2624,10 +2626,10 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm, bool seen_dfa = false; u32 nfa_count = 0; for (const auto &outfix : tbi.outfixes) { - if (outfix.holder) { + if (outfix.holder()) { DEBUG_PRINTF("nfa\n"); nfa_count++; - } else if (outfix.rdfa) { + } else if (outfix.rdfa()) { DEBUG_PRINTF("dfa\n"); seen_dfa = true; } @@ -2647,27 +2649,29 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm, vector dfas; for (auto it = tbi.outfixes.begin(); it != tbi.outfixes.end(); ++it) { - assert(!it->is_dead()); - assert(!it->chained); - if (it->rdfa) { - dfas.push_back(it->rdfa.get()); - dfa_mapping[it->rdfa.get()] = it - tbi.outfixes.begin(); + auto &outfix = *it; + assert(!outfix.is_dead()); + assert(!outfix.chained); + + if (outfix.rdfa()) { + auto *rdfa = outfix.rdfa(); + dfas.push_back(rdfa); + dfa_mapping[rdfa] = it - tbi.outfixes.begin(); continue; } - if (!it->holder) { + if (!outfix.holder()) { continue; } - NGHolder *h = it->holder.get(); + NGHolder *h = outfix.holder(); assert(h->kind == NFA_OUTFIX); auto rdfa = buildMcClellan(*h, &rm, grey); if (rdfa) { // Transform this outfix into a DFA and add it to the merge set. dfa_mapping[rdfa.get()] = it - tbi.outfixes.begin(); dfas.push_back(rdfa.get()); - it->clear(); - it->rdfa = move(rdfa); + outfix.proto = move(rdfa); new_dfas++; } } @@ -2695,8 +2699,9 @@ void mergeOutfixHaigs(RoseBuildImpl &tbi, vector &dfas, ue2::unordered_map dfa_mapping; for (size_t i = 0; i < outfixes.size(); i++) { - if (outfixes[i].haig) { - dfa_mapping[outfixes[i].haig.get()] = i; + auto *haig = outfixes[i].haig(); + if (haig) { + dfa_mapping[haig] = i; } } @@ -2721,14 +2726,14 @@ void mergeOutfixes(RoseBuildImpl &tbi) { vector dfas; vector som_dfas; - for (const auto &outfix : tbi.outfixes) { + for (auto &outfix : tbi.outfixes) { assert(!outfix.chained); - if (outfix.rdfa) { - dfas.push_back(outfix.rdfa.get()); - } else if (outfix.holder) { - nfas.push_back(outfix.holder.get()); - } else if (outfix.haig) { - som_dfas.push_back(outfix.haig.get()); + if (outfix.rdfa()) { + dfas.push_back(outfix.rdfa()); + } else if (outfix.holder()) { + nfas.push_back(outfix.holder()); + } else if (outfix.haig()) { + som_dfas.push_back(outfix.haig()); } } diff --git a/src/rose/rose_build_misc.cpp b/src/rose/rose_build_misc.cpp index 2904e4ac..b16e3a69 100644 --- a/src/rose/rose_build_misc.cpp +++ b/src/rose/rose_build_misc.cpp @@ -631,10 +631,11 @@ RoseDedupeAuxImpl::RoseDedupeAuxImpl(const RoseBuildImpl &tbi_in) } if (tbi.mpv_outfix) { - for (const auto &puff : tbi.mpv_outfix->mpv.puffettes) { + auto *mpv = tbi.mpv_outfix->mpv(); + for (const auto &puff : mpv->puffettes) { puff_map[puff.report].insert(&puff); } - for (const auto &puff : tbi.mpv_outfix->mpv.triggered_puffettes) { + for (const auto &puff : mpv->triggered_puffettes) { puff_map[puff.report].insert(&puff); } } @@ -785,12 +786,13 @@ bool RoseDedupeAuxImpl::requiresDedupeSupport( } has_outfix = true; - if (out.haig) { + if (out.haig()) { return true; /* haig may report matches with different SOM at the same offset */ } - if (out.holder && requiresDedupe(*out.holder, reports, tbi.cc.grey)) { + if (out.holder() && + requiresDedupe(*out.holder(), reports, tbi.cc.grey)) { return true; } } @@ -874,25 +876,33 @@ u32 OutfixInfo::get_queue(QueueIndexFactory &qif) { return queue; } +namespace { +class OutfixAllReports : public boost::static_visitor> { +public: + set operator()(const boost::blank &) const { + return {}; + } + + template + set operator()(const unique_ptr &x) const { + return all_reports(*x); + } + + set operator()(const MpvProto &mpv) const { + set reports; + for (const auto &puff : mpv.puffettes) { + reports.insert(puff.report); + } + for (const auto &puff : mpv.triggered_puffettes) { + reports.insert(puff.report); + } + return reports; + } +}; +} + set all_reports(const OutfixInfo &outfix) { - set reports; - if (outfix.holder) { - insert(&reports, all_reports(*outfix.holder)); - } - if (outfix.rdfa) { - insert(&reports, all_reports(*outfix.rdfa)); - } - if (outfix.haig) { - insert(&reports, all_reports(*outfix.haig)); - } - - for (const auto &puff : outfix.mpv.puffettes) { - reports.insert(puff.report); - } - for (const auto &puff : outfix.mpv.triggered_puffettes) { - reports.insert(puff.report); - } - + auto reports = boost::apply_visitor(OutfixAllReports(), outfix.proto); assert(!reports.empty()); return reports; }