mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 00:58:19 +00:00
tracking control flow
This commit is contained in:
parent
e479ccf3a0
commit
3dbaa141ec
8 changed files with 78 additions and 8 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 16bcb175dddaa1cb6e3df7e1951287a29a74164e
|
||||
Subproject commit 113acbada6478a610dfa639f34ef6662fbb671d9
|
|
@ -522,6 +522,12 @@ void ProfileFunc::TrackID(const ID* id) {
|
|||
// Already tracked.
|
||||
return;
|
||||
|
||||
if ( id->IsGlobal() )
|
||||
{
|
||||
globals.insert(id);
|
||||
all_globals.insert(id);
|
||||
}
|
||||
|
||||
ordered_ids.push_back(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,8 +167,14 @@ private:
|
|||
void PushFallThroughs() { PushGoTos(fallthroughs); }
|
||||
void PushCatchReturns() { PushGoTos(catches); }
|
||||
|
||||
void ResolveNexts(const InstLabel l) { ResolveGoTos(nexts, l); }
|
||||
void ResolveBreaks(const InstLabel l) { ResolveGoTos(breaks, l); }
|
||||
void ResolveNexts(const InstLabel l) {
|
||||
ResolveGoTos(nexts, l);
|
||||
AddCFT(l, CFT_NEXT);
|
||||
}
|
||||
void ResolveBreaks(const InstLabel l) {
|
||||
ResolveGoTos(breaks, l);
|
||||
AddCFT(l, CFT_BREAK);
|
||||
}
|
||||
void ResolveFallThroughs(const InstLabel l) { ResolveGoTos(fallthroughs, l); }
|
||||
void ResolveCatchReturns(const InstLabel l) { ResolveGoTos(catches, l); }
|
||||
|
||||
|
@ -319,6 +325,9 @@ private:
|
|||
const ZAMStmt ErrorStmt();
|
||||
const ZAMStmt LastInst();
|
||||
|
||||
// Adds control flow information to an instruction.
|
||||
void AddCFT(ZInstI* inst, ControlFlowType cft);
|
||||
|
||||
// Returns a handle to state associated with building
|
||||
// up a list of values.
|
||||
OpaqueVals* BuildVals(const ListExprPtr&);
|
||||
|
|
|
@ -203,6 +203,7 @@ StmtPtr ZAMCompiler::CompileBody() {
|
|||
|
||||
auto zb = make_intrusive<ZBody>(fname, this);
|
||||
zb->SetInsts(insts2);
|
||||
zb->SetLocationInfo(body->GetLocationInfo());
|
||||
|
||||
// Could erase insts1 here to recover memory, but it's handy
|
||||
// for debugging.
|
||||
|
|
|
@ -20,9 +20,15 @@ bool ZAMCompiler::NullStmtOK() const {
|
|||
|
||||
const ZAMStmt ZAMCompiler::EmptyStmt() { return ZAMStmt(insts1.size() - 1); }
|
||||
|
||||
const ZAMStmt ZAMCompiler::ErrorStmt() { return ZAMStmt(0); }
|
||||
|
||||
const ZAMStmt ZAMCompiler::LastInst() { return ZAMStmt(insts1.size() - 1); }
|
||||
|
||||
const ZAMStmt ZAMCompiler::ErrorStmt() { return ZAMStmt(0); }
|
||||
void ZAMCompiler::AddCFT(ZInstI* inst, ControlFlowType cft) {
|
||||
if ( ! inst->aux )
|
||||
inst->aux = new ZInstAux(0);
|
||||
inst->aux->cft.insert(cft);
|
||||
}
|
||||
|
||||
OpaqueVals* ZAMCompiler::BuildVals(const ListExprPtr& l) { return new OpaqueVals(InternalBuildVals(l.get())); }
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ issues:
|
|||
|`profile-ZAM` | Generate to "zprof.out" a ZAM execution profile. (Requires configuring with `--enable-ZAM-profiling` or `--enable-debug`.)|
|
||||
|`report-recursive` | Report on recursive functions and exit.|
|
||||
|`report-uncompilable` | Report on uncompilable functions and exit. For ZAM, all functions should be compilable.|
|
||||
|`validate-ZAM` | Perform internal validation of ZAM instructions and exit.|
|
||||
|`xform` | Transform scripts to "reduced" form.|
|
||||
|
||||
<a name="ZAM-profiling"></a>
|
||||
|
|
|
@ -145,13 +145,22 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
|||
else
|
||||
cond_stmt = GenCond(e, branch_v);
|
||||
|
||||
auto cft = (s1 && s2) ? CFT_IF_ELSE : (s1 ? CFT_IF : CFT_IF_NOT);
|
||||
AddCFT(insts1.back(), cft);
|
||||
|
||||
if ( s1 ) {
|
||||
auto s1_end = CompileStmt(s1);
|
||||
AddCFT(insts1.back(), CFT_BLOCK_END);
|
||||
|
||||
if ( s2 ) {
|
||||
auto branch_after_s1 = GoToStub();
|
||||
auto else_start = insts1.size();
|
||||
auto s2_end = CompileStmt(s2);
|
||||
|
||||
SetV(cond_stmt, GoToTargetBeyond(branch_after_s1), branch_v);
|
||||
SetGoTo(branch_after_s1, GoToTargetBeyond(s2_end));
|
||||
AddCFT(insts1[else_start], CFT_ELSE);
|
||||
AddCFT(insts1.back(), CFT_BLOCK_END);
|
||||
|
||||
return s2_end;
|
||||
}
|
||||
|
@ -164,6 +173,7 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
|||
|
||||
// Only the else clause is non-empty.
|
||||
auto s2_end = CompileStmt(s2);
|
||||
AddCFT(insts1.back(), CFT_BLOCK_END);
|
||||
|
||||
// For complex conditionals, we need to invert their sense since
|
||||
// we're switching to "if ( ! cond ) s2".
|
||||
|
@ -705,12 +715,17 @@ const ZAMStmt ZAMCompiler::While(const Stmt* cond_stmt, const Expr* cond, const
|
|||
else
|
||||
cond_IF = GenCond(cond, branch_v);
|
||||
|
||||
AddCFT(insts1[head.stmt_num], CFT_LOOP);
|
||||
AddCFT(insts1[cond_IF.stmt_num], CFT_LOOP_COND);
|
||||
|
||||
PushNexts();
|
||||
PushBreaks();
|
||||
|
||||
if ( body && body->Tag() != STMT_NULL )
|
||||
(void)CompileStmt(body);
|
||||
|
||||
AddCFT(insts1.back(), CFT_BLOCK_END);
|
||||
|
||||
auto tail = GoTo(GoToTarget(head));
|
||||
|
||||
auto beyond_tail = GoToTargetBeyond(tail);
|
||||
|
@ -730,17 +745,25 @@ const ZAMStmt ZAMCompiler::CompileFor(const ForStmt* f) {
|
|||
PushNexts();
|
||||
PushBreaks();
|
||||
|
||||
auto head = StartingBlock();
|
||||
ZAMStmt z;
|
||||
|
||||
if ( et == TYPE_TABLE )
|
||||
return LoopOverTable(f, val);
|
||||
z = LoopOverTable(f, val);
|
||||
|
||||
else if ( et == TYPE_VECTOR )
|
||||
return LoopOverVector(f, val);
|
||||
z = LoopOverVector(f, val);
|
||||
|
||||
else if ( et == TYPE_STRING )
|
||||
return LoopOverString(f, e);
|
||||
z = LoopOverString(f, e);
|
||||
|
||||
else
|
||||
reporter->InternalError("bad \"for\" loop-over value when compiling");
|
||||
|
||||
AddCFT(insts1[head.stmt_num], CFT_LOOP);
|
||||
AddCFT(insts1[z.stmt_num], CFT_BLOCK_END);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::LoopOverTable(const ForStmt* f, const NameExpr* val) {
|
||||
|
@ -798,6 +821,7 @@ const ZAMStmt ZAMCompiler::LoopOverTable(const ForStmt* f, const NameExpr* val)
|
|||
}
|
||||
|
||||
z.aux = aux; // so ZOpt.cc can get to it
|
||||
AddCFT(&z, CFT_LOOP_COND);
|
||||
|
||||
return FinishLoop(iter_head, z, body, iter_slot, true);
|
||||
}
|
||||
|
@ -842,6 +866,8 @@ const ZAMStmt ZAMCompiler::LoopOverVector(const ForStmt* f, const NameExpr* val)
|
|||
}
|
||||
}
|
||||
|
||||
AddCFT(&z, CFT_LOOP_COND);
|
||||
|
||||
return FinishLoop(iter_head, z, f->LoopBody(), iter_slot, false);
|
||||
}
|
||||
|
||||
|
@ -878,6 +904,8 @@ const ZAMStmt ZAMCompiler::LoopOverString(const ForStmt* f, const Expr* e) {
|
|||
z.is_managed = true;
|
||||
}
|
||||
|
||||
AddCFT(&z, CFT_LOOP_COND);
|
||||
|
||||
return FinishLoop(iter_head, z, f->LoopBody(), iter_slot, false);
|
||||
}
|
||||
|
||||
|
@ -886,7 +914,11 @@ const ZAMStmt ZAMCompiler::Loop(const Stmt* body) {
|
|||
PushBreaks();
|
||||
|
||||
auto head = StartingBlock();
|
||||
(void)CompileStmt(body);
|
||||
auto b = CompileStmt(body);
|
||||
|
||||
AddCFT(insts1[head.stmt_num], CFT_LOOP);
|
||||
AddCFT(insts1[b.stmt_num], CFT_BLOCK_END);
|
||||
|
||||
auto tail = GoTo(GoToTarget(head));
|
||||
|
||||
ResolveNexts(GoToTarget(head));
|
||||
|
|
|
@ -375,6 +375,18 @@ private:
|
|||
bool is_managed = false;
|
||||
};
|
||||
|
||||
enum ControlFlowType {
|
||||
CFT_IF,
|
||||
CFT_IF_NOT,
|
||||
CFT_IF_ELSE,
|
||||
CFT_BLOCK_END,
|
||||
CFT_ELSE,
|
||||
CFT_LOOP,
|
||||
CFT_LOOP_COND,
|
||||
CFT_NEXT,
|
||||
CFT_BREAK,
|
||||
};
|
||||
|
||||
// Auxiliary information, used when the fixed ZInst layout lacks
|
||||
// sufficient expressiveness to represent all of the elements that
|
||||
// an instruction needs.
|
||||
|
@ -493,6 +505,9 @@ public:
|
|||
// Whether we know that we're calling a BiF.
|
||||
bool is_BiF_call = false;
|
||||
|
||||
// Associated control flow information.
|
||||
std::set<ControlFlowType> cft;
|
||||
|
||||
// Used for referring to events.
|
||||
EventHandler* event_handler = nullptr;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue