// See the file "COPYING" in the main distribution directory for copyright. // Classes for controlling/orchestrating script optimization & compilation. #pragma once #include #include #include #include "zeek/Expr.h" #include "zeek/Func.h" #include "zeek/Scope.h" namespace zeek { struct Options; } namespace zeek::detail { // Flags controlling what sorts of analysis to do. struct AnalyOpt { // If non-nil, then only analyze function/event/hook(s) whose names // match one of the given regular expressions. // // Applies to both ZAM and C++. std::vector only_funcs; // Same, but for the filenames where the function is found. std::vector only_files; // For a given compilation target, report functions that can't // be compiled. bool report_uncompilable = false; ////// Options relating to ZAM: // Whether to analyze scripts. bool activate = false; // If true, compile all compileable functions, even those that // are inlined. Mainly useful for ensuring compatibility for // some tests in the test suite. bool compile_all = false; // Whether to optimize the AST. bool optimize_AST = false; // If true, do global inlining. bool inliner = false; // If true, report which functions are directly and indirectly // recursive, and exit. Only germane if running the inliner. bool report_recursive = false; // If true, generate ZAM code for applicable function bodies, // activating all optimizations. bool gen_ZAM = false; // Generate ZAM code, but do not turn on optimizations unless // specified. bool gen_ZAM_code = false; // Deactivate the low-level ZAM optimizer. bool no_ZAM_opt = false; // Produce a profile of ZAM execution. bool profile_ZAM = false; // If true, dump out transformed code: the results of reducing // interpreted scripts, and, if optimize is set, of then optimizing // them. bool dump_xform = false; // If true, dump out the use-defs for each analyzed function. bool dump_uds = false; // If true, dump out generated ZAM code. bool dump_ZAM = false; // If non-zero, looks for variables that are used-but-possibly-not-set, // or set-but-not-used. We store this as an int rather than a bool // because we might at some point extend the analysis to deeper forms // of usage issues, such as those present in record fields. // // Included here with other ZAM-related options since conducting // the analysis requires activating some of the machinery used // for ZAM. int usage_issues = 0; ////// Options relating to C++: // If true, generate C++; bool gen_CPP = false; // If true, the C++ should be standalone (not require the presence // of the corresponding script, and not activated by default). bool gen_standalone_CPP = false; // If true, use C++ bodies if available. bool use_CPP = false; // If true, report on available C++ bodies. bool report_CPP = false; // If true, allow standalone compilation in the presence of // conditional code. bool allow_cond = false; }; extern AnalyOpt analysis_options; class ProfileFunc; using ScriptFuncPtr = IntrusivePtr; // Info we need for tracking an instance of a function. class FuncInfo { public: FuncInfo(ScriptFuncPtr _func, ScopePtr _scope, StmtPtr _body, int _priority) : func(std::move(_func)), scope(std::move(_scope)), body(std::move(_body)), priority(_priority) { } ScriptFunc* Func() const { return func.get(); } const ScriptFuncPtr& FuncPtr() const { return func; } const ScopePtr& Scope() const { return scope; } const StmtPtr& Body() const { return body; } int Priority() const { return priority; } const ProfileFunc* Profile() const { return pf.get(); } std::shared_ptr ProfilePtr() const { return pf; } void SetBody(StmtPtr new_body) { body = std::move(new_body); } // void SetProfile(std::shared_ptr _pf); void SetProfile(std::shared_ptr _pf) { pf = std::move(_pf); } // The following provide a way of marking FuncInfo's as // should-be-skipped for script optimization, generally because // the function body has a property that a given script optimizer // doesn't know how to deal with. Defaults to don't-skip. bool ShouldSkip() const { return skip; } void SetSkip(bool should_skip) { skip = should_skip; } protected: ScriptFuncPtr func; ScopePtr scope; StmtPtr body; std::shared_ptr pf; int priority; // Whether to skip optimizing this function. bool skip = false; }; // We track which functions are definitely not recursive. We do this // as the negative, rather than tracking functions known to be recursive, // so that if we don't do the analysis at all (it's driven by inlining), // we err on the conservative side and assume every function is recursive. extern std::unordered_set non_recursive_funcs; // Analyze a given function for optimization. extern void analyze_func(ScriptFuncPtr f); // Analyze the given top-level statement(s) for optimization. Returns // a pointer to a FuncInfo for an argument-less quasi-function that can // be Invoked, or its body executed directly, to execute the statements. extern const FuncInfo* analyze_global_stmts(Stmt* stmts); // Add a pattern to the "only_funcs" list. extern void add_func_analysis_pattern(AnalyOpt& opts, const char* pat); // Add a pattern to the "only_files" list. extern void add_file_analysis_pattern(AnalyOpt& opts, const char* pat); // True if the given script function & body should be analyzed; otherwise // it should be skipped. extern bool should_analyze(const ScriptFuncPtr& f, const StmtPtr& body); // Analyze all of the parsed scripts collectively for usage issues (unless // suppressed by the flag) and optimization. extern void analyze_scripts(bool no_unused_warnings); // Called when Zeek is terminating. extern void finish_script_execution(); // Used for C++-compiled scripts to signal their presence, by setting this // to a non-empty value. extern void (*CPP_init_hook)(); // Used for "standalone" C++-compiled scripts to complete their activation; // called after parsing and BiF initialization, but before zeek_init. extern void (*CPP_activation_hook)(); } // namespace zeek::detail