mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
introduce internal "mask" expression node to avoid mixed-type overloading of "/"
This commit is contained in:
parent
b53a025b1e
commit
434a7e059d
6 changed files with 55 additions and 13 deletions
22
src/Expr.cc
22
src/Expr.cc
|
@ -48,6 +48,7 @@ const char* expr_name(ExprTag t)
|
||||||
"-=",
|
"-=",
|
||||||
"*",
|
"*",
|
||||||
"/",
|
"/",
|
||||||
|
"/", // mask operator
|
||||||
"%",
|
"%",
|
||||||
"&",
|
"&",
|
||||||
"|",
|
"|",
|
||||||
|
@ -1918,14 +1919,27 @@ DivideExpr::DivideExpr(ExprPtr arg_op1, ExprPtr arg_op2)
|
||||||
else if ( BothArithmetic(bt1, bt2) )
|
else if ( BothArithmetic(bt1, bt2) )
|
||||||
PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
|
PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2));
|
||||||
|
|
||||||
else if ( bt1 == TYPE_ADDR && ! is_vector(op2) && (bt2 == TYPE_COUNT || bt2 == TYPE_INT) )
|
|
||||||
SetType(base_type(TYPE_SUBNET));
|
|
||||||
|
|
||||||
else
|
else
|
||||||
ExprError("requires arithmetic operands");
|
ExprError("requires arithmetic operands");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValPtr DivideExpr::AddrFold(Val* v1, Val* v2) const
|
MaskExpr::MaskExpr(ExprPtr arg_op1, ExprPtr arg_op2)
|
||||||
|
: BinaryExpr(EXPR_MASK, std::move(arg_op1), std::move(arg_op2))
|
||||||
|
{
|
||||||
|
if ( IsError() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
TypeTag bt1, bt2;
|
||||||
|
if ( ! get_types_from_scalars_or_vectors(this, bt1, bt2) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( bt1 == TYPE_ADDR && ! is_vector(op2) && (bt2 == TYPE_COUNT || bt2 == TYPE_INT) )
|
||||||
|
SetType(base_type(TYPE_SUBNET));
|
||||||
|
else
|
||||||
|
ExprError("requires address LHS and count/int RHS");
|
||||||
|
}
|
||||||
|
|
||||||
|
ValPtr MaskExpr::AddrFold(Val* v1, Val* v2) const
|
||||||
{
|
{
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
|
|
||||||
|
|
10
src/Expr.h
10
src/Expr.h
|
@ -52,6 +52,7 @@ enum ExprTag : int
|
||||||
EXPR_REMOVE_FROM,
|
EXPR_REMOVE_FROM,
|
||||||
EXPR_TIMES,
|
EXPR_TIMES,
|
||||||
EXPR_DIVIDE,
|
EXPR_DIVIDE,
|
||||||
|
EXPR_MASK,
|
||||||
EXPR_MOD,
|
EXPR_MOD,
|
||||||
EXPR_AND,
|
EXPR_AND,
|
||||||
EXPR_OR,
|
EXPR_OR,
|
||||||
|
@ -819,6 +820,15 @@ public:
|
||||||
ExprPtr Duplicate() override;
|
ExprPtr Duplicate() override;
|
||||||
bool WillTransform(Reducer* c) const override;
|
bool WillTransform(Reducer* c) const override;
|
||||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MaskExpr final : public BinaryExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaskExpr(ExprPtr op1, ExprPtr op2);
|
||||||
|
|
||||||
|
// Optimization-related:
|
||||||
|
ExprPtr Duplicate() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ValPtr AddrFold(Val* v1, Val* v2) const override;
|
ValPtr AddrFold(Val* v1, Val* v2) const override;
|
||||||
|
|
|
@ -633,7 +633,10 @@ expr:
|
||||||
| expr '/' expr
|
| expr '/' expr
|
||||||
{
|
{
|
||||||
set_location(@1, @3);
|
set_location(@1, @3);
|
||||||
$$ = new DivideExpr({AdoptRef{}, $1}, {AdoptRef{}, $3});
|
if ( $1->GetType()->Tag() == TYPE_ADDR )
|
||||||
|
$$ = new MaskExpr({AdoptRef{}, $1}, {AdoptRef{}, $3});
|
||||||
|
else
|
||||||
|
$$ = new DivideExpr({AdoptRef{}, $1}, {AdoptRef{}, $3});
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr '%' expr
|
| expr '%' expr
|
||||||
|
|
|
@ -80,6 +80,7 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level)
|
||||||
case EXPR_TIMES:
|
case EXPR_TIMES:
|
||||||
return GenBinary(e, gt, "*", "mul");
|
return GenBinary(e, gt, "*", "mul");
|
||||||
case EXPR_DIVIDE:
|
case EXPR_DIVIDE:
|
||||||
|
case EXPR_MASK: // later code will split into addr masking
|
||||||
return GenBinary(e, gt, "/", "div");
|
return GenBinary(e, gt, "/", "div");
|
||||||
case EXPR_MOD:
|
case EXPR_MOD:
|
||||||
return GenBinary(e, gt, "%", "mod");
|
return GenBinary(e, gt, "%", "mod");
|
||||||
|
@ -1060,7 +1061,7 @@ string CPPCompile::GenBinaryAddr(const Expr* e, GenType gt, const char* op)
|
||||||
{
|
{
|
||||||
auto v1 = GenExpr(e->GetOp1(), GEN_DONT_CARE) + "->AsAddr()";
|
auto v1 = GenExpr(e->GetOp1(), GEN_DONT_CARE) + "->AsAddr()";
|
||||||
|
|
||||||
if ( e->Tag() == EXPR_DIVIDE )
|
if ( e->Tag() == EXPR_MASK )
|
||||||
{
|
{
|
||||||
auto gen = string("addr_mask__CPP(") + v1 + ", " + GenExpr(e->GetOp2(), GEN_NATIVE) + ")";
|
auto gen = string("addr_mask__CPP(") + v1 + ", " + GenExpr(e->GetOp2(), GEN_NATIVE) + ")";
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,7 @@ bool Expr::IsFieldAssignable(const Expr* e) const
|
||||||
case EXPR_SUB:
|
case EXPR_SUB:
|
||||||
case EXPR_TIMES:
|
case EXPR_TIMES:
|
||||||
case EXPR_DIVIDE:
|
case EXPR_DIVIDE:
|
||||||
|
case EXPR_MASK:
|
||||||
case EXPR_MOD:
|
case EXPR_MOD:
|
||||||
case EXPR_AND:
|
case EXPR_AND:
|
||||||
case EXPR_OR:
|
case EXPR_OR:
|
||||||
|
@ -1091,20 +1092,24 @@ ExprPtr DivideExpr::Duplicate()
|
||||||
|
|
||||||
bool DivideExpr::WillTransform(Reducer* c) const
|
bool DivideExpr::WillTransform(Reducer* c) const
|
||||||
{
|
{
|
||||||
return GetType()->Tag() != TYPE_SUBNET && op2->IsOne();
|
return op2->IsOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprPtr DivideExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
ExprPtr DivideExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
||||||
{
|
{
|
||||||
if ( GetType()->Tag() != TYPE_SUBNET )
|
if ( op2->IsOne() )
|
||||||
{
|
return op1->ReduceToSingleton(c, red_stmt);
|
||||||
if ( op2->IsOne() )
|
|
||||||
return op1->ReduceToSingleton(c, red_stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return BinaryExpr::Reduce(c, red_stmt);
|
return BinaryExpr::Reduce(c, red_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprPtr MaskExpr::Duplicate()
|
||||||
|
{
|
||||||
|
auto op1_d = op1->Duplicate();
|
||||||
|
auto op2_d = op2->Duplicate();
|
||||||
|
return SetSucc(new MaskExpr(op1_d, op2_d));
|
||||||
|
}
|
||||||
|
|
||||||
ExprPtr ModExpr::Duplicate()
|
ExprPtr ModExpr::Duplicate()
|
||||||
{
|
{
|
||||||
auto op1_d = op1->Duplicate();
|
auto op1_d = op1->Duplicate();
|
||||||
|
|
|
@ -490,7 +490,16 @@ eval-pre if ( $2 == 0 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
eval $1 / $2
|
eval $1 / $2
|
||||||
#
|
|
||||||
|
binary-expr-op Mask
|
||||||
|
op-type I
|
||||||
|
vector
|
||||||
|
### Note that this first "eval" is a dummy - we'll never generate code
|
||||||
|
### that uses it because "Mask" expressions don't have LHS operands of
|
||||||
|
### type "int". We could omit this if we modified Gen-ZAM to understand
|
||||||
|
### that an op-type of 'X' for a binary-expr-op means "skip the usual case
|
||||||
|
### of two operands of the same type".
|
||||||
|
eval $1 / $2
|
||||||
eval-mixed A I auto mask = static_cast<uint32_t>($2);
|
eval-mixed A I auto mask = static_cast<uint32_t>($2);
|
||||||
auto a = $1->AsAddr();
|
auto a = $1->AsAddr();
|
||||||
if ( a.GetFamily() == IPv4 && mask > 32 )
|
if ( a.GetFamily() == IPv4 && mask > 32 )
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue