mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
factored ZAM source's main header into collection of per-source-file headers
This commit is contained in:
parent
d6c1d0640e
commit
64de2dbf31
9 changed files with 428 additions and 397 deletions
101
src/script_opt/ZAM/AM-Opt.h
Normal file
101
src/script_opt/ZAM/AM-Opt.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for low-level optimization of the ZAM abstract machine.
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
// Optimizing the low-level compiled instructions.
|
||||
void OptimizeInsts();
|
||||
|
||||
// Tracks which instructions can be branched to via the given
|
||||
// set of switches.
|
||||
template<typename T>
|
||||
void TallySwitchTargets(const CaseMapsI<T>& switches);
|
||||
|
||||
// Remove code that can't be reached. True if some removal happened.
|
||||
bool RemoveDeadCode();
|
||||
|
||||
// Collapse chains of gotos. True if some something changed.
|
||||
bool CollapseGoTos();
|
||||
|
||||
// Prune statements that are unnecessary. True if something got
|
||||
// pruned.
|
||||
bool PruneUnused();
|
||||
|
||||
// For the current state of insts1, compute lifetimes of frame
|
||||
// denizens (variable(s) using a given frame slot) in terms of
|
||||
// first-instruction-to-last-instruction during which they're
|
||||
// relevant, including consideration for loops.
|
||||
void ComputeFrameLifetimes();
|
||||
|
||||
// Given final frame lifetime information, remaps frame members
|
||||
// with non-overlapping lifetimes to share slots.
|
||||
void ReMapFrame();
|
||||
|
||||
// Given final frame lifetime information, remaps slots in the
|
||||
// interpreter frame. (No longer strictly necessary.)
|
||||
void ReMapInterpreterFrame();
|
||||
|
||||
// Computes the remapping for a variable currently in the given slot,
|
||||
// whose scope begins at the given instruction.
|
||||
void ReMapVar(const ID* id, int slot, zeek_uint_t inst);
|
||||
|
||||
// Look to initialize the beginning of local lifetime based on slot
|
||||
// assignment at instruction inst.
|
||||
void CheckSlotAssignment(int slot, const ZInstI* inst);
|
||||
|
||||
// Track that a local's lifetime begins at the given statement.
|
||||
void SetLifetimeStart(int slot, const ZInstI* inst);
|
||||
|
||||
// Look for extension of local lifetime based on slot usage
|
||||
// at instruction inst.
|
||||
void CheckSlotUse(int slot, const ZInstI* inst);
|
||||
|
||||
// Extend (or create) the end of a local's lifetime.
|
||||
void ExtendLifetime(int slot, const ZInstI* inst);
|
||||
|
||||
// Returns the (live) instruction at the beginning/end of the loop(s)
|
||||
// within which the given instruction lies; or that instruction
|
||||
// itself if it's not inside a loop. The second argument specifies
|
||||
// the loop depth. For example, a value of '2' means "extend to
|
||||
// the beginning/end of any loop(s) of depth >= 2".
|
||||
const ZInstI* BeginningOfLoop(const ZInstI* inst, int depth) const;
|
||||
const ZInstI* EndOfLoop(const ZInstI* inst, int depth) const;
|
||||
|
||||
// True if any statement other than a frame sync uses the given slot.
|
||||
bool VarIsUsed(int slot) const;
|
||||
|
||||
// Find the first non-dead instruction after i (inclusive).
|
||||
// If follow_gotos is true, then if that instruction is
|
||||
// an unconditional branch, continues the process until
|
||||
// a different instruction is found (and report if there
|
||||
// are infinite loops).
|
||||
//
|
||||
// First form returns nil if there's nothing live after i.
|
||||
// Second form returns insts1.size() in that case.
|
||||
ZInstI* FirstLiveInst(ZInstI* i, bool follow_gotos = false);
|
||||
zeek_uint_t FirstLiveInst(zeek_uint_t i, bool follow_gotos = false);
|
||||
|
||||
// Same, but not including i.
|
||||
ZInstI* NextLiveInst(ZInstI* i, bool follow_gotos = false) {
|
||||
if ( i->inst_num == static_cast<int>(insts1.size()) - 1 )
|
||||
return nullptr;
|
||||
return FirstLiveInst(insts1[i->inst_num + 1], follow_gotos);
|
||||
}
|
||||
int NextLiveInst(int i, bool follow_gotos = false) { return FirstLiveInst(i + 1, follow_gotos); }
|
||||
|
||||
// Mark an instruction as unnecessary and remove its influence on
|
||||
// other statements. The instruction is indicated as an offset
|
||||
// into insts1; any labels associated with it are transferred
|
||||
// to its next live successor, if any.
|
||||
void KillInst(ZInstI* i) { KillInst(i->inst_num); }
|
||||
void KillInst(zeek_uint_t i);
|
||||
|
||||
// Helper function for propagating control flow (of a given type)
|
||||
// backwards, when the instruction at the given offset has been killed.
|
||||
void BackPropagateCFT(int inst_num, ControlFlowType cf_type);
|
||||
|
||||
// The same, but kills any successor instructions until finding
|
||||
// one that's labeled.
|
||||
void KillInsts(ZInstI* i) { KillInsts(i->inst_num); }
|
||||
void KillInsts(zeek_uint_t i);
|
56
src/script_opt/ZAM/Branches.h
Normal file
56
src/script_opt/ZAM/Branches.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for managing low-level ZAM control flow, which is implemented
|
||||
// using go-to branches.
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
void PushNexts() { PushGoTos(nexts); }
|
||||
void PushBreaks() { PushGoTos(breaks); }
|
||||
void PushFallThroughs() { PushGoTos(fallthroughs); }
|
||||
void PushCatchReturns() { PushGoTos(catches); }
|
||||
|
||||
void ResolveNexts(const InstLabel l) { ResolveGoTos(nexts, l, CFT_NEXT); }
|
||||
void ResolveBreaks(const InstLabel l) { ResolveGoTos(breaks, l, CFT_BREAK); }
|
||||
void ResolveFallThroughs(const InstLabel l) { ResolveGoTos(fallthroughs, l); }
|
||||
void ResolveCatchReturns(const InstLabel l) { ResolveGoTos(catches, l, CFT_INLINED_RETURN); }
|
||||
|
||||
using GoToSet = std::vector<ZAMStmt>;
|
||||
using GoToSets = std::vector<GoToSet>;
|
||||
|
||||
void PushGoTos(GoToSets& gotos);
|
||||
void ResolveGoTos(GoToSets& gotos, const InstLabel l, ControlFlowType cft = CFT_NONE);
|
||||
|
||||
ZAMStmt GenGoTo(GoToSet& v);
|
||||
ZAMStmt GoToStub();
|
||||
ZAMStmt GoTo(const InstLabel l);
|
||||
InstLabel GoToTarget(const ZAMStmt s);
|
||||
InstLabel GoToTargetBeyond(const ZAMStmt s);
|
||||
|
||||
void SetTarget(ZInstI* inst, const InstLabel l, int slot);
|
||||
|
||||
// Given a GoTo target, find its live equivalent (first instruction
|
||||
// at that location or beyond that's live).
|
||||
ZInstI* FindLiveTarget(ZInstI* goto_target);
|
||||
|
||||
// Given an instruction that has a slot associated with the
|
||||
// given target, updates the slot to correspond with the current
|
||||
// instruction number of the target.
|
||||
void ConcretizeBranch(ZInstI* inst, ZInstI* target, int target_slot);
|
||||
|
||||
void SetV(ZAMStmt s, const InstLabel l, int v) {
|
||||
if ( v == 1 )
|
||||
SetV1(s, l);
|
||||
else if ( v == 2 )
|
||||
SetV2(s, l);
|
||||
else if ( v == 3 )
|
||||
SetV3(s, l);
|
||||
else
|
||||
SetV4(s, l);
|
||||
}
|
||||
|
||||
void SetV1(ZAMStmt s, const InstLabel l);
|
||||
void SetV2(ZAMStmt s, const InstLabel l);
|
||||
void SetV3(ZAMStmt s, const InstLabel l);
|
||||
void SetV4(ZAMStmt s, const InstLabel l);
|
||||
void SetGoTo(ZAMStmt s, const InstLabel targ) { SetV1(s, targ); }
|
|
@ -51,14 +51,22 @@ public:
|
|||
ZInstAux* aux;
|
||||
};
|
||||
|
||||
// Most of the methods for the compiler are either in separate header source
|
||||
// files, or in headers generated by auxil/gen-zam. We include these within
|
||||
// the private part of the compiler class definitions, so a few methods that
|
||||
// need to be public are specified here directly, rather than via such
|
||||
// headers.
|
||||
//
|
||||
// We declare member variables here, rather than in included headers, since
|
||||
// many of them are used across different source files, and don't necessarily
|
||||
// have a natural "home".
|
||||
|
||||
class ZAMCompiler {
|
||||
public:
|
||||
ZAMCompiler(ScriptFuncPtr f, std::shared_ptr<ProfileFuncs> pfs, std::shared_ptr<ProfileFunc> pf, ScopePtr scope,
|
||||
StmtPtr body, std::shared_ptr<UseDefs> ud, std::shared_ptr<Reducer> rd);
|
||||
~ZAMCompiler();
|
||||
|
||||
StmtPtr CompileBody();
|
||||
|
||||
const FrameReMap& FrameDenizens() const { return shared_frame_denizens_final; }
|
||||
|
||||
const std::vector<int>& ManagedSlots() const { return managed_slotsI; }
|
||||
|
@ -82,6 +90,8 @@ public:
|
|||
return str_cases;
|
||||
}
|
||||
|
||||
StmtPtr CompileBody();
|
||||
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
|
@ -92,406 +102,27 @@ private:
|
|||
friend class CatZBI;
|
||||
friend class MultiZBI;
|
||||
|
||||
void Init();
|
||||
void InitGlobals();
|
||||
void InitArgs();
|
||||
void InitCaptures();
|
||||
void InitLocals();
|
||||
void TrackMemoryManagement();
|
||||
|
||||
void ResolveHookBreaks();
|
||||
void ComputeLoopLevels();
|
||||
void AdjustBranches();
|
||||
void RetargetBranches();
|
||||
void RemapFrameDenizens(const std::vector<int>& inst1_to_inst2);
|
||||
void CreateSharedFrameDenizens();
|
||||
void ConcretizeSwitches();
|
||||
|
||||
// The following are used for switch statements, mapping the
|
||||
// switch value (which can be any atomic type) to a branch target.
|
||||
// We have vectors of them because functions can contain multiple
|
||||
// switches.
|
||||
// See ZBody.h for their concrete counterparts, which we've
|
||||
// already #include'd.
|
||||
// The following are used for switch statements, mapping the switch value
|
||||
// (which can be any atomic type) to a branch target. We have vectors of
|
||||
// them because functions can contain multiple switches.
|
||||
//
|
||||
// See ZBody.h for their concrete counterparts, which we've already #include'd.
|
||||
template<typename T>
|
||||
using CaseMapI = std::map<T, InstLabel>;
|
||||
template<typename T>
|
||||
using CaseMapsI = std::vector<CaseMapI<T>>;
|
||||
|
||||
template<typename T>
|
||||
void AdjustSwitchTables(CaseMapsI<T>& abstract_cases);
|
||||
|
||||
template<typename T>
|
||||
void ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases, CaseMaps<T>& concrete_cases);
|
||||
|
||||
template<typename T>
|
||||
void DumpCases(const CaseMaps<T>& cases, const char* type_name) const;
|
||||
void DumpInsts1(const FrameReMap* remappings);
|
||||
|
||||
#include "zeek/ZAM-MethodDecls.h"
|
||||
|
||||
const ZAMStmt CompileStmt(const StmtPtr& body) { return CompileStmt(body.get()); }
|
||||
const ZAMStmt CompileStmt(const Stmt* body);
|
||||
|
||||
const ZAMStmt CompilePrint(const PrintStmt* ps);
|
||||
const ZAMStmt CompileExpr(const ExprStmt* es);
|
||||
const ZAMStmt CompileIf(const IfStmt* is);
|
||||
const ZAMStmt CompileSwitch(const SwitchStmt* sw);
|
||||
const ZAMStmt CompileWhile(const WhileStmt* ws);
|
||||
const ZAMStmt CompileFor(const ForStmt* f);
|
||||
const ZAMStmt CompileReturn(const ReturnStmt* r);
|
||||
const ZAMStmt CompileCatchReturn(const CatchReturnStmt* cr);
|
||||
const ZAMStmt CompileStmts(const StmtList* sl);
|
||||
const ZAMStmt CompileInit(const InitStmt* is);
|
||||
const ZAMStmt CompileWhen(const WhenStmt* ws);
|
||||
|
||||
const ZAMStmt CompileNext() { return GenGoTo(nexts.back()); }
|
||||
const ZAMStmt CompileBreak() { return GenGoTo(breaks.back()); }
|
||||
const ZAMStmt CompileFallThrough() { return GenGoTo(fallthroughs.back()); }
|
||||
const ZAMStmt CompileCatchReturn() { return GenGoTo(catches.back()); }
|
||||
|
||||
const ZAMStmt IfElse(const Expr* e, const Stmt* s1, const Stmt* s2);
|
||||
const ZAMStmt While(const Stmt* cond_stmt, const Expr* cond, const Stmt* body);
|
||||
|
||||
const ZAMStmt InitRecord(IDPtr id, RecordType* rt);
|
||||
const ZAMStmt InitVector(IDPtr id, VectorType* vt);
|
||||
const ZAMStmt InitTable(IDPtr id, TableType* tt, Attributes* attrs);
|
||||
|
||||
const ZAMStmt ValueSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
const ZAMStmt TypeSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
const ZAMStmt GenSwitch(const SwitchStmt* sw, int slot, InternalTypeTag it);
|
||||
|
||||
void PushNexts() { PushGoTos(nexts); }
|
||||
void PushBreaks() { PushGoTos(breaks); }
|
||||
void PushFallThroughs() { PushGoTos(fallthroughs); }
|
||||
void PushCatchReturns() { PushGoTos(catches); }
|
||||
|
||||
void ResolveNexts(const InstLabel l) { ResolveGoTos(nexts, l, CFT_NEXT); }
|
||||
void ResolveBreaks(const InstLabel l) { ResolveGoTos(breaks, l, CFT_BREAK); }
|
||||
void ResolveFallThroughs(const InstLabel l) { ResolveGoTos(fallthroughs, l); }
|
||||
void ResolveCatchReturns(const InstLabel l) { ResolveGoTos(catches, l, CFT_INLINED_RETURN); }
|
||||
|
||||
const ZAMStmt LoopOverTable(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverVector(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverString(const ForStmt* f, const Expr* e);
|
||||
|
||||
const ZAMStmt FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt, const Stmt* body, int iter_slot,
|
||||
bool is_table);
|
||||
|
||||
const ZAMStmt Loop(const Stmt* body);
|
||||
|
||||
const ZAMStmt CompileExpr(const ExprPtr& e) { return CompileExpr(e.get()); }
|
||||
const ZAMStmt CompileExpr(const Expr* body);
|
||||
|
||||
const ZAMStmt CompileIncrExpr(const IncrExpr* e);
|
||||
const ZAMStmt CompileAppendToExpr(const AppendToExpr* e);
|
||||
const ZAMStmt CompileAdd(const AggrAddExpr* e);
|
||||
const ZAMStmt CompileDel(const AggrDelExpr* e);
|
||||
const ZAMStmt CompileAddToExpr(const AddToExpr* e);
|
||||
const ZAMStmt CompileRemoveFromExpr(const RemoveFromExpr* e);
|
||||
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
||||
const ZAMStmt CompileRecFieldUpdates(const RecordFieldUpdatesExpr* e);
|
||||
const ZAMStmt CompileZAMBuiltin(const NameExpr* lhs, const ScriptOptBuiltinExpr* zbi);
|
||||
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs);
|
||||
const ZAMStmt CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e);
|
||||
const ZAMStmt CompileScheduleExpr(const ScheduleExpr* e);
|
||||
const ZAMStmt CompileSchedule(const NameExpr* n, const ConstExpr* c, int is_interval, EventHandler* h,
|
||||
const ListExpr* l);
|
||||
const ZAMStmt CompileEvent(EventHandler* h, const ListExpr* l);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const NameExpr* n3) {
|
||||
return CompileInExpr(n1, n2, nullptr, n3, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c) {
|
||||
return CompileInExpr(n1, n2, nullptr, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ConstExpr* c, const NameExpr* n3) {
|
||||
return CompileInExpr(n1, nullptr, c, n3, nullptr);
|
||||
}
|
||||
|
||||
// In the following, one of n2 or c2 (likewise, n3/c3) will be nil.
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c2, const NameExpr* n3,
|
||||
const ConstExpr* c3);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2) {
|
||||
return CompileInExpr(n1, l, n2, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n, const ListExpr* l, const ConstExpr* c) {
|
||||
return CompileInExpr(n, l, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2, const ConstExpr* c);
|
||||
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const NameExpr* n2, const ListExpr* l, bool in_when);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const ConstExpr* c, const ListExpr* l, bool in_when);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, int n2_slot, const TypePtr& n2_type, const ListExpr* l,
|
||||
bool in_when);
|
||||
|
||||
const ZAMStmt BuildLambda(const NameExpr* n, ExprPtr le);
|
||||
const ZAMStmt BuildLambda(int n_slot, ExprPtr le);
|
||||
|
||||
// Second argument is which instruction slot holds the branch target.
|
||||
const ZAMStmt GenCond(const Expr* e, int& branch_v);
|
||||
|
||||
const ZAMStmt Call(const ExprStmt* e);
|
||||
const ZAMStmt AssignToCall(const ExprStmt* e);
|
||||
const ZAMStmt DoCall(const CallExpr* c, const NameExpr* n);
|
||||
bool CheckForBuiltIn(const ExprPtr& e, CallExprPtr c);
|
||||
|
||||
const ZAMStmt AssignVecElems(const Expr* e);
|
||||
const ZAMStmt AssignTableElem(const Expr* e);
|
||||
|
||||
const ZAMStmt ConstructTable(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt ConstructSet(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt ConstructRecord(const NameExpr* n, const Expr* e) { return ConstructRecord(n, e, false); }
|
||||
const ZAMStmt ConstructRecordFromRecord(const NameExpr* n, const Expr* e) { return ConstructRecord(n, e, true); }
|
||||
const ZAMStmt ConstructRecord(const NameExpr* n, const Expr* e, bool is_from_rec);
|
||||
const ZAMStmt ConstructVector(const NameExpr* n, const Expr* e);
|
||||
|
||||
const ZAMStmt ArithCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt RecordCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt TableCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt VectorCoerce(const NameExpr* n, const Expr* e);
|
||||
|
||||
const ZAMStmt Is(const NameExpr* n, const Expr* e);
|
||||
|
||||
#include "zeek/script_opt/ZAM/AM-Opt.h"
|
||||
#include "zeek/script_opt/ZAM/Branches.h"
|
||||
#include "zeek/script_opt/ZAM/Driver.h"
|
||||
#include "zeek/script_opt/ZAM/Expr.h"
|
||||
#include "zeek/script_opt/ZAM/Inst-Gen.h"
|
||||
#include "zeek/script_opt/ZAM/Low-Level.h"
|
||||
#include "zeek/script_opt/ZAM/Stmt.h"
|
||||
#include "zeek/script_opt/ZAM/Vars.h"
|
||||
|
||||
int ConvertToInt(const Expr* e) {
|
||||
if ( e->Tag() == EXPR_NAME )
|
||||
return FrameSlot(e->AsNameExpr()->Id());
|
||||
else
|
||||
return e->AsConstExpr()->Value()->AsInt();
|
||||
}
|
||||
|
||||
int ConvertToCount(const Expr* e) {
|
||||
if ( e->Tag() == EXPR_NAME )
|
||||
return FrameSlot(e->AsNameExpr()->Id());
|
||||
else
|
||||
return e->AsConstExpr()->Value()->AsCount();
|
||||
}
|
||||
|
||||
using GoToSet = std::vector<ZAMStmt>;
|
||||
using GoToSets = std::vector<GoToSet>;
|
||||
|
||||
void PushGoTos(GoToSets& gotos);
|
||||
void ResolveGoTos(GoToSets& gotos, const InstLabel l, ControlFlowType cft = CFT_NONE);
|
||||
|
||||
ZAMStmt GenGoTo(GoToSet& v);
|
||||
ZAMStmt GoToStub();
|
||||
ZAMStmt GoTo(const InstLabel l);
|
||||
InstLabel GoToTarget(const ZAMStmt s);
|
||||
InstLabel GoToTargetBeyond(const ZAMStmt s);
|
||||
|
||||
void SetTarget(ZInstI* inst, const InstLabel l, int slot);
|
||||
|
||||
// Given a GoTo target, find its live equivalent (first instruction
|
||||
// at that location or beyond that's live).
|
||||
ZInstI* FindLiveTarget(ZInstI* goto_target);
|
||||
|
||||
// Given an instruction that has a slot associated with the
|
||||
// given target, updates the slot to correspond with the current
|
||||
// instruction number of the target.
|
||||
void ConcretizeBranch(ZInstI* inst, ZInstI* target, int target_slot);
|
||||
|
||||
void SetV(ZAMStmt s, const InstLabel l, int v) {
|
||||
if ( v == 1 )
|
||||
SetV1(s, l);
|
||||
else if ( v == 2 )
|
||||
SetV2(s, l);
|
||||
else if ( v == 3 )
|
||||
SetV3(s, l);
|
||||
else
|
||||
SetV4(s, l);
|
||||
}
|
||||
|
||||
void SetV1(ZAMStmt s, const InstLabel l);
|
||||
void SetV2(ZAMStmt s, const InstLabel l);
|
||||
void SetV3(ZAMStmt s, const InstLabel l);
|
||||
void SetV4(ZAMStmt s, const InstLabel l);
|
||||
void SetGoTo(ZAMStmt s, const InstLabel targ) { SetV1(s, targ); }
|
||||
|
||||
const ZAMStmt StartingBlock();
|
||||
const ZAMStmt FinishBlock(const ZAMStmt start);
|
||||
|
||||
bool NullStmtOK() const;
|
||||
|
||||
const ZAMStmt EmptyStmt();
|
||||
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.
|
||||
std::unique_ptr<OpaqueVals> BuildVals(const ListExprPtr&);
|
||||
|
||||
// "stride" is how many slots each element of l will consume.
|
||||
ZInstAux* InternalBuildVals(const ListExpr* l, int stride = 1);
|
||||
|
||||
// Returns how many values were added.
|
||||
int InternalAddVal(ZInstAux* zi, int i, Expr* e);
|
||||
|
||||
// Adds the given instruction to the ZAM program. The second
|
||||
// argument, if true, suppresses generation of any pending
|
||||
// global/capture store for this instruction.
|
||||
const ZAMStmt AddInst(const ZInstI& inst, bool suppress_non_local = false);
|
||||
|
||||
// Returns the statement just before the given one.
|
||||
ZAMStmt PrevStmt(const ZAMStmt s);
|
||||
|
||||
// Returns the last (interpreter) statement in the body.
|
||||
const Stmt* LastStmt(const Stmt* s) const;
|
||||
|
||||
// Returns the most recent added instruction *other* than those
|
||||
// added for bookkeeping.
|
||||
ZInstI* TopMainInst() { return insts1[top_main_inst]; }
|
||||
|
||||
bool IsUnused(const IDPtr& id, const Stmt* where) const;
|
||||
|
||||
bool IsCapture(const IDPtr& id) const { return IsCapture(id.get()); }
|
||||
bool IsCapture(const ID* id) const;
|
||||
|
||||
int CaptureOffset(const IDPtr& id) const { return IsCapture(id.get()); }
|
||||
int CaptureOffset(const ID* id) const;
|
||||
|
||||
void LoadParam(const ID* id);
|
||||
const ZAMStmt LoadGlobal(const ID* id);
|
||||
const ZAMStmt LoadCapture(const ID* id);
|
||||
|
||||
int AddToFrame(const ID*);
|
||||
|
||||
int FrameSlot(const IDPtr& id) { return FrameSlot(id.get()); }
|
||||
int FrameSlot(const ID* id);
|
||||
int FrameSlotIfName(const Expr* e) {
|
||||
auto n = e->Tag() == EXPR_NAME ? e->AsNameExpr() : nullptr;
|
||||
return n ? FrameSlot(n->Id()) : -1;
|
||||
}
|
||||
|
||||
int FrameSlot(const NameExpr* id) { return FrameSlot(id->AsNameExpr()->Id()); }
|
||||
int Frame1Slot(const NameExpr* id, ZOp op) { return Frame1Slot(id->AsNameExpr()->Id(), op); }
|
||||
|
||||
int Frame1Slot(const ID* id, ZOp op) { return Frame1Slot(id, op1_flavor[op]); }
|
||||
int Frame1Slot(const NameExpr* n, ZAMOp1Flavor fl) { return Frame1Slot(n->Id(), fl); }
|
||||
int Frame1Slot(const ID* id, ZAMOp1Flavor fl);
|
||||
|
||||
// The slot without doing any global-related checking.
|
||||
int RawSlot(const NameExpr* n) { return RawSlot(n->Id()); }
|
||||
int RawSlot(const ID* id);
|
||||
|
||||
bool HasFrameSlot(const ID* id) const;
|
||||
|
||||
int NewSlot(const TypePtr& t) { return NewSlot(ZVal::IsManagedType(t)); }
|
||||
int NewSlot(bool is_managed);
|
||||
|
||||
int TempForConst(const ConstExpr* c);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// The following methods relate to optimizing the low-level
|
||||
// ZAM function body after it is initially generated. They're
|
||||
// factored out into ZOpt.cc since they're structurally quite
|
||||
// different from the methods above that relate to the initial
|
||||
// compilation.
|
||||
|
||||
// Optimizing the low-level compiled instructions.
|
||||
void OptimizeInsts();
|
||||
|
||||
// Tracks which instructions can be branched to via the given
|
||||
// set of switches.
|
||||
template<typename T>
|
||||
void TallySwitchTargets(const CaseMapsI<T>& switches);
|
||||
|
||||
// Remove code that can't be reached. True if some removal happened.
|
||||
bool RemoveDeadCode();
|
||||
|
||||
// Collapse chains of gotos. True if some something changed.
|
||||
bool CollapseGoTos();
|
||||
|
||||
// Prune statements that are unnecessary. True if something got
|
||||
// pruned.
|
||||
bool PruneUnused();
|
||||
|
||||
// For the current state of insts1, compute lifetimes of frame
|
||||
// denizens (variable(s) using a given frame slot) in terms of
|
||||
// first-instruction-to-last-instruction during which they're
|
||||
// relevant, including consideration for loops.
|
||||
void ComputeFrameLifetimes();
|
||||
|
||||
// Given final frame lifetime information, remaps frame members
|
||||
// with non-overlapping lifetimes to share slots.
|
||||
void ReMapFrame();
|
||||
|
||||
// Given final frame lifetime information, remaps slots in the
|
||||
// interpreter frame. (No longer strictly necessary.)
|
||||
void ReMapInterpreterFrame();
|
||||
|
||||
// Computes the remapping for a variable currently in the given slot,
|
||||
// whose scope begins at the given instruction.
|
||||
void ReMapVar(const ID* id, int slot, zeek_uint_t inst);
|
||||
|
||||
// Look to initialize the beginning of local lifetime based on slot
|
||||
// assignment at instruction inst.
|
||||
void CheckSlotAssignment(int slot, const ZInstI* inst);
|
||||
|
||||
// Track that a local's lifetime begins at the given statement.
|
||||
void SetLifetimeStart(int slot, const ZInstI* inst);
|
||||
|
||||
// Look for extension of local lifetime based on slot usage
|
||||
// at instruction inst.
|
||||
void CheckSlotUse(int slot, const ZInstI* inst);
|
||||
|
||||
// Extend (or create) the end of a local's lifetime.
|
||||
void ExtendLifetime(int slot, const ZInstI* inst);
|
||||
|
||||
// Returns the (live) instruction at the beginning/end of the loop(s)
|
||||
// within which the given instruction lies; or that instruction
|
||||
// itself if it's not inside a loop. The second argument specifies
|
||||
// the loop depth. For example, a value of '2' means "extend to
|
||||
// the beginning/end of any loop(s) of depth >= 2".
|
||||
const ZInstI* BeginningOfLoop(const ZInstI* inst, int depth) const;
|
||||
const ZInstI* EndOfLoop(const ZInstI* inst, int depth) const;
|
||||
|
||||
// True if any statement other than a frame sync uses the given slot.
|
||||
bool VarIsUsed(int slot) const;
|
||||
|
||||
// Find the first non-dead instruction after i (inclusive).
|
||||
// If follow_gotos is true, then if that instruction is
|
||||
// an unconditional branch, continues the process until
|
||||
// a different instruction is found (and report if there
|
||||
// are infinite loops).
|
||||
//
|
||||
// First form returns nil if there's nothing live after i.
|
||||
// Second form returns insts1.size() in that case.
|
||||
ZInstI* FirstLiveInst(ZInstI* i, bool follow_gotos = false);
|
||||
zeek_uint_t FirstLiveInst(zeek_uint_t i, bool follow_gotos = false);
|
||||
|
||||
// Same, but not including i.
|
||||
ZInstI* NextLiveInst(ZInstI* i, bool follow_gotos = false) {
|
||||
if ( i->inst_num == static_cast<int>(insts1.size()) - 1 )
|
||||
return nullptr;
|
||||
return FirstLiveInst(insts1[i->inst_num + 1], follow_gotos);
|
||||
}
|
||||
int NextLiveInst(int i, bool follow_gotos = false) { return FirstLiveInst(i + 1, follow_gotos); }
|
||||
|
||||
// Mark an instruction as unnecessary and remove its influence on
|
||||
// other statements. The instruction is indicated as an offset
|
||||
// into insts1; any labels associated with it are transferred
|
||||
// to its next live successor, if any.
|
||||
void KillInst(ZInstI* i) { KillInst(i->inst_num); }
|
||||
void KillInst(zeek_uint_t i);
|
||||
|
||||
// Helper function for propagating control flow (of a given type)
|
||||
// backwards, when the instruction at the given offset has been killed.
|
||||
void BackPropagateCFT(int inst_num, ControlFlowType cf_type);
|
||||
|
||||
// The same, but kills any successor instructions until finding
|
||||
// one that's labeled.
|
||||
void KillInsts(ZInstI* i) { KillInsts(i->inst_num); }
|
||||
void KillInsts(zeek_uint_t i);
|
||||
// Headers auto-generated by gen-zam.
|
||||
#include "zeek/ZAM-MethodDecls.h"
|
||||
|
||||
// The first of these is used as we compile down to ZInstI's.
|
||||
// The second is the final intermediary code. They're separate
|
||||
|
|
31
src/script_opt/ZAM/Driver.h
Normal file
31
src/script_opt/ZAM/Driver.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for driving the overall ZAM compilation process.
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
void Init();
|
||||
void InitGlobals();
|
||||
void InitArgs();
|
||||
void InitCaptures();
|
||||
void InitLocals();
|
||||
void TrackMemoryManagement();
|
||||
|
||||
template<typename T>
|
||||
void AdjustSwitchTables(CaseMapsI<T>& abstract_cases);
|
||||
|
||||
template<typename T>
|
||||
void ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases, CaseMaps<T>& concrete_cases);
|
||||
void ConcretizeSwitches();
|
||||
|
||||
void RetargetBranches();
|
||||
void RemapFrameDenizens(const std::vector<int>& inst1_to_inst2);
|
||||
void CreateSharedFrameDenizens();
|
||||
|
||||
void ResolveHookBreaks();
|
||||
void ComputeLoopLevels();
|
||||
void AdjustBranches();
|
||||
|
||||
template<typename T>
|
||||
void DumpCases(const CaseMaps<T>& cases, const char* type_name) const;
|
||||
void DumpInsts1(const FrameReMap* remappings);
|
79
src/script_opt/ZAM/Expr.h
Normal file
79
src/script_opt/ZAM/Expr.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for ZAM compilation of expression AST nodes (Expr's).
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
const ZAMStmt CompileExpr(const ExprPtr& e) { return CompileExpr(e.get()); }
|
||||
const ZAMStmt CompileExpr(const Expr* body);
|
||||
|
||||
const ZAMStmt CompileIncrExpr(const IncrExpr* e);
|
||||
const ZAMStmt CompileAppendToExpr(const AppendToExpr* e);
|
||||
const ZAMStmt CompileAdd(const AggrAddExpr* e);
|
||||
const ZAMStmt CompileDel(const AggrDelExpr* e);
|
||||
const ZAMStmt CompileAddToExpr(const AddToExpr* e);
|
||||
const ZAMStmt CompileRemoveFromExpr(const RemoveFromExpr* e);
|
||||
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
||||
const ZAMStmt CompileRecFieldUpdates(const RecordFieldUpdatesExpr* e);
|
||||
const ZAMStmt CompileZAMBuiltin(const NameExpr* lhs, const ScriptOptBuiltinExpr* zbi);
|
||||
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs);
|
||||
const ZAMStmt CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e);
|
||||
const ZAMStmt CompileScheduleExpr(const ScheduleExpr* e);
|
||||
const ZAMStmt CompileSchedule(const NameExpr* n, const ConstExpr* c, int is_interval, EventHandler* h,
|
||||
const ListExpr* l);
|
||||
const ZAMStmt CompileEvent(EventHandler* h, const ListExpr* l);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const NameExpr* n3) {
|
||||
return CompileInExpr(n1, n2, nullptr, n3, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c) {
|
||||
return CompileInExpr(n1, n2, nullptr, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ConstExpr* c, const NameExpr* n3) {
|
||||
return CompileInExpr(n1, nullptr, c, n3, nullptr);
|
||||
}
|
||||
|
||||
// In the following, one of n2 or c2 (likewise, n3/c3) will be nil.
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c2, const NameExpr* n3,
|
||||
const ConstExpr* c3);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2) {
|
||||
return CompileInExpr(n1, l, n2, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n, const ListExpr* l, const ConstExpr* c) {
|
||||
return CompileInExpr(n, l, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2, const ConstExpr* c);
|
||||
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const NameExpr* n2, const ListExpr* l, bool in_when);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const ConstExpr* c, const ListExpr* l, bool in_when);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, int n2_slot, const TypePtr& n2_type, const ListExpr* l, bool in_when);
|
||||
|
||||
const ZAMStmt BuildLambda(const NameExpr* n, ExprPtr le);
|
||||
const ZAMStmt BuildLambda(int n_slot, ExprPtr le);
|
||||
|
||||
const ZAMStmt AssignVecElems(const Expr* e);
|
||||
const ZAMStmt AssignTableElem(const Expr* e);
|
||||
|
||||
const ZAMStmt Call(const ExprStmt* e);
|
||||
const ZAMStmt AssignToCall(const ExprStmt* e);
|
||||
bool CheckForBuiltIn(const ExprPtr& e, CallExprPtr c);
|
||||
const ZAMStmt DoCall(const CallExpr* c, const NameExpr* n);
|
||||
|
||||
const ZAMStmt ConstructTable(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt ConstructSet(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt ConstructRecord(const NameExpr* n, const Expr* e) { return ConstructRecord(n, e, false); }
|
||||
const ZAMStmt ConstructRecordFromRecord(const NameExpr* n, const Expr* e) { return ConstructRecord(n, e, true); }
|
||||
const ZAMStmt ConstructRecord(const NameExpr* n, const Expr* e, bool is_from_rec);
|
||||
const ZAMStmt ConstructVector(const NameExpr* n, const Expr* e);
|
||||
|
||||
const ZAMStmt ArithCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt RecordCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt TableCoerce(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt VectorCoerce(const NameExpr* n, const Expr* e);
|
||||
|
||||
const ZAMStmt Is(const NameExpr* n, const Expr* e);
|
|
@ -4,8 +4,7 @@
|
|||
// NameExpr*'s to slots. Some aren't needed, but we provide a complete
|
||||
// set mirroring the ZInstI constructors for consistency.
|
||||
//
|
||||
// Maintained separately from Compile.h to make it conceptually simple to
|
||||
// add new helpers.
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
ZInstI GenInst(ZOp op);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1);
|
||||
|
|
42
src/script_opt/ZAM/Low-Level.h
Normal file
42
src/script_opt/ZAM/Low-Level.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for low-level manipulation of ZAM instructions/statements.
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
const ZAMStmt StartingBlock();
|
||||
const ZAMStmt FinishBlock(const ZAMStmt start);
|
||||
|
||||
bool NullStmtOK() const;
|
||||
|
||||
const ZAMStmt EmptyStmt();
|
||||
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.
|
||||
std::unique_ptr<OpaqueVals> BuildVals(const ListExprPtr&);
|
||||
|
||||
// "stride" is how many slots each element of l will consume.
|
||||
ZInstAux* InternalBuildVals(const ListExpr* l, int stride = 1);
|
||||
|
||||
// Returns how many values were added.
|
||||
int InternalAddVal(ZInstAux* zi, int i, Expr* e);
|
||||
|
||||
// Adds the given instruction to the ZAM program. The second
|
||||
// argument, if true, suppresses generation of any pending
|
||||
// global/capture store for this instruction.
|
||||
const ZAMStmt AddInst(const ZInstI& inst, bool suppress_non_local = false);
|
||||
|
||||
// Returns the statement just before the given one.
|
||||
ZAMStmt PrevStmt(const ZAMStmt s);
|
||||
|
||||
// Returns the last (interpreter) statement in the body.
|
||||
const Stmt* LastStmt(const Stmt* s) const;
|
||||
|
||||
// Returns the most recent added instruction *other* than those
|
||||
// added for bookkeeping.
|
||||
ZInstI* TopMainInst() { return insts1[top_main_inst]; }
|
48
src/script_opt/ZAM/Stmt.h
Normal file
48
src/script_opt/ZAM/Stmt.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for ZAM compilation of statement AST nodes (Stmt's).
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
// Note, we first list the AST nodes and then the helper functions, though
|
||||
// in the definitions source these are intermingled.
|
||||
const ZAMStmt CompileStmt(const StmtPtr& body) { return CompileStmt(body.get()); }
|
||||
const ZAMStmt CompileStmt(const Stmt* body);
|
||||
|
||||
const ZAMStmt CompilePrint(const PrintStmt* ps);
|
||||
const ZAMStmt CompileExpr(const ExprStmt* es);
|
||||
const ZAMStmt CompileIf(const IfStmt* is);
|
||||
const ZAMStmt CompileSwitch(const SwitchStmt* sw);
|
||||
const ZAMStmt CompileWhile(const WhileStmt* ws);
|
||||
const ZAMStmt CompileFor(const ForStmt* f);
|
||||
const ZAMStmt CompileReturn(const ReturnStmt* r);
|
||||
const ZAMStmt CompileCatchReturn(const CatchReturnStmt* cr);
|
||||
const ZAMStmt CompileStmts(const StmtList* sl);
|
||||
const ZAMStmt CompileInit(const InitStmt* is);
|
||||
const ZAMStmt CompileWhen(const WhenStmt* ws);
|
||||
|
||||
const ZAMStmt CompileNext() { return GenGoTo(nexts.back()); }
|
||||
const ZAMStmt CompileBreak() { return GenGoTo(breaks.back()); }
|
||||
const ZAMStmt CompileFallThrough() { return GenGoTo(fallthroughs.back()); }
|
||||
const ZAMStmt CompileCatchReturn() { return GenGoTo(catches.back()); }
|
||||
|
||||
const ZAMStmt IfElse(const Expr* e, const Stmt* s1, const Stmt* s2);
|
||||
// Second argument is which instruction slot holds the branch target.
|
||||
const ZAMStmt GenCond(const Expr* e, int& branch_v);
|
||||
|
||||
const ZAMStmt While(const Stmt* cond_stmt, const Expr* cond, const Stmt* body);
|
||||
|
||||
const ZAMStmt ValueSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
const ZAMStmt TypeSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
const ZAMStmt GenSwitch(const SwitchStmt* sw, int slot, InternalTypeTag it);
|
||||
|
||||
const ZAMStmt LoopOverTable(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverVector(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverString(const ForStmt* f, const Expr* e);
|
||||
|
||||
const ZAMStmt Loop(const Stmt* body);
|
||||
const ZAMStmt FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt, const Stmt* body, int iter_slot, bool is_table);
|
||||
|
||||
const ZAMStmt InitRecord(IDPtr id, RecordType* rt);
|
||||
const ZAMStmt InitVector(IDPtr id, VectorType* vt);
|
||||
const ZAMStmt InitTable(IDPtr id, TableType* tt, Attributes* attrs);
|
44
src/script_opt/ZAM/Vars.h
Normal file
44
src/script_opt/ZAM/Vars.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Methods for managing Zeek function variables.
|
||||
//
|
||||
// This file is included by Compile.h to insert into the ZAMCompiler class.
|
||||
|
||||
bool IsUnused(const IDPtr& id, const Stmt* where) const;
|
||||
|
||||
bool IsCapture(const IDPtr& id) const { return IsCapture(id.get()); }
|
||||
bool IsCapture(const ID* id) const;
|
||||
|
||||
int CaptureOffset(const IDPtr& id) const { return IsCapture(id.get()); }
|
||||
int CaptureOffset(const ID* id) const;
|
||||
|
||||
void LoadParam(const ID* id);
|
||||
const ZAMStmt LoadGlobal(const ID* id);
|
||||
const ZAMStmt LoadCapture(const ID* id);
|
||||
|
||||
int AddToFrame(const ID*);
|
||||
|
||||
int FrameSlot(const IDPtr& id) { return FrameSlot(id.get()); }
|
||||
int FrameSlot(const ID* id);
|
||||
int FrameSlotIfName(const Expr* e) {
|
||||
auto n = e->Tag() == EXPR_NAME ? e->AsNameExpr() : nullptr;
|
||||
return n ? FrameSlot(n->Id()) : -1;
|
||||
}
|
||||
|
||||
int FrameSlot(const NameExpr* id) { return FrameSlot(id->AsNameExpr()->Id()); }
|
||||
int Frame1Slot(const NameExpr* id, ZOp op) { return Frame1Slot(id->AsNameExpr()->Id(), op); }
|
||||
|
||||
int Frame1Slot(const ID* id, ZOp op) { return Frame1Slot(id, op1_flavor[op]); }
|
||||
int Frame1Slot(const NameExpr* n, ZAMOp1Flavor fl) { return Frame1Slot(n->Id(), fl); }
|
||||
int Frame1Slot(const ID* id, ZAMOp1Flavor fl);
|
||||
|
||||
// The slot without doing any global-related checking.
|
||||
int RawSlot(const NameExpr* n) { return RawSlot(n->Id()); }
|
||||
int RawSlot(const ID* id);
|
||||
|
||||
bool HasFrameSlot(const ID* id) const;
|
||||
|
||||
int NewSlot(const TypePtr& t) { return NewSlot(ZVal::IsManagedType(t)); }
|
||||
int NewSlot(bool is_managed);
|
||||
|
||||
int TempForConst(const ConstExpr* c);
|
Loading…
Add table
Add a link
Reference in a new issue