diff --git a/src/rose/eod.c b/src/rose/eod.c index 4961a728..30b8db0e 100644 --- a/src/rose/eod.c +++ b/src/rose/eod.c @@ -210,16 +210,6 @@ void roseEodExec_i(const struct RoseEngine *t, u64a offset, return; } - if (!t->eodIterProgramOffset && !t->ematcherOffset) { - DEBUG_PRINTF("no eod accepts\n"); - return; - } - - // Handle pending EOD reports. - if (roseEodRunIterator(t, offset, scratch) == MO_HALT_MATCHING) { - return; - } - // Run the EOD anchored matcher if there is one. if (t->ematcherOffset) { assert(t->ematcherRegionSize); diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 904f8df9..1c8e8cd0 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -4005,6 +4005,11 @@ pair buildEodAnchorProgram(RoseBuildImpl &build, build_context &bc) { for (const auto &e : in_edges_range(v, g)) { RoseVertex u = source(e, g); + if (!build.isInETable(u)) { + DEBUG_PRINTF("pred %zu is not in etable\n", g[u].idx); + continue; + } + if (canEagerlyReportAtEod(build, e)) { DEBUG_PRINTF("already done report for vertex %zu\n", g[u].idx); continue; @@ -4034,6 +4039,57 @@ pair buildEodAnchorProgram(RoseBuildImpl &build, build_context &bc) { return {writeProgram(bc, program), iter_offset}; } +static +void addGeneralEodAnchorProgram(RoseBuildImpl &build, build_context &bc, + vector &program) { + const RoseGraph &g = build.g; + + // pred state id -> list of programs + map>> predProgramLists; + + for (auto v : vertices_range(g)) { + if (!g[v].eod_accept) { + continue; + } + + DEBUG_PRINTF("vertex %zu (with %zu preds) fires on EOD\n", g[v].idx, + in_degree(v, g)); + + for (const auto &e : in_edges_range(v, g)) { + RoseVertex u = source(e, g); + + if (build.isInETable(u)) { + DEBUG_PRINTF("pred %zu is in etable\n", g[u].idx); + continue; + } + + if (canEagerlyReportAtEod(build, e)) { + DEBUG_PRINTF("already done report for vertex %zu\n", g[u].idx); + continue; + } + + assert(contains(bc.roleStateIndices, u)); + u32 predStateIdx = bc.roleStateIndices.at(u); + + auto program = makeEodAnchorProgram(build, bc, e); + predProgramLists[predStateIdx].push_back(program); + } + } + + if (predProgramLists.empty()) { + DEBUG_PRINTF("no eod anchored roles\n"); + return; + } + + if (!program.empty()) { + assert(program.back().code() == ROSE_INSTR_END); + program.pop_back(); + } + // TODO: don't force sparse iter, be more careful with generating + // CHECK_NOT_HANDLED. + addPredBlocks(bc, predProgramLists, program, true); +} + static u32 writeEodProgram(RoseBuildImpl &build, build_context &bc, u32 eodNfaIterOffset) { @@ -4076,6 +4132,8 @@ u32 writeEodProgram(RoseBuildImpl &build, build_context &bc, program = flattenProgram({program}); } + addGeneralEodAnchorProgram(build, bc, program); + if (program.empty()) { return 0; }