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