diff --git a/src/script_opt/CPP/Compile.h b/src/script_opt/CPP/Compile.h index 0f0f9d5de8..7c00a6ed0b 100644 --- a/src/script_opt/CPP/Compile.h +++ b/src/script_opt/CPP/Compile.h @@ -134,8 +134,8 @@ namespace zeek::detail { class CPPCompile { public: CPPCompile(std::vector& _funcs, ProfileFuncs& pfs, - const char* gen_name, CPPHashManager& hm, - bool update, bool standalone); + const std::string& gen_name, const std::string& addl_name, + CPPHashManager& _hm, bool _update, bool _standalone); ~CPPCompile(); private: @@ -390,9 +390,14 @@ private: // function. std::string GenArgs(const RecordTypePtr& params, const Expr* e); - // Functions that we've declared/compiled. + // Functions that we've declared/compiled. Indexed by full C++ name. std::unordered_set compiled_funcs; + // "Simple" functions that we've compiled, i.e., those that have + // a single body and thus can be called dirctly. Indexed by + // function name, and maps to the C++ name. + std::unordered_map compiled_simple_funcs; + // Maps those to their associated files - used to make add-C++ body // hashes distinct. std::unordered_map cf_locs; @@ -858,6 +863,12 @@ private: void AddInit(const IntrusivePtr& o) { AddInit(o.get()); } void AddInit(const Obj* o); + // This is akin to an initialization, but done separately + // (upon "activation") so it can include initializations that + // rely on parsing having finished (in particular, BiFs having + // been registered). Only used when generating standalone code. + void AddActivation(std::string a) { activations.emplace_back(a); } + // Records the fact that the initialization of object o1 depends // on that of object o2. void NoteInitDependency(const IntrusivePtr& o1, @@ -922,6 +933,10 @@ private: // other initializations, and that themselves have no dependencies). std::vector pre_inits; + // A list of "activations" (essentially, post-initializations). + // See AddActivation() above. + std::vector activations; + // Expressions for which we need to generate initialization-time // code. Currently, these are only expressions appearing in // attributes. @@ -1010,6 +1025,9 @@ private: // File to which we're generating code. FILE* write_file; + // Name of file holding potential "additional" code. + std::string addl_name; + // Indentation level. int block_level = 0; diff --git a/src/script_opt/CPP/DeclFunc.cc b/src/script_opt/CPP/DeclFunc.cc index da7b3fa377..1d4017d793 100644 --- a/src/script_opt/CPP/DeclFunc.cc +++ b/src/script_opt/CPP/DeclFunc.cc @@ -24,6 +24,9 @@ void CPPCompile::DeclareFunc(const FuncInfo& func) DeclareSubclass(f->GetType(), pf, fname, body, priority, nullptr, f->Flavor()); + + if ( f->GetBodies().size() == 1 ) + compiled_simple_funcs[f->Name()] = fname; } void CPPCompile::DeclareLambda(const LambdaExpr* l, const ProfileFunc* pf) diff --git a/src/script_opt/CPP/Driver.cc b/src/script_opt/CPP/Driver.cc index 3efe5177a1..69abcf0289 100644 --- a/src/script_opt/CPP/Driver.cc +++ b/src/script_opt/CPP/Driver.cc @@ -13,20 +13,24 @@ using namespace std; CPPCompile::CPPCompile(vector& _funcs, ProfileFuncs& _pfs, - const char* gen_name, CPPHashManager& _hm, - bool _update, bool _standalone) -: funcs(_funcs), pfs(_pfs), hm(_hm), update(_update), standalone(_standalone) + const string& gen_name, const string& _addl_name, + CPPHashManager& _hm, bool _update, bool _standalone) +: funcs(_funcs), pfs(_pfs), hm(_hm), + update(_update), standalone(_standalone) { - auto mode = hm.IsAppend() ? "a" : "w"; + addl_name = _addl_name; + bool is_addl = hm.IsAppend(); + auto target_name = is_addl ? addl_name.c_str() : gen_name.c_str(); + auto mode = is_addl ? "a" : "w"; - write_file = fopen(gen_name, mode); + write_file = fopen(target_name, mode); if ( ! write_file ) { - reporter->Error("can't open C++ target file %s", gen_name); + reporter->Error("can't open C++ target file %s", target_name); exit(1); } - if ( hm.IsAppend() ) + if ( is_addl ) { // We need a unique number to associate with the name // space for the code we're adding. A convenient way to @@ -39,7 +43,7 @@ CPPCompile::CPPCompile(vector& _funcs, ProfileFuncs& _pfs, { char buf[256]; util::zeek_strerror_r(errno, buf, sizeof(buf)); - reporter->Error("fstat failed on %s: %s", gen_name, buf); + reporter->Error("fstat failed on %s: %s", target_name, buf); exit(1); } @@ -49,6 +53,20 @@ CPPCompile::CPPCompile(vector& _funcs, ProfileFuncs& _pfs, addl_tag = st.st_size + 1; } + else + { + // Create an empty "additional" file. + auto addl_f = fopen(addl_name.c_str(), "w"); + if ( ! addl_f ) + { + reporter->Error("can't open C++ additional file %s", + addl_name.c_str()); + exit(1); + } + + fclose(addl_f); + } + Compile(); } @@ -313,7 +331,7 @@ void CPPCompile::GenEpilog() if ( addl_tag > 0 ) return; - Emit("#include \"CPP-gen-addl.h\"\n"); + Emit("#include \"" + addl_name + "\"\n"); Emit("} // zeek::detail"); } diff --git a/src/script_opt/ScriptOpt.cc b/src/script_opt/ScriptOpt.cc index 5bfc4dfee3..0cec0c1a2b 100644 --- a/src/script_opt/ScriptOpt.cc +++ b/src/script_opt/ScriptOpt.cc @@ -280,9 +280,6 @@ void analyze_scripts() // Avoid profiling overhead. return; - const auto hash_name = hash_dir + "CPP-hashes"; - const auto gen_name = hash_dir + "CPP-gen-addl.h"; - // Now that everything's parsed and BiF's have been initialized, // profile the functions. auto pfs = std::make_unique(funcs, is_CPP_compilable, false); @@ -376,6 +373,8 @@ void analyze_scripts() if ( generating_CPP ) { + const auto hash_name = hash_dir + "CPP-hashes"; + auto hm = std::make_unique(hash_name.c_str(), analysis_options.add_CPP); @@ -394,7 +393,10 @@ void analyze_scripts() pfs = std::make_unique(funcs, is_CPP_compilable, false); } - CPPCompile cpp(funcs, *pfs, gen_name.c_str(), *hm, + const auto gen_name = hash_dir + "CPP-gen.cc"; + const auto addl_name = hash_dir + "CPP-gen-addl.h"; + + CPPCompile cpp(funcs, *pfs, gen_name, addl_name, *hm, analysis_options.gen_CPP || analysis_options.update_CPP, analysis_options.gen_standalone_CPP);