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.
return;
if ( id->IsGlobal() )
{
globals.insert(id);
all_globals.insert(id);
}
ordered_ids.push_back(id);
}

View file

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

View file

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

View file

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

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`.)|
|`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>

View file

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

View file

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