diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index c0d8d0a7..6eb42d4c 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -4761,27 +4761,57 @@ pair buildLiteralPrograms(RoseBuildImpl &build, build_context &bc) { return {litProgramsOffset, delayRebuildProgramsOffset}; } +/** + * \brief Returns all reports used by output-exposed engines, for which we need + * to generate programs. + */ static -u32 buildReportPrograms(RoseBuildImpl &build, build_context &bc) { - const auto &rm = build.rm; - const u32 numReports = verify_u32(rm.numReports()); - vector programs(numReports); +set findEngineReports(const RoseBuildImpl &build) { + set reports; + + // The small write engine uses these engine report programs. + insert(&reports, build.smwr.all_reports()); + + for (const auto &outfix : build.outfixes) { + insert(&reports, all_reports(outfix)); + } + + const auto &g = build.g; + for (auto v : vertices_range(g)) { + if (g[v].suffix) { + insert(&reports, all_reports(g[v].suffix)); + } + } + + DEBUG_PRINTF("%zu engine reports (of %zu)\n", reports.size(), + build.rm.numReports()); + return reports; +} + +static +pair buildReportPrograms(RoseBuildImpl &build, build_context &bc) { + const auto reports = findEngineReports(build); + vector programs; + programs.reserve(reports.size()); vector program; - for (ReportID id = 0; id < numReports; id++) { + for (ReportID id : reports) { program.clear(); const bool has_som = false; makeCatchupMpv(build, bc, id, program); makeReport(build, id, has_som, program); program = flattenProgram({program}); applyFinalSpecialisation(program); - programs[id] = writeProgram(bc, program); - build.rm.setProgramOffset(id, programs[id]); + u32 offset = writeProgram(bc, program); + programs.push_back(offset); + build.rm.setProgramOffset(id, offset); DEBUG_PRINTF("program for report %u @ %u (%zu instructions)\n", id, programs.back(), program.size()); } - return add_to_engine_blob(bc, begin(programs), end(programs)); + u32 offset = add_to_engine_blob(bc, begin(programs), end(programs)); + u32 count = verify_u32(programs.size()); + return {offset, count}; } static @@ -5174,7 +5204,10 @@ aligned_unique_ptr RoseBuildImpl::buildFinalEngine(u32 minWidth) { auto boundary_out = makeBoundaryPrograms(*this, bc, boundary, dboundary); - u32 reportProgramOffset = buildReportPrograms(*this, bc); + u32 reportProgramOffset; + u32 reportProgramCount; + tie(reportProgramOffset, reportProgramCount) = + buildReportPrograms(*this, bc); // Build NFAs set no_retrigger_queues; @@ -5394,7 +5427,7 @@ aligned_unique_ptr RoseBuildImpl::buildFinalEngine(u32 minWidth) { engine->litProgramOffset = litProgramOffset; engine->litDelayRebuildProgramOffset = litDelayRebuildProgramOffset; engine->reportProgramOffset = reportProgramOffset; - engine->reportProgramCount = verify_u32(rm.reports().size()); + engine->reportProgramCount = reportProgramCount; engine->runtimeImpl = pickRuntimeImpl(*this, bc, outfixEndQueue); engine->mpvTriggeredByLeaf = anyEndfixMpvTriggers(*this); diff --git a/src/rose/rose_internal.h b/src/rose/rose_internal.h index 2b646af0..51913984 100644 --- a/src/rose/rose_internal.h +++ b/src/rose/rose_internal.h @@ -347,10 +347,15 @@ struct RoseEngine { * literals. */ u32 litDelayRebuildProgramOffset; - /** \brief Offset of u32 array of program offsets for internal reports. */ + /** + * \brief Offset of u32 array of program offsets for reports used by + * output-exposed engines. + */ u32 reportProgramOffset; - /** \brief Number of programs for internal reports. */ + /** + * \brief Number of programs for reports used by output-exposed engines. + */ u32 reportProgramCount; /** diff --git a/src/smallwrite/smallwrite_build.cpp b/src/smallwrite/smallwrite_build.cpp index 7fb54440..1cffe514 100644 --- a/src/smallwrite/smallwrite_build.cpp +++ b/src/smallwrite/smallwrite_build.cpp @@ -74,6 +74,8 @@ public: void add(const NGWrapper &w) override; void add(const ue2_literal &literal, ReportID r) override; + set all_reports() const override; + bool determiniseLiterals(); const ReportManager &rm; @@ -413,6 +415,20 @@ SmallWriteBuildImpl::build(u32 roseQuality) { return smwr; } +set SmallWriteBuildImpl::all_reports() const { + set reports; + if (poisoned) { + return reports; + } + if (rdfa) { + insert(&reports, ::ue2::all_reports(*rdfa)); + } + for (const auto &cand : cand_literals) { + reports.insert(cand.second); + } + return reports; +} + size_t smwrSize(const SmallWriteEngine *smwr) { assert(smwr); return smwr->size; diff --git a/src/smallwrite/smallwrite_build.h b/src/smallwrite/smallwrite_build.h index 59a8528a..84c6df3a 100644 --- a/src/smallwrite/smallwrite_build.h +++ b/src/smallwrite/smallwrite_build.h @@ -38,6 +38,8 @@ #include "ue2common.h" #include "util/alloc.h" +#include + #include struct SmallWriteEngine; @@ -61,6 +63,8 @@ public: virtual void add(const NGWrapper &w) = 0; virtual void add(const ue2_literal &literal, ReportID r) = 0; + + virtual std::set all_reports() const = 0; }; // Construct a usable SmallWrite builder.