diff --git a/src/script_opt/Expr.cc b/src/script_opt/Expr.cc index 64ac636000..e7e4070834 100644 --- a/src/script_opt/Expr.cc +++ b/src/script_opt/Expr.cc @@ -1468,7 +1468,7 @@ ExprPtr AssignExpr::Reduce(Reducer* c, StmtPtr& red_stmt) { auto ind1_e = ind_e->Op1()->Reduce(c, ind1_stmt); auto ind2_e = ind_e->Op2()->Reduce(c, ind2_stmt); - auto rhs_e = op2->Reduce(c, rhs_stmt); + auto rhs_e = op2->ReduceToSingleton(c, rhs_stmt); red_stmt = MergeStmts(MergeStmts(rhs_reduce, ind1_stmt), ind2_stmt, rhs_stmt); diff --git a/src/script_opt/ScriptOpt.cc b/src/script_opt/ScriptOpt.cc index 91db971d19..191c61feef 100644 --- a/src/script_opt/ScriptOpt.cc +++ b/src/script_opt/ScriptOpt.cc @@ -56,7 +56,7 @@ bool is_lambda(const ScriptFunc* f) { return lambdas.count(f) > 0; } bool is_when_lambda(const ScriptFunc* f) { return when_lambdas.count(f) > 0; } -const FuncInfo* analyze_global_stmts(Stmt* stmts) { +size_t analyze_global_stmts(Stmt* stmts) { // We ignore analysis_options.only_{files,funcs} - if they're in use, later // logic will keep this function from being compiled, but it's handy // now to enter it into "funcs" so we have a FuncInfo to return. @@ -72,9 +72,11 @@ const FuncInfo* analyze_global_stmts(Stmt* stmts) { global_stmts->AddBody(stmts->ThisPtr(), empty_inits, sc->Length()); funcs.emplace_back(global_stmts, sc, stmts->ThisPtr(), 0); - return &funcs.back(); + return funcs.size() - 1; } +const FuncInfo& get_global_stmts(size_t global_ind) { return funcs[global_ind]; } + void add_func_analysis_pattern(AnalyOpt& opts, const char* pat) { try { std::string full_pat = std::string("^(") + pat + ")$"; diff --git a/src/script_opt/ScriptOpt.h b/src/script_opt/ScriptOpt.h index 88c7f2f2cc..f7ef8a69a8 100644 --- a/src/script_opt/ScriptOpt.h +++ b/src/script_opt/ScriptOpt.h @@ -171,9 +171,16 @@ extern bool is_lambda(const ScriptFunc* f); extern bool is_when_lambda(const ScriptFunc* 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); +// an opaque value that can be provided to get_global_stmts() to retrieve +// the corresponding FuncInfo, which reflects an argument-less quasi-function +// that can be Invoked, or its body executed directly, to execute the +// statements. This indirection is used in case in between the call to +// analyze_global_stmts() and using the value subsequently, the FuncInfo may +// have been updated or shifted. 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 size_t analyze_global_stmts(Stmt* stmts); +extern const FuncInfo& get_global_stmts(size_t handle); // Add a pattern to the "only_funcs" list. extern void add_func_analysis_pattern(AnalyOpt& opts, const char* pat); diff --git a/src/script_opt/Stmt.cc b/src/script_opt/Stmt.cc index 444bda789f..3edb9f183d 100644 --- a/src/script_opt/Stmt.cc +++ b/src/script_opt/Stmt.cc @@ -171,7 +171,7 @@ void IfStmt::Inline(Inliner* inl) { } bool IfStmt::IsReduced(Reducer* c) const { - if ( ! e->IsReducedConditional(c) ) + if ( e->IsConst() || ! e->IsReducedConditional(c) ) return NonReduced(e.get()); return s1->IsReduced(c) && s2->IsReduced(c); @@ -707,7 +707,7 @@ bool StmtList::ReduceStmt(unsigned int& s_i, std::vector& f_stmts, Redu if ( e->Tag() != EXPR_ASSIGN ) { f_stmts.push_back(std::move(stmt)); - return false; + return did_change; } auto a = e->AsAssignExpr(); @@ -715,7 +715,7 @@ bool StmtList::ReduceStmt(unsigned int& s_i, std::vector& f_stmts, Redu if ( lhs->Tag() != EXPR_NAME ) { f_stmts.push_back(std::move(stmt)); - return false; + return did_change; } auto var = lhs->AsNameExpr(); diff --git a/src/script_opt/ZAM/Ops.in b/src/script_opt/ZAM/Ops.in index e407676ba4..d9acb601cc 100644 --- a/src/script_opt/ZAM/Ops.in +++ b/src/script_opt/ZAM/Ops.in @@ -2089,7 +2089,7 @@ macro BuildWhen(timeout) if ( v ) local_aggrs.push_back(v); } - (void)make_intrusive(wi, wi->WhenExprGlobals(), local_aggrs, timeout, f, z.loc); + (void)make_intrusive(wi, wi->WhenExprGlobals(), local_aggrs, timeout, f, z.loc.get()); ######################################## # Internal diff --git a/src/script_opt/ZAM/Support.cc b/src/script_opt/ZAM/Support.cc index 0cba184fd0..34055b1ace 100644 --- a/src/script_opt/ZAM/Support.cc +++ b/src/script_opt/ZAM/Support.cc @@ -77,8 +77,8 @@ void ZAM_run_time_error(const char* msg) { ZAM_error = true; } -void ZAM_run_time_error(const Location* loc, const char* msg) { - reporter->RuntimeError(loc, "%s", msg); +void ZAM_run_time_error(std::shared_ptr loc, const char* msg) { + reporter->RuntimeError(loc.get(), "%s", msg); ZAM_error = true; } @@ -87,12 +87,12 @@ void ZAM_run_time_error(const char* msg, const Obj* o) { ZAM_error = true; } -void ZAM_run_time_error(const Location* loc, const char* msg, const Obj* o) { - reporter->RuntimeError(loc, "%s (%s)", msg, obj_desc(o).c_str()); +void ZAM_run_time_error(std::shared_ptr loc, const char* msg, const Obj* o) { + reporter->RuntimeError(loc.get(), "%s (%s)", msg, obj_desc(o).c_str()); ZAM_error = true; } -void ZAM_run_time_warning(const Location* loc, const char* msg) { +void ZAM_run_time_warning(std::shared_ptr loc, const char* msg) { ODesc d; loc->Describe(&d); diff --git a/src/script_opt/ZAM/Support.h b/src/script_opt/ZAM/Support.h index 9aa61e04be..ecf7b3e40b 100644 --- a/src/script_opt/ZAM/Support.h +++ b/src/script_opt/ZAM/Support.h @@ -35,14 +35,14 @@ extern TypePtr log_ID_enum_type; extern TypePtr any_base_type; extern void ZAM_run_time_error(const char* msg); -extern void ZAM_run_time_error(const Location* loc, const char* msg); -extern void ZAM_run_time_error(const Location* loc, const char* msg, const Obj* o); +extern void ZAM_run_time_error(std::shared_ptr loc, const char* msg); +extern void ZAM_run_time_error(std::shared_ptr loc, const char* msg, const Obj* o); extern void ZAM_run_time_error(const Stmt* stmt, const char* msg); extern void ZAM_run_time_error(const char* msg, const Obj* o); extern bool ZAM_error; -extern void ZAM_run_time_warning(const Location* loc, const char* msg); +extern void ZAM_run_time_warning(std::shared_ptr loc, const char* msg); extern StringVal* ZAM_to_lower(const StringVal* sv); extern StringVal* ZAM_sub_bytes(const StringVal* s, zeek_uint_t start, zeek_int_t n); diff --git a/src/script_opt/ZAM/ZBody.cc b/src/script_opt/ZAM/ZBody.cc index 42db4a58f4..9b77da28ff 100644 --- a/src/script_opt/ZAM/ZBody.cc +++ b/src/script_opt/ZAM/ZBody.cc @@ -194,8 +194,12 @@ void ZBody::SetInsts(vector& instsI) { for ( auto i = 0U; i < end_pc; ++i ) { auto& iI = *instsI[i]; insts_copy[i] = iI; - if ( iI.stmt ) - insts_copy[i].loc = iI.stmt->Original()->GetLocationInfo(); + if ( iI.stmt ) { + auto l = iI.stmt->Original()->GetLocationInfo(); + if ( l != &no_location ) + insts_copy[i].loc = std::make_shared(util::copy_string(l->filename), l->first_line, + l->last_line, l->first_column, l->last_column); + } } insts = insts_copy; @@ -358,7 +362,8 @@ void ZBody::ProfileExecution() const { } } -bool ZBody::CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, const Location* loc) const { +bool ZBody::CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, + const std::shared_ptr& loc) const { if ( IsAny(expected_type) ) return true; @@ -377,7 +382,7 @@ bool ZBody::CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, char buf[8192]; snprintf(buf, sizeof buf, "run-time type clash (%s/%s)", type_name(at), type_name(et)); - reporter->RuntimeError(loc, "%s", buf); + reporter->RuntimeError(loc.get(), "%s", buf); return false; } diff --git a/src/script_opt/ZAM/ZBody.h b/src/script_opt/ZAM/ZBody.h index 984f1e1864..b00993cad3 100644 --- a/src/script_opt/ZAM/ZBody.h +++ b/src/script_opt/ZAM/ZBody.h @@ -58,7 +58,8 @@ protected: // 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; + bool CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type, + const std::shared_ptr& loc) const; StmtPtr Duplicate() override { return {NewRef{}, this}; } diff --git a/src/script_opt/ZAM/ZInst.h b/src/script_opt/ZAM/ZInst.h index 39de5d1e76..2d58b7ac2e 100644 --- a/src/script_opt/ZAM/ZInst.h +++ b/src/script_opt/ZAM/ZInst.h @@ -121,7 +121,7 @@ public: ZInstAux* aux = nullptr; // Location associated with this instruction, for error reporting. - const Location* loc = nullptr; + std::shared_ptr loc; // Interpreter call expression associated with this instruction, // for error reporting and stack backtraces. diff --git a/src/zeek-setup.cc b/src/zeek-setup.cc index 4b45dbf57a..80aad3cdbf 100644 --- a/src/zeek-setup.cc +++ b/src/zeek-setup.cc @@ -923,7 +923,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) { exit(reporter->Errors() != 0); } - auto init_stmts = stmts ? analyze_global_stmts(stmts) : nullptr; + auto init_stmts_handle = stmts ? analyze_global_stmts(stmts) : 0; analyze_scripts(options.no_unused_warnings); @@ -1025,13 +1025,14 @@ SetupResult setup(int argc, char** argv, Options* zopts) { // cause more severe problems. ZEEK_LSAN_ENABLE(); - if ( init_stmts ) { + if ( stmts ) { + auto& init_stmts = get_global_stmts(init_stmts_handle); StmtFlowType flow; - Frame f(init_stmts->Scope()->Length(), nullptr, nullptr); + Frame f(init_stmts.Scope()->Length(), nullptr, nullptr); g_frame_stack.push_back(&f); try { - init_stmts->Body()->Exec(&f, flow); + init_stmts.Body()->Exec(&f, flow); } catch ( InterpreterException& ) { reporter->FatalError("failed to execute script statements at top-level scope"); }