mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
-O gen-C++ refinements for BiF failures, negative vector indices, boolean vector operations
This commit is contained in:
parent
f64304067b
commit
18be4ba91b
9 changed files with 94 additions and 30 deletions
|
@ -776,7 +776,7 @@ private:
|
||||||
std::string GenConstExpr(const ConstExpr* c, GenType gt);
|
std::string GenConstExpr(const ConstExpr* c, GenType gt);
|
||||||
std::string GenIncrExpr(const Expr* e, GenType gt, bool is_incr, bool top_level);
|
std::string GenIncrExpr(const Expr* e, GenType gt, bool is_incr, bool top_level);
|
||||||
std::string GenCondExpr(const Expr* e, GenType gt);
|
std::string GenCondExpr(const Expr* e, GenType gt);
|
||||||
std::string GenCallExpr(const CallExpr* c, GenType gt);
|
std::string GenCallExpr(const CallExpr* c, GenType gt, bool top_level);
|
||||||
std::string GenInExpr(const Expr* e, GenType gt);
|
std::string GenInExpr(const Expr* e, GenType gt);
|
||||||
std::string GenFieldExpr(const FieldExpr* fe, GenType gt);
|
std::string GenFieldExpr(const FieldExpr* fe, GenType gt);
|
||||||
std::string GenHasFieldExpr(const HasFieldExpr* hfe, GenType gt);
|
std::string GenHasFieldExpr(const HasFieldExpr* hfe, GenType gt);
|
||||||
|
|
|
@ -114,7 +114,7 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level)
|
||||||
case EXPR_COND:
|
case EXPR_COND:
|
||||||
return GenCondExpr(e, gt);
|
return GenCondExpr(e, gt);
|
||||||
case EXPR_CALL:
|
case EXPR_CALL:
|
||||||
return GenCallExpr(e->AsCallExpr(), gt);
|
return GenCallExpr(e->AsCallExpr(), gt, top_level);
|
||||||
case EXPR_LIST:
|
case EXPR_LIST:
|
||||||
return GenListExpr(e, gt, false);
|
return GenListExpr(e, gt, false);
|
||||||
case EXPR_IN:
|
case EXPR_IN:
|
||||||
|
@ -291,7 +291,7 @@ string CPPCompile::GenCondExpr(const Expr* e, GenType gt)
|
||||||
return string("(") + gen1 + ") ? (" + gen2 + ") : (" + gen3 + ")";
|
return string("(") + gen1 + ") ? (" + gen2 + ") : (" + gen3 + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
string CPPCompile::GenCallExpr(const CallExpr* c, GenType gt)
|
string CPPCompile::GenCallExpr(const CallExpr* c, GenType gt, bool top_level)
|
||||||
{
|
{
|
||||||
const auto& t = c->GetType();
|
const auto& t = c->GetType();
|
||||||
auto f = c->Func();
|
auto f = c->Func();
|
||||||
|
@ -347,7 +347,18 @@ string CPPCompile::GenCallExpr(const CallExpr* c, GenType gt)
|
||||||
// Indirect call.
|
// Indirect call.
|
||||||
gen = string("(") + gen + ")->AsFunc()";
|
gen = string("(") + gen + ")->AsFunc()";
|
||||||
|
|
||||||
string invoke_func = is_async ? "when_invoke__CPP" : "invoke__CPP";
|
string invoke_func;
|
||||||
|
|
||||||
|
if ( is_async )
|
||||||
|
invoke_func = "when_invoke__CPP";
|
||||||
|
else if ( t->Tag() == TYPE_VOID )
|
||||||
|
{
|
||||||
|
ASSERT(top_level);
|
||||||
|
invoke_func = "invoke_void__CPP";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
invoke_func = "invoke__CPP";
|
||||||
|
|
||||||
auto args_list = string(", {") + GenExpr(args_l, GEN_VAL_PTR) + "}";
|
auto args_list = string(", {") + GenExpr(args_l, GEN_VAL_PTR) + "}";
|
||||||
auto invoker = invoke_func + "(" + gen + args_list + ", f__CPP";
|
auto invoker = invoke_func + "(" + gen + args_list + ", f__CPP";
|
||||||
|
|
||||||
|
@ -356,6 +367,10 @@ string CPPCompile::GenCallExpr(const CallExpr* c, GenType gt)
|
||||||
|
|
||||||
invoker += ")";
|
invoker += ")";
|
||||||
|
|
||||||
|
if ( top_level )
|
||||||
|
// No need to use accessor.
|
||||||
|
return invoker;
|
||||||
|
|
||||||
if ( IsNativeType(t) && gt != GEN_VAL_PTR )
|
if ( IsNativeType(t) && gt != GEN_VAL_PTR )
|
||||||
return invoker + NativeAccessor(t);
|
return invoker + NativeAccessor(t);
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,13 @@ ValPtr index_table__CPP(const TableValPtr& t, vector<ValPtr> indices)
|
||||||
|
|
||||||
ValPtr index_vec__CPP(const VectorValPtr& vec, int index)
|
ValPtr index_vec__CPP(const VectorValPtr& vec, int index)
|
||||||
{
|
{
|
||||||
|
if ( index < 0 )
|
||||||
|
index += vec->Size();
|
||||||
|
|
||||||
auto v = vec->ValAt(index);
|
auto v = vec->ValAt(index);
|
||||||
if ( ! v )
|
if ( ! v )
|
||||||
reporter->CPPRuntimeError("no such index");
|
reporter->CPPRuntimeError("no such index");
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,12 +48,28 @@ extern ValPtr when_index_vec__CPP(const VectorValPtr& vec, int index);
|
||||||
// custom one for those occurring inside a "when" clause.
|
// custom one for those occurring inside a "when" clause.
|
||||||
extern ValPtr when_index_slice__CPP(VectorVal* vec, const ListVal* lv);
|
extern ValPtr when_index_slice__CPP(VectorVal* vec, const ListVal* lv);
|
||||||
|
|
||||||
|
// Calls out to the given script or BiF function, which does not return
|
||||||
|
// a value.
|
||||||
|
inline ValPtr invoke_void__CPP(Func* f, std::vector<ValPtr> args, Frame* frame)
|
||||||
|
{
|
||||||
|
return f->Invoke(&args, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for error propagation by failed calls.
|
||||||
|
class CPPInterpreterException : public InterpreterException
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
// Calls out to the given script or BiF function. A separate function because
|
// Calls out to the given script or BiF function. A separate function because
|
||||||
// of the need to (1) construct the "args" vector using {} initializers,
|
// of the need to (1) construct the "args" vector using {} initializers,
|
||||||
// but (2) needing to have the address of that vector.
|
// but (2) needing to have the address of that vector.
|
||||||
inline ValPtr invoke__CPP(Func* f, std::vector<ValPtr> args, Frame* frame)
|
inline ValPtr invoke__CPP(Func* f, std::vector<ValPtr> args, Frame* frame)
|
||||||
{
|
{
|
||||||
return f->Invoke(&args, frame);
|
auto v = f->Invoke(&args, frame);
|
||||||
|
if ( ! v )
|
||||||
|
throw CPPInterpreterException();
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The same, but raises an interpreter exception if the function does
|
// The same, but raises an interpreter exception if the function does
|
||||||
|
|
|
@ -26,12 +26,17 @@ static bool check_vec_sizes__CPP(const VectorValPtr& v1, const VectorValPtr& v2)
|
||||||
// (for example, adding one vector of "interval" to another), which
|
// (for example, adding one vector of "interval" to another), which
|
||||||
// we want to do using the low-level representations. We'll later
|
// we want to do using the low-level representations. We'll later
|
||||||
// convert the vector to the high-level representation if needed.
|
// convert the vector to the high-level representation if needed.
|
||||||
static VectorTypePtr base_vector_type__CPP(const VectorTypePtr& vt)
|
//
|
||||||
|
// One exception: for booleans ("is_bool" is true), we use those directly.
|
||||||
|
static VectorTypePtr base_vector_type__CPP(const VectorTypePtr& vt, bool is_bool = false)
|
||||||
{
|
{
|
||||||
switch ( vt->Yield()->InternalType() )
|
switch ( vt->Yield()->InternalType() )
|
||||||
{
|
{
|
||||||
case TYPE_INTERNAL_INT:
|
case TYPE_INTERNAL_INT:
|
||||||
return make_intrusive<VectorType>(base_type(TYPE_INT));
|
{
|
||||||
|
auto base_tag = is_bool ? TYPE_BOOL : TYPE_INT;
|
||||||
|
return make_intrusive<VectorType>(base_type(base_tag));
|
||||||
|
}
|
||||||
|
|
||||||
case TYPE_INTERNAL_UNSIGNED:
|
case TYPE_INTERNAL_UNSIGNED:
|
||||||
return make_intrusive<VectorType>(base_type(TYPE_COUNT));
|
return make_intrusive<VectorType>(base_type(TYPE_COUNT));
|
||||||
|
@ -119,36 +124,27 @@ VEC_OP1(comp, ~, )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analogous to VEC_OP1, instantiates a function for a given binary operation,
|
// Analogous to VEC_OP1, instantiates a function for a given binary operation,
|
||||||
// which might-or-might-not be supported for low-level "double" types.
|
// with customimzable kernels for "int" and "double" operations.
|
||||||
// This version is for operations whose result type is the same as the
|
// This version is for operations whose result type is the same as the
|
||||||
// operand type.
|
// operand type.
|
||||||
#define VEC_OP2(name, op, double_kernel, zero_check) \
|
#define VEC_OP2(name, op, int_kernel, double_kernel, zero_check, is_bool) \
|
||||||
VectorValPtr vec_op_##name##__CPP(const VectorValPtr& v1, const VectorValPtr& v2) \
|
VectorValPtr vec_op_##name##__CPP(const VectorValPtr& v1, const VectorValPtr& v2) \
|
||||||
{ \
|
{ \
|
||||||
if ( ! check_vec_sizes__CPP(v1, v2) ) \
|
if ( ! check_vec_sizes__CPP(v1, v2) ) \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
\
|
\
|
||||||
auto vt = base_vector_type__CPP(v1->GetType<VectorType>()); \
|
auto vt = base_vector_type__CPP(v1->GetType<VectorType>(), is_bool); \
|
||||||
auto v_result = make_intrusive<VectorVal>(vt); \
|
auto v_result = make_intrusive<VectorVal>(vt); \
|
||||||
\
|
\
|
||||||
switch ( vt->Yield()->InternalType() ) \
|
switch ( vt->Yield()->InternalType() ) \
|
||||||
{ \
|
{ \
|
||||||
case TYPE_INTERNAL_INT: \
|
|
||||||
{ \
|
|
||||||
if ( vt->Yield()->Tag() == TYPE_BOOL ) \
|
|
||||||
VEC_OP2_KERNEL(AsBool, BoolVal, op, zero_check) \
|
|
||||||
else \
|
|
||||||
VEC_OP2_KERNEL(AsInt, IntVal, op, zero_check) \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
case TYPE_INTERNAL_UNSIGNED: \
|
case TYPE_INTERNAL_UNSIGNED: \
|
||||||
{ \
|
{ \
|
||||||
VEC_OP2_KERNEL(AsCount, CountVal, op, zero_check) \
|
VEC_OP2_KERNEL(AsCount, CountVal, op, zero_check) \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
double_kernel \
|
int_kernel double_kernel \
|
||||||
\
|
\
|
||||||
default : break; \
|
default : break; \
|
||||||
} \
|
} \
|
||||||
|
@ -156,9 +152,29 @@ VEC_OP1(comp, ~, )
|
||||||
return v_result; \
|
return v_result; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instantiates a regular int_kernel for a binary operation.
|
||||||
|
#define VEC_OP2_WITH_INT(name, op, double_kernel, zero_check) \
|
||||||
|
VEC_OP2( \
|
||||||
|
name, op, case TYPE_INTERNAL_INT \
|
||||||
|
: { \
|
||||||
|
VEC_OP2_KERNEL(AsInt, IntVal, op, zero_check) \
|
||||||
|
break; \
|
||||||
|
}, \
|
||||||
|
double_kernel, zero_check, false)
|
||||||
|
|
||||||
|
// Instantiates an int_kernel for boolean operations.
|
||||||
|
#define VEC_OP2_WITH_BOOL(name, op, zero_check) \
|
||||||
|
VEC_OP2( \
|
||||||
|
name, op, case TYPE_INTERNAL_INT \
|
||||||
|
: { \
|
||||||
|
VEC_OP2_KERNEL(AsBool, BoolVal, op, zero_check) \
|
||||||
|
break; \
|
||||||
|
}, \
|
||||||
|
, zero_check, true)
|
||||||
|
|
||||||
// Instantiates a double_kernel for a binary operation.
|
// Instantiates a double_kernel for a binary operation.
|
||||||
#define VEC_OP2_WITH_DOUBLE(name, op, zero_check) \
|
#define VEC_OP2_WITH_DOUBLE(name, op, zero_check) \
|
||||||
VEC_OP2( \
|
VEC_OP2_WITH_INT( \
|
||||||
name, op, case TYPE_INTERNAL_DOUBLE \
|
name, op, case TYPE_INTERNAL_DOUBLE \
|
||||||
: { \
|
: { \
|
||||||
VEC_OP2_KERNEL(AsDouble, DoubleVal, op, zero_check) \
|
VEC_OP2_KERNEL(AsDouble, DoubleVal, op, zero_check) \
|
||||||
|
@ -171,14 +187,14 @@ VEC_OP2_WITH_DOUBLE(add, +, 0)
|
||||||
VEC_OP2_WITH_DOUBLE(sub, -, 0)
|
VEC_OP2_WITH_DOUBLE(sub, -, 0)
|
||||||
VEC_OP2_WITH_DOUBLE(mul, *, 0)
|
VEC_OP2_WITH_DOUBLE(mul, *, 0)
|
||||||
VEC_OP2_WITH_DOUBLE(div, /, 1)
|
VEC_OP2_WITH_DOUBLE(div, /, 1)
|
||||||
VEC_OP2(mod, %, , 1)
|
VEC_OP2_WITH_INT(mod, %, , 1)
|
||||||
VEC_OP2(and, &, , 0)
|
VEC_OP2_WITH_INT(and, &, , 0)
|
||||||
VEC_OP2(or, |, , 0)
|
VEC_OP2_WITH_INT(or, |, , 0)
|
||||||
VEC_OP2(xor, ^, , 0)
|
VEC_OP2_WITH_INT(xor, ^, , 0)
|
||||||
VEC_OP2(andand, &&, , 0)
|
VEC_OP2_WITH_BOOL(andand, &&, 0)
|
||||||
VEC_OP2(oror, ||, , 0)
|
VEC_OP2_WITH_BOOL(oror, ||, 0)
|
||||||
VEC_OP2(lshift, <<, , 0)
|
VEC_OP2_WITH_INT(lshift, <<, , 0)
|
||||||
VEC_OP2(rshift, >>, , 0)
|
VEC_OP2_WITH_INT(rshift, >>, , 0)
|
||||||
|
|
||||||
// A version of VEC_OP2 that instead supports relational operations, so
|
// A version of VEC_OP2 that instead supports relational operations, so
|
||||||
// the result type is always vector-of-bool.
|
// the result type is always vector-of-bool.
|
||||||
|
|
|
@ -34,7 +34,9 @@ The maintenance workflow:
|
||||||
5. Run "check-CPP-gen.sh" for each Zeek file that passed "check-zeek.sh".
|
5. Run "check-CPP-gen.sh" for each Zeek file that passed "check-zeek.sh".
|
||||||
This will generate a corresponding file in CPP-test/out* indicating whether
|
This will generate a corresponding file in CPP-test/out* indicating whether
|
||||||
"-O gen-C++" can successfully run on the input. Presently, it should
|
"-O gen-C++" can successfully run on the input. Presently, it should
|
||||||
be able to do so for all of them.
|
be able to do so for all of them except a few that have conditional code,
|
||||||
|
which I've left active (no @TEST-REQUIRES to prune) given hopes of
|
||||||
|
soon being able to support (most) conditional code for C++ compilation.
|
||||||
|
|
||||||
This step is parallelizable, say using xargs -P 10 -n 1.
|
This step is parallelizable, say using xargs -P 10 -n 1.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
error in <...>/publish-hrw-type-check.zeek (C++), line 13: expected type Cluster::Pool for pool (<___>testing_btest__tmp_scripts_base_frameworks_cluster_publish_hrw_type_check_publish_hrw_type_check_zeek__zeek_init__34__zf())
|
||||||
|
error in <...>/publish-hrw-type-check.zeek (C++), line 13: expected type Cluster::Pool for pool (<___>testing_btest__tmp_scripts_base_frameworks_cluster_publish_hrw_type_check_publish_hrw_type_check_zeek__zeek_init__34__zf())
|
||||||
|
error in <...>/publish-hrw-type-check.zeek (C++), line 13: expected type Cluster::Pool for pool (<___>testing_btest__tmp_scripts_base_frameworks_cluster_publish_hrw_type_check_publish_hrw_type_check_zeek__zeek_init__34__zf())
|
||||||
|
error in <...>/publish-hrw-type-check.zeek (C++), line 13: expected type string for key, got port (<___>testing_btest__tmp_scripts_base_frameworks_cluster_publish_hrw_type_check_publish_hrw_type_check_zeek__zeek_init__34__zf())
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Not compatible with -O C++ testing since includes two distinct scripts.
|
||||||
|
# @TEST-REQUIRES: test "${ZEEK_USE_CPP}" != "1"
|
||||||
|
#
|
||||||
# @TEST-GROUP: broker
|
# @TEST-GROUP: broker
|
||||||
#
|
#
|
||||||
# @TEST-PORT: BROKER_PORT
|
# @TEST-PORT: BROKER_PORT
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Not compatible with -O C++ testing since includes two distinct scripts.
|
||||||
|
# @TEST-REQUIRES: test "${ZEEK_USE_CPP}" != "1"
|
||||||
|
#
|
||||||
# @TEST-GROUP: broker
|
# @TEST-GROUP: broker
|
||||||
#
|
#
|
||||||
# @TEST-PORT: BROKER_PORT
|
# @TEST-PORT: BROKER_PORT
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue