ZAM control-flow tracking now explicitly includes the ends of loops

This commit is contained in:
Vern Paxson 2024-09-11 16:41:24 +02:00 committed by Christian Kreibich
parent b0e21b7e64
commit 56d01ea83b
4 changed files with 24 additions and 5 deletions

View file

@ -1031,6 +1031,23 @@ void ZAMCompiler::KillInst(zeek_uint_t i) {
insts1[j]->aux->cft[CFT_BLOCK_END] += be_cnt; insts1[j]->aux->cft[CFT_BLOCK_END] += be_cnt;
} }
if ( cft.count(CFT_LOOP_END) > 0 ) {
// Propagate block-ends backwards.
int j = i;
while ( --j >= 0 )
if ( insts1[j]->live )
break;
ASSERT(j >= 0);
// Make sure the CFT entry is created.
AddCFT(insts1[j], CFT_LOOP_END);
auto le_cnt = cft[CFT_LOOP_END];
--le_cnt; // we already did one above
insts1[j]->aux->cft[CFT_LOOP_END] += le_cnt;
}
// If's can be killed because their bodies become empty, // If's can be killed because their bodies become empty,
// break's because they just lead to their following instruction, // break's because they just lead to their following instruction,
// and next's if they become dead code. // and next's if they become dead code.

View file

@ -35,7 +35,7 @@ void ZAMCompiler::AddCFT(ZInstI* inst, ControlFlowType cft) {
if ( cft_entry == inst->aux->cft.end() ) if ( cft_entry == inst->aux->cft.end() )
inst->aux->cft[cft] = 1; inst->aux->cft[cft] = 1;
else { else {
ASSERT(cft == CFT_BLOCK_END || cft == CFT_BREAK); ASSERT(cft == CFT_BLOCK_END || cft == CFT_LOOP_END || cft == CFT_BREAK);
++cft_entry->second; ++cft_entry->second;
} }
} }

View file

@ -650,7 +650,7 @@ const ZAMStmt ZAMCompiler::While(const Stmt* cond_stmt, const Expr* cond, const
if ( body && body->Tag() != STMT_NULL ) if ( body && body->Tag() != STMT_NULL )
(void)CompileStmt(body); (void)CompileStmt(body);
AddCFT(insts1.back(), CFT_BLOCK_END); AddCFT(insts1.back(), CFT_LOOP_END);
auto tail = GoTo(GoToTarget(head)); auto tail = GoTo(GoToTarget(head));
@ -849,7 +849,7 @@ const ZAMStmt ZAMCompiler::Loop(const Stmt* body) {
auto b = CompileStmt(body); auto b = CompileStmt(body);
AddCFT(insts1[head.stmt_num], CFT_LOOP); AddCFT(insts1[head.stmt_num], CFT_LOOP);
AddCFT(insts1[b.stmt_num], CFT_BLOCK_END); AddCFT(insts1[b.stmt_num], CFT_LOOP_END);
auto tail = GoTo(GoToTarget(head)); auto tail = GoTo(GoToTarget(head));
@ -863,14 +863,15 @@ const ZAMStmt ZAMCompiler::FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt
bool is_table) { bool is_table) {
auto loop_iter = AddInst(iter_stmt); auto loop_iter = AddInst(iter_stmt);
auto body_end = CompileStmt(body); auto body_end = CompileStmt(body);
AddCFT(insts1[body_end.stmt_num], CFT_BLOCK_END);
auto loop_end = GoTo(GoToTarget(iter_head));
AddCFT(insts1[loop_end.stmt_num], CFT_LOOP_END);
// We only need cleanup for looping over tables, but for now we // We only need cleanup for looping over tables, but for now we
// need some sort of placeholder instruction (until the optimizer // need some sort of placeholder instruction (until the optimizer
// can elide it) to resolve loop exits. // can elide it) to resolve loop exits.
ZOp op = is_table ? OP_END_TABLE_LOOP_f : OP_NOP; ZOp op = is_table ? OP_END_TABLE_LOOP_f : OP_NOP;
auto loop_end = GoTo(GoToTarget(iter_head));
auto z = ZInstI(op, iter_slot); auto z = ZInstI(op, iter_slot);
z.op_type = is_table ? OP_V_I1 : OP_X; z.op_type = is_table ? OP_V_I1 : OP_X;
auto final_stmt = AddInst(z); auto final_stmt = AddInst(z);

View file

@ -390,6 +390,7 @@ enum ControlFlowType {
CFT_ELSE, CFT_ELSE,
CFT_LOOP, CFT_LOOP,
CFT_LOOP_COND, CFT_LOOP_COND,
CFT_LOOP_END,
CFT_NEXT, CFT_NEXT,
CFT_BREAK, CFT_BREAK,
CFT_DEFAULT, CFT_DEFAULT,