diff --git a/src/script_opt/CPP/Compile.h b/src/script_opt/CPP/Compile.h index 6aad9eb1e9..447427204e 100644 --- a/src/script_opt/CPP/Compile.h +++ b/src/script_opt/CPP/Compile.h @@ -792,6 +792,7 @@ private: std::string GenIndexExpr(const Expr* e, GenType gt); std::string GenAssignExpr(const Expr* e, GenType gt, bool top_level); std::string GenAddToExpr(const Expr* e, GenType gt, bool top_level); + std::string GenRemoveFromExpr(const Expr* e, GenType gt, bool top_level); std::string GenSizeExpr(const Expr* e, GenType gt); std::string GenScheduleExpr(const Expr* e); std::string GenLambdaExpr(const Expr* e); diff --git a/src/script_opt/CPP/Exprs.cc b/src/script_opt/CPP/Exprs.cc index a9c41a8377..fed8ddcbe9 100644 --- a/src/script_opt/CPP/Exprs.cc +++ b/src/script_opt/CPP/Exprs.cc @@ -77,8 +77,6 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level) return GenBinary(e, gt, "+", "add"); case EXPR_SUB: return GenBinary(e, gt, "-", "sub"); - case EXPR_REMOVE_FROM: - return GenBinary(e, gt, "-="); case EXPR_TIMES: return GenBinary(e, gt, "*", "mul"); case EXPR_DIVIDE: @@ -127,6 +125,8 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level) return GenAssignExpr(e, gt, top_level); case EXPR_ADD_TO: return GenAddToExpr(e, gt, top_level); + case EXPR_REMOVE_FROM: + return GenRemoveFromExpr(e, gt, top_level); case EXPR_REF: return GenExpr(e->GetOp1(), gt); case EXPR_SIZE: @@ -476,16 +476,34 @@ string CPPCompile::GenAssignExpr(const Expr* e, GenType gt, bool top_level) string CPPCompile::GenAddToExpr(const Expr* e, GenType gt, bool top_level) { const auto& t = e->GetType(); + auto lhs = e->GetOp1(); + auto rhs = e->GetOp2(); + + std::string add_to_func; if ( t->Tag() == TYPE_VECTOR ) { - auto gen = string("vector_append__CPP(") + GenExpr(e->GetOp1(), GEN_VAL_PTR) + ", " + - GenExpr(e->GetOp2(), GEN_VAL_PTR) + ")"; + if ( same_type(lhs->GetType(), rhs->GetType()) ) + add_to_func = "vector_vec_append__CPP"; + else + add_to_func = "vector_append__CPP"; + } + + else if ( t->Tag() == TYPE_PATTERN ) + add_to_func = "re_append__CPP"; + + else if ( t->Tag() == TYPE_TABLE ) + add_to_func = "table_append__CPP"; + + if ( ! add_to_func.empty() ) + { + auto gen = add_to_func + "(" + GenExpr(lhs, GEN_VAL_PTR) + ", " + + GenExpr(rhs, GEN_VAL_PTR) + ")"; return GenericValPtrToGT(gen, t, gt); } - // Second GetOp1 is because for non-vectors, LHS will be a RefExpr. - auto lhs = e->GetOp1()->GetOp1(); + // Second GetOp1 is because if we get this far, LHS will be a RefExpr. + lhs = lhs->GetOp1(); if ( t->Tag() == TYPE_STRING ) { @@ -499,7 +517,7 @@ string CPPCompile::GenAddToExpr(const Expr* e, GenType gt, bool top_level) { // LHS is a compound, or a global (and thus doesn't // equate to a C++ variable); expand x += y to x = x + y - auto rhs = make_intrusive(lhs, e->GetOp2()); + rhs = make_intrusive(lhs, rhs); auto assign = make_intrusive(lhs, rhs, false, nullptr, nullptr, false); // Make sure any newly created types are known to @@ -513,6 +531,40 @@ string CPPCompile::GenAddToExpr(const Expr* e, GenType gt, bool top_level) return GenBinary(e, gt, "+="); } +string CPPCompile::GenRemoveFromExpr(const Expr* e, GenType gt, bool top_level) + { + const auto& t = e->GetType(); + auto lhs = e->GetOp1(); + auto rhs = e->GetOp2(); + + if ( t->Tag() == TYPE_TABLE && same_type(lhs->GetType(), rhs->GetType()) ) + { + auto gen = std::string("table_remove_from__CPP(") + GenExpr(lhs, GEN_VAL_PTR) + ", " + + GenExpr(rhs, GEN_VAL_PTR) + ")"; + return GenericValPtrToGT(gen, t, gt); + } + + // Second GetOp1 is because if we get this far, LHS will be a RefExpr. + lhs = lhs->GetOp1(); + + if ( lhs->Tag() != EXPR_NAME || lhs->AsNameExpr()->Id()->IsGlobal() ) + { + // LHS is a compound, or a global (and thus doesn't + // equate to a C++ variable); expand x -= y to x = x - y + rhs = make_intrusive(lhs, rhs); + auto assign = make_intrusive(lhs, rhs, false, nullptr, nullptr, false); + + // Make sure any newly created types are known to + // the profiler. + (void)pfs.HashType(rhs->GetType()); + (void)pfs.HashType(assign->GetType()); + + return GenExpr(assign, gt, top_level); + } + + return GenBinary(e, gt, "-="); + } + string CPPCompile::GenSizeExpr(const Expr* e, GenType gt) { const auto& t = e->GetType(); diff --git a/src/script_opt/CPP/RuntimeOps.h b/src/script_opt/CPP/RuntimeOps.h index c0ea9231f9..02df049eb9 100644 --- a/src/script_opt/CPP/RuntimeOps.h +++ b/src/script_opt/CPP/RuntimeOps.h @@ -113,6 +113,21 @@ inline TableValPtr table_coerce__CPP(const ValPtr& v, const TypePtr& t) return make_intrusive(cast_intrusive(t), tv->GetAttrs()); } +// For tables, executes t1 += t2. +inline TableValPtr table_append__CPP(const TableValPtr& t1, const TableValPtr& t2) + { + t2->AddTo(t1.get(), false); + return t1; + } + +// For tables, executes t1 -= t2. +inline TableValPtr table_remove_from__CPP(const TableValPtr& t1, const TableValPtr& t2) + { + if ( t2->Size() > 0 ) + t2->RemoveFrom(t1.get()); + return t1; + } + // The same, for an empty record. inline VectorValPtr vector_coerce__CPP(const ValPtr& v, const TypePtr& t) { @@ -147,6 +162,13 @@ extern RecordValPtr record_constructor_map__CPP(std::vector vals, std::v // Constructs a vector of the given type, populated with the given values. extern VectorValPtr vector_constructor__CPP(std::vector vals, VectorTypePtr t); +// For patterns, executes p1 += p2. +inline PatternValPtr re_append__CPP(const PatternValPtr& p1, const PatternValPtr& p2) + { + p2->AddTo(p1.get(), false); + return p1; + } + // Schedules an event to occur at the given absolute time, parameterized // with the given set of values. A separate function to facilitate avoiding // the scheduling if Zeek is terminating. diff --git a/src/script_opt/CPP/RuntimeVec.h b/src/script_opt/CPP/RuntimeVec.h index 2dfe1374c3..41be84c55f 100644 --- a/src/script_opt/CPP/RuntimeVec.h +++ b/src/script_opt/CPP/RuntimeVec.h @@ -15,10 +15,17 @@ namespace zeek::detail // Appends v2 to the vector v1. A separate function because of the // need to support assignment cascades. -inline ValPtr vector_append__CPP(VectorValPtr v1, ValPtr v2) +inline ValPtr vector_append__CPP(VectorValPtr v1, const ValPtr& v2) { v1->Assign(v1->Size(), v2); - return v2; + return v1; + } + +// Appends vector v2 to the vector v1. +inline ValPtr vector_vec_append__CPP(VectorValPtr v1, const VectorValPtr& v2) + { + v2->AddTo(v1.get(), false); + return v1; } // Unary vector operations.