tracking control flow

This commit is contained in:
Vern Paxson 2024-06-12 15:05:24 -07:00
parent e479ccf3a0
commit 3dbaa141ec
8 changed files with 78 additions and 8 deletions

@ -1 +1 @@
Subproject commit 16bcb175dddaa1cb6e3df7e1951287a29a74164e Subproject commit 113acbada6478a610dfa639f34ef6662fbb671d9

View file

@ -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);
} }

View file

@ -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&);

View file

@ -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.

View file

@ -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())); }

View file

@ -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>

View file

@ -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));

View file

@ -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;