// See the file "COPYING" in the main distribution directory for copyright. // ZBody: ZAM function body that replaces a function's original AST body. #pragma once #include "zeek/script_opt/ZAM/IterInfo.h" #include "zeek/script_opt/ZAM/Support.h" namespace zeek::detail { // Static information about globals used in a function. class GlobalInfo { public: IDPtr id; int slot; }; // These are the counterparts to CaseMapI and CaseMapsI in ZAM.h, // but concretized to use instruction numbers rather than pointers // to instructions. template using CaseMap = std::map; template using CaseMaps = std::vector>; using TableIterVec = std::vector; class ZBody : public Stmt { public: ZBody(const char* _func_name, const ZAMCompiler* zc); ~ZBody() override; // These are split out from the constructor to allow construction // of a ZBody from either save-file full instructions (first method, // not currently supported) or intermediary instructions (second method). void SetInsts(std::vector& insts); void SetInsts(std::vector& instsI); ValPtr Exec(Frame* f, StmtFlowType& flow) override; // Older code exists for save files, but let's see if we can // avoid having to support them, as they're a fairly elaborate // production. // // void SaveTo(FILE* f, int interp_frame_size) const; void Dump() const; void ProfileExecution() const; protected: friend class ZAMResumption; // Initializes profiling information, if needed. void InitProfile(); ValPtr DoExec(Frame* f, int start_pc, StmtFlowType& flow); // Run-time checking for "any" type being consistent with // expected typed. Returns true if the type match is okay. bool CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, const Location* loc) const; StmtPtr Duplicate() override { return {NewRef{}, this}; } void StmtDescribe(ODesc* d) const override; TraversalCode Traverse(TraversalCallback* cb) const override; private: const char* func_name = nullptr; const ZInst* insts = nullptr; unsigned int ninst; FrameReMap frame_denizens; int frame_size; // A list of frame slots that correspond to managed values. std::vector managed_slots; // This is non-nil if the function is (asserted to be) non-recursive, // in which case we pre-allocate this. ZVal* fixed_frame = nullptr; // Pre-allocated table iteration values. For recursive invocations, // these are copied into a local stack variable, but for non-recursive // functions they can be used directly. TableIterVec table_iters; // Points to the TableIterVec used to manage iteration over tables. // For non-recursive functions, we just use the static one, but // for recursive ones this points to the local stack variable. TableIterVec* tiv_ptr = &table_iters; // Number of StepIterInfo's required by the function. These we // always create using a local stack variable, since they don't // require any overhead or cleanup. int num_step_iters; std::vector globals; int num_globals; // The following are only maintained if we're doing profiling. // // These need to be pointers so we can manipulate them in a // const method. std::vector* inst_count = nullptr; // for profiling double* CPU_time = nullptr; // cumulative CPU time for the program std::vector* inst_CPU = nullptr; // per-instruction CPU time. CaseMaps int_cases; CaseMaps uint_cases; CaseMaps double_cases; CaseMaps str_cases; }; // This is a statement that resumes execution into a code block in a // ZBody. Used for deferred execution for "when" statements. class ZAMResumption : public Stmt { public: ZAMResumption(ZBody* _am, int _xfer_pc) : Stmt(STMT_ZAM_RESUMPTION), am(_am), xfer_pc(_xfer_pc) { } ValPtr Exec(Frame* f, StmtFlowType& flow) override; StmtPtr Duplicate() override { return {NewRef{}, this}; } void StmtDescribe(ODesc* d) const override; protected: TraversalCode Traverse(TraversalCallback* cb) const override; ZBody* am; int xfer_pc = 0; }; // Prints the execution profile. extern void report_ZOP_profile(); } // namespace zeek::detail