rose: add CLEAR_WORK_DONE instruction

Preparatory work for allowing fragments to be shared between literals
that squash groups and those that don't.
This commit is contained in:
Justin Viiret 2017-03-29 13:06:26 +11:00 committed by Matthew Barr
parent 803f61d818
commit 18f843bcc1
6 changed files with 45 additions and 1 deletions

View File

@ -2166,6 +2166,12 @@ hwlmcb_rv_t roseRunProgram_i(const struct RoseEngine *t,
}
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(CLEAR_WORK_DONE) {
DEBUG_PRINTF("clear work_done flag\n");
work_done = 0;
}
PROGRAM_NEXT_INSTRUCTION
}
}

View File

@ -4517,6 +4517,18 @@ u32 writeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
bool is_anchored_program) {
assert(!lit_ids.empty());
// If we have multiple literals and any of them squash groups, we will have
// to add a CLEAR_WORK_DONE instruction to each literal program block to
// clear the work_done flags so that it's only set if a state has been
// switched on for that literal.
// Note that we add it to every lit program, as they may be
// reordered/uniquified by assembleProgramBlocks() above.
const bool needs_clear_work = lit_ids.size() > 1 &&
any_of_in(lit_ids, [&](u32 lit_id) {
return build.literal_info.at(lit_id).squash_group;
});
vector<RoseProgram> blocks;
const vector<RoseEdge> no_edges;
@ -4531,6 +4543,11 @@ u32 writeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
}
auto prog = buildLiteralProgram(build, bc, prog_build, lit_id,
*edges_ptr, is_anchored_program);
if (needs_clear_work) {
RoseProgram clear_block;
clear_block.add_before_end(make_unique<RoseInstrClearWorkDone>());
prog.add_block(move(clear_block));
}
blocks.push_back(move(prog));
}

View File

@ -1100,6 +1100,9 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(CLEAR_WORK_DONE) {}
PROGRAM_NEXT_INSTRUCTION
default:
os << " UNKNOWN (code " << int{code} << ")" << endl;
os << " <stopping>" << endl;

View File

@ -48,6 +48,7 @@ RoseInstrSomZero::~RoseInstrSomZero() = default;
RoseInstrSuffixesEod::~RoseInstrSuffixesEod() = default;
RoseInstrMatcherEod::~RoseInstrMatcherEod() = default;
RoseInstrEnd::~RoseInstrEnd() = default;
RoseInstrClearWorkDone::~RoseInstrClearWorkDone() = default;
using OffsetMap = RoseInstruction::OffsetMap;

View File

@ -1851,6 +1851,14 @@ public:
}
};
class RoseInstrClearWorkDone
: public RoseInstrBaseTrivial<ROSE_INSTR_CLEAR_WORK_DONE,
ROSE_STRUCT_CLEAR_WORK_DONE,
RoseInstrClearWorkDone> {
public:
~RoseInstrClearWorkDone() override;
};
class RoseInstrEnd
: public RoseInstrBaseTrivial<ROSE_INSTR_END, ROSE_STRUCT_END,
RoseInstrEnd> {

View File

@ -141,7 +141,12 @@ enum RoseInstructionCode {
*/
ROSE_INSTR_CHECK_MED_LIT_NOCASE,
LAST_ROSE_INSTRUCTION = ROSE_INSTR_CHECK_MED_LIT_NOCASE //!< Sentinel.
/**
* \brief Clear the "work done" flag used by the SQUASH_GROUPS instruction.
*/
ROSE_INSTR_CLEAR_WORK_DONE,
LAST_ROSE_INSTRUCTION = ROSE_INSTR_CLEAR_WORK_DONE //!< Sentinel.
};
struct ROSE_STRUCT_END {
@ -517,4 +522,8 @@ struct ROSE_STRUCT_CHECK_MED_LIT_NOCASE {
u32 fail_jump; //!< Jump forward this many bytes on failure.
};
struct ROSE_STRUCT_CLEAR_WORK_DONE {
u8 code; //!< From enum RoseInstructionCode.
};
#endif // ROSE_ROSE_PROGRAM_H