]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
OutfixInfo: use boost::variant for engines
authorJustin Viiret <justin.viiret@intel.com>
Fri, 15 Apr 2016 06:41:35 +0000 (16:41 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Wed, 20 Apr 2016 03:34:57 +0000 (13:34 +1000)
src/rose/rose_build_add.cpp
src/rose/rose_build_bytecode.cpp
src/rose/rose_build_compile.cpp
src/rose/rose_build_impl.h
src/rose/rose_build_merge.cpp
src/rose/rose_build_misc.cpp

index 5cf45dcce1099e66ff557f75060ceaadd636709a..f2ef2ca9cc05eacde44ed892ed86f1c706ff8c53 100644 (file)
@@ -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<OutfixInfo>();
+        mpv_outfix = make_unique<OutfixInfo>(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<OutfixInfo>();
+        mpv_outfix = make_unique<OutfixInfo>(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 */
 }
index 1cd150c09ca4592140e841cc9c95764d0c74c093..6c3b1844a56cbe4ff0e1297d6d3a4c6b1daa1d5c 100644 (file)
@@ -1264,14 +1264,14 @@ aligned_unique_ptr<NFA> buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) {
     const ReportManager &rm = tbi.rm;
 
     aligned_unique_ptr<NFA> 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<NFA> 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);
index 477335cafd47cb36e7f68d1d89ad3fa8d6f421a3..12500599c17ab56101c7dd9cc72716377a32274d 100644 (file)
@@ -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");
index d2a19f78f9f8a393113537119db005d3644e14a7..4b9f6f103d62bf47629bfbeac46f40fe0a841a97 100644 (file)
@@ -48,6 +48,7 @@
 #include <vector>
 #include <boost/bimap.hpp>
 #include <boost/functional/hash/hash.hpp>
+#include <boost/variant.hpp>
 
 struct RoseEngine;
 
@@ -302,17 +303,11 @@ struct MpvProto {
     std::vector<raw_puff> triggered_puffettes;
 };
 
-struct OutfixInfo { /* TODO: poly */
-    OutfixInfo() {}
-    explicit OutfixInfo(std::unique_ptr<raw_dfa> r) : rdfa(std::move(r)) {
-        assert(rdfa);
-    }
-    explicit OutfixInfo(std::unique_ptr<NGHolder> h) : holder(std::move(h)) {
-        assert(holder);
-    }
-    explicit OutfixInfo(std::unique_ptr<raw_som_dfa> r) : haig(std::move(r)) {
-        assert(haig);
-    }
+struct OutfixInfo {
+    template<class T>
+    explicit OutfixInfo(std::unique_ptr<T> 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<MpvProto>(&proto);
+        return mpv && !mpv->empty();
     }
 
     bool is_dead() const {
-        return !holder && !rdfa && !haig && mpv.empty();
+        auto *mpv = boost::get<MpvProto>(&proto);
+        if (mpv) {
+            return mpv->empty();
+        }
+        return boost::get<boost::blank>(&proto) != nullptr;
     }
 
     void clear() {
-        holder.reset();
-        rdfa.reset();
-        haig.reset();
-        mpv.reset();
-        assert(is_dead());
+        proto = boost::blank();
+    }
+
+    // Convenience accessor functions.
+
+    NGHolder *holder() {
+        auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    raw_dfa *rdfa() {
+        auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    raw_som_dfa *haig() {
+        auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    MpvProto *mpv() {
+        return boost::get<MpvProto>(&proto);
+    }
+
+    // Convenience const accessor functions.
+
+    const NGHolder *holder() const {
+        auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    const raw_dfa *rdfa() const {
+        auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    const raw_som_dfa *haig() const {
+        auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
+        return up ? up->get() : nullptr;
+    }
+    const MpvProto *mpv() const {
+        return boost::get<MpvProto>(&proto);
     }
 
-    std::unique_ptr<NGHolder> holder;
-    std::unique_ptr<raw_dfa> rdfa;
-    std::unique_ptr<raw_som_dfa> haig;
-    MpvProto mpv;
+    /**
+     * \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<NGHolder>,
+        std::unique_ptr<raw_dfa>,
+        std::unique_ptr<raw_som_dfa>,
+        MpvProto> proto = boost::blank();
 
     RevAccInfo rev_info;
     u32 maxBAWidth = 0; //!< max bi-anchored width
index fd15e3963988d5cfe9fc3c7d4a51b512d2312339..664aaef78ab86a38dc50c70350d0a855299fb5f8 100644 (file)
@@ -2451,8 +2451,9 @@ void mergeOutfixNfas(RoseBuildImpl &tbi, vector<NGHolder *> &nfas) {
 
     map<NGHolder *, size_t> 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<raw_dfa> d) {
-        outfix.rdfa = move(d);
+        outfix.proto = move(d);
     }
 
 private:
@@ -2503,7 +2504,7 @@ struct MergeHaig {
     }
 
     static void transfer(OutfixInfo &outfix, unique_ptr<raw_som_dfa> d) {
-        outfix.haig = move(d);
+        outfix.proto = move(d);
     }
 
 private:
@@ -2602,8 +2603,9 @@ void mergeOutfixDfas(RoseBuildImpl &tbi, vector<raw_dfa *> &dfas) {
      * element addition. */
     ue2::unordered_map<raw_dfa *, size_t> 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<raw_dfa *> 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<raw_som_dfa *> &dfas,
 
     ue2::unordered_map<raw_som_dfa *, size_t> 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<raw_dfa *> dfas;
     vector<raw_som_dfa *> 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());
         }
     }
 
index 2904e4acc0f3bb9f278073bd6fe08c5c79b7b8c3..b16e3a69efc818b272da6cef0e1e9098df1a3971 100644 (file)
@@ -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;
 }
 
-set<ReportID> all_reports(const OutfixInfo &outfix) {
-    set<ReportID> 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));
+namespace {
+class OutfixAllReports : public boost::static_visitor<set<ReportID>> {
+public:
+    set<ReportID> operator()(const boost::blank &) const {
+        return {};
     }
 
-    for (const auto &puff : outfix.mpv.puffettes) {
-        reports.insert(puff.report);
+    template<class T>
+    set<ReportID> operator()(const unique_ptr<T> &x) const {
+        return all_reports(*x);
     }
-    for (const auto &puff : outfix.mpv.triggered_puffettes) {
-        reports.insert(puff.report);
+
+    set<ReportID> operator()(const MpvProto &mpv) const {
+        set<ReportID> 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<ReportID> all_reports(const OutfixInfo &outfix) {
+    auto reports = boost::apply_visitor(OutfixAllReports(), outfix.proto);
     assert(!reports.empty());
     return reports;
 }