Add bitshift operators

This commit is contained in:
AmazingPP 2022-07-21 10:59:19 +08:00
parent 1d2c12e980
commit f2bfa61fc6
10 changed files with 57 additions and 4 deletions

View file

@ -51,6 +51,8 @@ const char* expr_name(ExprTag t)
"&",
"|",
"^",
"<<",
">>",
"&&",
"||",
"<",
@ -957,6 +959,12 @@ ValPtr BinaryExpr::Fold(Val* v1, Val* v2) const
case EXPR_XOR:
DO_UINT_FOLD(^);
break;
case EXPR_LSHIFT:
DO_INT_FOLD(<<);
break;
case EXPR_RSHIFT:
DO_INT_FOLD(>>);
break;
case EXPR_AND_AND:
DO_INT_FOLD(&&);
@ -2156,7 +2164,22 @@ BitExpr::BitExpr(ExprTag arg_tag, ExprPtr arg_op1, ExprPtr arg_op2)
if ( IsVector(bt2) )
bt2 = t2->AsVectorType()->Yield()->Tag();
if ( (bt1 == TYPE_COUNT) && (bt2 == TYPE_COUNT) )
if ( tag == EXPR_LSHIFT || tag == EXPR_RSHIFT )
{
if ( IsIntegral(bt1) && bt2 == TYPE_COUNT )
{
if ( is_vector(op1) || is_vector(op2) )
SetType(make_intrusive<VectorType>(base_type(bt1)));
else
SetType(base_type(bt1));
}
else if ( IsIntegral(bt1) && bt2 == TYPE_INT )
ExprError("requires \"count\" right operand");
else
ExprError("requires integral operands");
}
else if ( (bt1 == TYPE_COUNT) && (bt2 == TYPE_COUNT) )
{
if ( is_vector(op1) || is_vector(op2) )
SetType(make_intrusive<VectorType>(base_type(TYPE_COUNT)));

View file

@ -53,6 +53,8 @@ enum ExprTag : int
EXPR_AND,
EXPR_OR,
EXPR_XOR,
EXPR_LSHIFT,
EXPR_RSHIFT,
EXPR_AND_AND,
EXPR_OR_OR,
EXPR_LT,

View file

@ -5,7 +5,7 @@
// Switching parser table type fixes ambiguity problems.
%define lr.type ielr
%expect 195
%expect 199
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@ -46,6 +46,7 @@
%left '|'
%left '^'
%left '&'
%left TOK_LSHIFT TOK_RSHIFT
%left '+' '-'
%left '*' '/' '%'
%left TOK_INCR TOK_DECR
@ -554,6 +555,18 @@ expr:
$$ = new BitExpr(EXPR_XOR, {AdoptRef{}, $1}, {AdoptRef{}, $3});
}
| expr TOK_LSHIFT expr
{
set_location(@1, @3);
$$ = new BitExpr(EXPR_LSHIFT, {AdoptRef{}, $1}, {AdoptRef{}, $3});
}
| expr TOK_RSHIFT expr
{
set_location(@1, @3);
$$ = new BitExpr(EXPR_RSHIFT, {AdoptRef{}, $1}, {AdoptRef{}, $3});
}
| expr TOK_AND_AND expr
{
set_location(@1, @3);

View file

@ -248,6 +248,9 @@ ESCSEQ (\\([^\r\n]|[0-7]+|x[[:xdigit:]]+))
"&&" return TOK_AND_AND;
"||" return TOK_OR_OR;
"<<" return TOK_LSHIFT;
">>" return TOK_RSHIFT;
add return TOK_ADD;
addr return TOK_ADDR;
any return TOK_ANY;

View file

@ -89,6 +89,10 @@ string CPPCompile::GenExpr(const Expr* e, GenType gt, bool top_level)
return GenBinary(e, gt, "|", "or");
case EXPR_XOR:
return GenBinary(e, gt, "^", "xor");
case EXPR_LSHIFT:
return GenBinary(e, gt, "<<", "lshift");
case EXPR_RSHIFT:
return GenBinary(e, gt, ">>", "rshift");
case EXPR_AND_AND:
return GenBinary(e, gt, "&&", "andand");
case EXPR_OR_OR:

View file

@ -257,6 +257,8 @@ bool Expr::IsFieldAssignable(const Expr* e) const
case EXPR_AND:
case EXPR_OR:
case EXPR_XOR:
case EXPR_LSHIFT:
case EXPR_RSHIFT:
case EXPR_FIELD:
case EXPR_HAS_FIELD:
case EXPR_IN:
@ -1293,7 +1295,7 @@ bool BitExpr::WillTransform(Reducer* c) const
ExprPtr BitExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
{
if ( GetType()->Tag() != TYPE_COUNT )
if ( ! IsIntegral(GetType()->Tag()) )
return BinaryExpr::Reduce(c, red_stmt);
auto zero1 = op1->IsZero();
@ -1311,7 +1313,7 @@ ExprPtr BitExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
if ( Tag() == EXPR_AND )
return zero_op->ReduceToSingleton(c, red_stmt);
else
// OR or XOR
// OR or XOR or LSHIFT or RSHIFT
return non_zero_op->ReduceToSingleton(c, red_stmt);
}

View file

@ -20,6 +20,8 @@ bitwise and (PASS)
bitwise or (PASS)
bitwise or (PASS)
bitwise xor (PASS)
bitwise lshift (PASS)
bitwise rshift (PASS)
bitwise complement (PASS)
bitwise complement (PASS)
max count value = 18446744073709551615 (PASS)

View file

@ -18,6 +18,7 @@ modulus operator (PASS)
division operator (PASS)
assignment operator (PASS)
assignment operator (PASS)
bitwise rshift (PASS)
max int value = 9223372036854775807 (PASS)
min int value = -9223372036854775808 (PASS)
max int value = 9223372036854775807 (PASS)

View file

@ -49,6 +49,8 @@ event zeek_init()
test_case( "bitwise or", c2 | 0x4 == c2 );
test_case( "bitwise or", c4 | 0x4 == c4 );
test_case( "bitwise xor", c4 ^ 0x4 == 251 );
test_case( "bitwise lshift", c4 << 0x4 == 4080 );
test_case( "bitwise rshift", c4 >> 0x4 == 15 );
test_case( "bitwise complement", ~c6 == 0 );
test_case( "bitwise complement", ~~c4 == c4 );

View file

@ -54,6 +54,7 @@ event zeek_init()
test_case( "assignment operator", i2 == 7 );
i2 -= 2;
test_case( "assignment operator", i2 == 5 );
test_case( "bitwise rshift", i10 >> 1 == -6 );
# Max/min value tests