bitwise operations for "count" types implemented

This commit is contained in:
Vern Paxson 2018-04-26 12:38:24 -07:00
parent d9dc8d69d7
commit 1658931af1
5 changed files with 144 additions and 6 deletions

View file

@ -23,7 +23,7 @@ const char* expr_name(BroExprTag t)
static const char* expr_names[int(NUM_EXPRS)] = {
"name", "const",
"(*)",
"++", "--", "!", "+", "-",
"++", "--", "!", "~", "+", "-",
"+", "-", "+=", "-=", "*", "/", "%",
"&", "|", "^",
"&&", "||",
@ -706,6 +706,12 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const
else \
Internal("bad type in BinaryExpr::Fold");
#define DO_UINT_FOLD(op) \
if ( is_unsigned ) \
u3 = u1 op u2; \
else \
Internal("bad type in BinaryExpr::Fold");
#define DO_FOLD(op) \
if ( is_integral ) \
i3 = i1 op i2; \
@ -779,6 +785,10 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const
break;
case EXPR_AND: DO_UINT_FOLD(&); break;
case EXPR_OR: DO_UINT_FOLD(|); break;
case EXPR_XOR: DO_UINT_FOLD(^); break;
case EXPR_AND_AND: DO_INT_FOLD(&&); break;
case EXPR_OR_OR: DO_INT_FOLD(||); break;
@ -1081,6 +1091,39 @@ bool IncrExpr::DoUnserialize(UnserialInfo* info)
return true;
}
ComplementExpr::ComplementExpr(Expr* arg_op) : UnaryExpr(EXPR_COMPLEMENT, arg_op)
{
if ( IsError() )
return;
BroType* t = op->Type();
TypeTag bt = t->Tag();
if ( bt != TYPE_COUNT )
ExprError("requires \"count\" operand");
else
SetType(base_type(TYPE_COUNT));
}
Val* ComplementExpr::Fold(Val* v) const
{
return new Val(~ v->InternalUnsigned(), type->Tag());
}
IMPLEMENT_SERIAL(ComplementExpr, SER_COMPLEMENT_EXPR);
bool ComplementExpr::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_COMPLEMENT_EXPR, UnaryExpr);
return true;
}
bool ComplementExpr::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(UnaryExpr);
return true;
}
NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op)
{
if ( IsError() )
@ -1817,6 +1860,46 @@ bool BoolExpr::DoUnserialize(UnserialInfo* info)
return true;
}
BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
: BinaryExpr(arg_tag, arg_op1, arg_op2)
{
if ( IsError() )
return;
TypeTag bt1 = op1->Type()->Tag();
if ( IsVector(bt1) )
bt1 = op1->Type()->AsVectorType()->YieldType()->Tag();
TypeTag bt2 = op2->Type()->Tag();
if ( IsVector(bt2) )
bt2 = op2->Type()->AsVectorType()->YieldType()->Tag();
if ( bt1 == TYPE_COUNT && bt2 == bt1 )
{
if ( is_vector(op1) || is_vector(op2) )
SetType(new VectorType(base_type(bt1)));
else
SetType(base_type(bt1));
}
else
ExprError("requires \"count\" operands");
}
IMPLEMENT_SERIAL(BitExpr, SER_BIT_EXPR);
bool BitExpr::DoSerialize(SerialInfo* info) const
{
DO_SERIALIZE(SER_BIT_EXPR, BinaryExpr);
return true;
}
bool BitExpr::DoUnserialize(UnserialInfo* info)
{
DO_UNSERIALIZE(BinaryExpr);
return true;
}
EqExpr::EqExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
: BinaryExpr(arg_tag, arg_op1, arg_op2)
{

View file

@ -17,7 +17,9 @@ typedef enum {
EXPR_ANY = -1,
EXPR_NAME, EXPR_CONST,
EXPR_CLONE,
EXPR_INCR, EXPR_DECR, EXPR_NOT, EXPR_POSITIVE, EXPR_NEGATE,
EXPR_INCR, EXPR_DECR,
EXPR_NOT, EXPR_COMPLEMENT,
EXPR_POSITIVE, EXPR_NEGATE,
EXPR_ADD, EXPR_SUB, EXPR_ADD_TO, EXPR_REMOVE_FROM,
EXPR_TIMES, EXPR_DIVIDE, EXPR_MOD,
EXPR_AND, EXPR_OR, EXPR_XOR,
@ -378,6 +380,19 @@ protected:
DECLARE_SERIAL(IncrExpr);
};
class ComplementExpr : public UnaryExpr {
public:
explicit ComplementExpr(Expr* op);
protected:
friend class Expr;
ComplementExpr() { }
Val* Fold(Val* v) const override;
DECLARE_SERIAL(ComplementExpr);
};
class NotExpr : public UnaryExpr {
public:
explicit NotExpr(Expr* op);
@ -531,6 +546,17 @@ protected:
DECLARE_SERIAL(BoolExpr);
};
class BitExpr : public BinaryExpr {
public:
BitExpr(BroExprTag tag, Expr* op1, Expr* op2);
protected:
friend class Expr;
BitExpr() { }
DECLARE_SERIAL(BitExpr);
};
class EqExpr : public BinaryExpr {
public:
EqExpr(BroExprTag tag, Expr* op1, Expr* op2);

View file

@ -3,7 +3,7 @@
// How to make objects of class Foo serializable:
//
// 1. Derive Foo (directly or indirectly) from SerialObj.
// 2. Add a SER_FOO constant to SerialTypes below.
// 2. Add a SER_FOO constant to SerialTypes in SerialTypes.h.
// 3. Add DECLARE_SERIAL(Foo) into class definition.
// 4. Add a (preferably protected) default ctor if it doesn't already exist.
// 5. For non-abstract classes, add IMPLEMENT_SERIAL(Foo, SER_FOO) to *.cc

View file

@ -162,6 +162,8 @@ SERIAL_EXPR(SET_CONSTRUCTOR_EXPR, 41)
SERIAL_EXPR(VECTOR_CONSTRUCTOR_EXPR, 42)
SERIAL_EXPR(TABLE_COERCE_EXPR, 43)
SERIAL_EXPR(VECTOR_COERCE_EXPR, 44)
SERIAL_EXPR(BIT_EXPR, 45)
SERIAL_EXPR(COMPLEMENT_EXPR, 46)
#define SERIAL_STMT(name, val) SERIAL_CONST(name, val, STMT)
SERIAL_STMT(STMT, 1)

View file

@ -31,7 +31,7 @@
%token TOK_NO_TEST
%left ',' '|'
%left ','
%right '=' TOK_ADD_TO TOK_REMOVE_FROM
%right '?' ':'
%left TOK_OR_OR
@ -39,10 +39,13 @@
%nonassoc TOK_HOOK
%nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE
%left TOK_IN TOK_NOT_IN
%left '|'
%left '^'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left TOK_INCR TOK_DECR
%right '!'
%right '!' '~'
%left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR
%type <b> opt_no_test opt_no_test_block opt_deprecated
@ -334,6 +337,12 @@ expr:
$$ = new NotExpr($2);
}
| '~' expr
{
set_location(@1, @2);
$$ = new ComplementExpr($2);
}
| '-' expr %prec '!'
{
set_location(@1, @2);
@ -388,6 +397,24 @@ expr:
$$ = new ModExpr($1, $3);
}
| expr '&' expr
{
set_location(@1, @3);
$$ = new BitExpr(EXPR_AND, $1, $3);
}
| expr '|' expr
{
set_location(@1, @3);
$$ = new BitExpr(EXPR_OR, $1, $3);
}
| expr '^' expr
{
set_location(@1, @3);
$$ = new BitExpr(EXPR_XOR, $1, $3);
}
| expr TOK_AND_AND expr
{
set_location(@1, @3);
@ -700,7 +727,7 @@ expr:
$$ = new ConstExpr(new PatternVal($1));
}
| '|' expr '|'
| '|' expr '|' %prec '('
{
set_location(@1, @3);
$$ = new SizeExpr($2);