mirror of
https://github.com/zeek/zeek.git
synced 2025-10-16 21:48:21 +00:00
fixes for vector coercion overflows, typing, and holes
This commit is contained in:
parent
a67897135e
commit
196b8767e8
3 changed files with 61 additions and 34 deletions
|
@ -1468,16 +1468,12 @@ void ZAM_ExprOpTemplate::InstantiateEval(const vector<ZAM_OperandType>& ot_orig,
|
||||||
{
|
{
|
||||||
string dispatch_params = "frame[z.v1].AsVectorRef(), frame[z.v2].AsVector()";
|
string dispatch_params = "frame[z.v1].AsVectorRef(), frame[z.v2].AsVector()";
|
||||||
|
|
||||||
string type_arg;
|
|
||||||
if ( Arity() == 2 )
|
if ( Arity() == 2 )
|
||||||
{
|
|
||||||
dispatch_params += ", frame[z.v3].AsVector()";
|
dispatch_params += ", frame[z.v3].AsVector()";
|
||||||
type_arg = ", z.t";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto op_code = g->GenOpCode(this, "_" + full_suffix);
|
auto op_code = g->GenOpCode(this, "_" + full_suffix);
|
||||||
auto dispatch = "vec_exec(" + op_code + type_arg +
|
auto dispatch = "vec_exec(" + op_code + ", z.t, " +
|
||||||
", " + dispatch_params + ", z);";
|
dispatch_params + ", z);";
|
||||||
|
|
||||||
ZAM_OpTemplate::InstantiateEval(Eval, full_suffix,
|
ZAM_OpTemplate::InstantiateEval(Eval, full_suffix,
|
||||||
dispatch, zc);
|
dispatch, zc);
|
||||||
|
@ -1560,6 +1556,14 @@ void ZAM_UnaryExprOpTemplate::BuildInstruction(const vector<ZAM_OperandType>& ot
|
||||||
// These can't take the type from the LHS variable, since
|
// These can't take the type from the LHS variable, since
|
||||||
// that's the enclosing record and not the field within it.
|
// that's the enclosing record and not the field within it.
|
||||||
Emit("z.t = t;");
|
Emit("z.t = t;");
|
||||||
|
|
||||||
|
else if ( zc == ZIC_VEC )
|
||||||
|
{
|
||||||
|
if ( constant_op )
|
||||||
|
Emit("z.t = n->GetType();");
|
||||||
|
else
|
||||||
|
Emit("z.t = n1->GetType();");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1142,7 +1142,7 @@ eval frame[z.v1].double_val = double(frame[z.v2].uint_val);
|
||||||
|
|
||||||
macro EvalCoerceVec(coercer)
|
macro EvalCoerceVec(coercer)
|
||||||
auto old_v1 = frame[z.v1].vector_val;
|
auto old_v1 = frame[z.v1].vector_val;
|
||||||
frame[z.v1].vector_val = coercer(frame[z.v2].vector_val);
|
frame[z.v1].vector_val = coercer(frame[z.v2].vector_val, z);
|
||||||
Unref(old_v1); // delayed to allow for same value on both sides
|
Unref(old_v1); // delayed to allow for same value on both sides
|
||||||
|
|
||||||
internal-op Coerce-UI-Vec
|
internal-op Coerce-UI-Vec
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "zeek/EventHandler.h"
|
#include "zeek/EventHandler.h"
|
||||||
#include "zeek/Trigger.h"
|
#include "zeek/Trigger.h"
|
||||||
#include "zeek/Traverse.h"
|
#include "zeek/Traverse.h"
|
||||||
|
#include "zeek/Overflow.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
#include "zeek/script_opt/ScriptOpt.h"
|
#include "zeek/script_opt/ScriptOpt.h"
|
||||||
#include "zeek/script_opt/ZAM/Compile.h"
|
#include "zeek/script_opt/ZAM/Compile.h"
|
||||||
|
@ -77,21 +78,18 @@ static bool copy_vec_elem(VectorVal* vv, int ind, ZVal zv, const TypePtr& t)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unary vector operations never work on managed types, so no need
|
// Unary and binary element-by-element vector operations, yielding a new
|
||||||
// to pass in the type ... However, the RHS, which normally would
|
// VectorVal with a yield type of 't'. 'z' is passed in only for localizing
|
||||||
// be const, needs to be non-const so we can use its Type() method
|
// errors.
|
||||||
// to get at a shareable VectorType.
|
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||||
static void vec_exec(ZOp op, VectorVal*& v1, VectorVal* v2, const ZInst& z);
|
const ZInst& z);
|
||||||
|
|
||||||
// Binary operations *can* have managed types (strings).
|
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, VectorVal* v2,
|
|
||||||
const VectorVal* v3, const ZInst& z);
|
const VectorVal* v3, const ZInst& z);
|
||||||
|
|
||||||
// Vector coercion.
|
// Vector coercion.
|
||||||
//
|
#define VEC_COERCE(tag, lhs_type, cast, rhs_accessor, ov_check, ov_err) \
|
||||||
// ### Should check for underflow/overflow.
|
static VectorVal* vec_coerce_##tag(VectorVal* vec, const ZInst& z) \
|
||||||
#define VEC_COERCE(tag, lhs_type, cast, rhs_accessor) \
|
|
||||||
static VectorVal* vec_coerce_##tag(VectorVal* vec) \
|
|
||||||
{ \
|
{ \
|
||||||
auto& v = *vec->RawVec(); \
|
auto& v = *vec->RawVec(); \
|
||||||
auto yt = make_intrusive<VectorType>(base_type(lhs_type)); \
|
auto yt = make_intrusive<VectorType>(base_type(lhs_type)); \
|
||||||
|
@ -101,18 +99,32 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, VectorVal* v2,
|
||||||
auto& res = *res_zv->RawVec(); \
|
auto& res = *res_zv->RawVec(); \
|
||||||
for ( auto i = 0U; i < n; ++i ) \
|
for ( auto i = 0U; i < n; ++i ) \
|
||||||
if ( v[i] ) \
|
if ( v[i] ) \
|
||||||
res[i] = ZVal(cast((*v[i]).rhs_accessor)); \
|
{ \
|
||||||
|
auto vi = (*v[i]).rhs_accessor; \
|
||||||
|
if ( ov_check(vi) ) \
|
||||||
|
{ \
|
||||||
|
std::string err = "overflow promoting from "; \
|
||||||
|
err += ov_err; \
|
||||||
|
err += " arithmetic value"; \
|
||||||
|
ZAM_run_time_error(z.loc, err.c_str()); \
|
||||||
|
res[i] = std::nullopt; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
res[i] = ZVal(cast(vi)); \
|
||||||
|
} \
|
||||||
else \
|
else \
|
||||||
res[i] = std::nullopt; \
|
res[i] = std::nullopt; \
|
||||||
return res_zv; \
|
return res_zv; \
|
||||||
}
|
}
|
||||||
|
|
||||||
VEC_COERCE(IU, TYPE_INT, bro_int_t, AsCount())
|
#define false_func(x) false
|
||||||
VEC_COERCE(ID, TYPE_INT, bro_int_t, AsDouble())
|
|
||||||
VEC_COERCE(UI, TYPE_COUNT, bro_int_t, AsInt())
|
VEC_COERCE(DI, TYPE_DOUBLE, double, AsInt(), false_func, "")
|
||||||
VEC_COERCE(UD, TYPE_COUNT, bro_uint_t, AsDouble())
|
VEC_COERCE(DU, TYPE_DOUBLE, double, AsCount(), false_func, "")
|
||||||
VEC_COERCE(DI, TYPE_DOUBLE, double, AsInt())
|
VEC_COERCE(ID, TYPE_INT, bro_int_t, AsDouble(), double_to_int_would_overflow, "double to signed")
|
||||||
VEC_COERCE(DU, TYPE_DOUBLE, double, AsCount())
|
VEC_COERCE(IU, TYPE_INT, bro_int_t, AsCount(), count_to_int_would_overflow, "unsigned to signed")
|
||||||
|
VEC_COERCE(UD, TYPE_COUNT, bro_uint_t, AsDouble(), double_to_count_would_overflow, "double to unsigned")
|
||||||
|
VEC_COERCE(UI, TYPE_COUNT, bro_int_t, AsInt(), int_to_count_would_overflow, "signed to unsigned")
|
||||||
|
|
||||||
double curr_CPU_time()
|
double curr_CPU_time()
|
||||||
{
|
{
|
||||||
|
@ -483,7 +495,8 @@ TraversalCode ZAMResumption::Traverse(TraversalCallback* cb) const
|
||||||
|
|
||||||
|
|
||||||
// Unary vector operation of v1 <vec-op> v2.
|
// Unary vector operation of v1 <vec-op> v2.
|
||||||
static void vec_exec(ZOp op, VectorVal*& v1, VectorVal* v2, const ZInst& z)
|
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||||
|
const ZInst& z)
|
||||||
{
|
{
|
||||||
// We could speed this up further still by gen'ing up an instance
|
// We could speed this up further still by gen'ing up an instance
|
||||||
// of the loop inside each switch case (in which case we might as
|
// of the loop inside each switch case (in which case we might as
|
||||||
|
@ -496,15 +509,20 @@ static void vec_exec(ZOp op, VectorVal*& v1, VectorVal* v2, const ZInst& z)
|
||||||
auto& vec1 = *vec1_ptr;
|
auto& vec1 = *vec1_ptr;
|
||||||
|
|
||||||
for ( auto i = 0U; i < n; ++i )
|
for ( auto i = 0U; i < n; ++i )
|
||||||
switch ( op ) {
|
{
|
||||||
|
if ( vec2[i] )
|
||||||
|
switch ( op ) {
|
||||||
|
|
||||||
#include "ZAM-Vec1EvalDefs.h"
|
#include "ZAM-Vec1EvalDefs.h"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
reporter->InternalError("bad invocation of VecExec");
|
reporter->InternalError("bad invocation of VecExec");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vec1[i] = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vt = cast_intrusive<VectorType>(v2->GetType());
|
auto vt = cast_intrusive<VectorType>(std::move(t));
|
||||||
auto old_v1 = v1;
|
auto old_v1 = v1;
|
||||||
v1 = new VectorVal(std::move(vt), vec1_ptr);
|
v1 = new VectorVal(std::move(vt), vec1_ptr);
|
||||||
Unref(old_v1);
|
Unref(old_v1);
|
||||||
|
@ -512,7 +530,7 @@ static void vec_exec(ZOp op, VectorVal*& v1, VectorVal* v2, const ZInst& z)
|
||||||
|
|
||||||
// Binary vector operation of v1 = v2 <vec-op> v3.
|
// Binary vector operation of v1 = v2 <vec-op> v3.
|
||||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
||||||
VectorVal* v2, const VectorVal* v3, const ZInst& z)
|
const VectorVal* v2, const VectorVal* v3, const ZInst& z)
|
||||||
{
|
{
|
||||||
// See comment above re further speed-up.
|
// See comment above re further speed-up.
|
||||||
|
|
||||||
|
@ -523,12 +541,17 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
||||||
auto& vec1 = *vec1_ptr;
|
auto& vec1 = *vec1_ptr;
|
||||||
|
|
||||||
for ( auto i = 0U; i < vec2.size(); ++i )
|
for ( auto i = 0U; i < vec2.size(); ++i )
|
||||||
switch ( op ) {
|
{
|
||||||
|
if ( vec2[i] && vec3[i] )
|
||||||
|
switch ( op ) {
|
||||||
|
|
||||||
#include "ZAM-Vec2EvalDefs.h"
|
#include "ZAM-Vec2EvalDefs.h"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
reporter->InternalError("bad invocation of VecExec");
|
reporter->InternalError("bad invocation of VecExec");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vec1[i] = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vt = cast_intrusive<VectorType>(std::move(t));
|
auto vt = cast_intrusive<VectorType>(std::move(t));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue