mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
factor script optimization Expr AST nodes out of main AST header
This commit is contained in:
parent
01fd30dda9
commit
7c8c83efc4
12 changed files with 276 additions and 270 deletions
|
@ -24,7 +24,7 @@
|
|||
#include "zeek/broker/Data.h"
|
||||
#include "zeek/digest.h"
|
||||
#include "zeek/module_util.h"
|
||||
#include "zeek/script_opt/ExprOptInfo.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
|
149
src/Expr.h
149
src/Expr.h
|
@ -1588,108 +1588,6 @@ private:
|
|||
TypePtr t;
|
||||
};
|
||||
|
||||
class InlineExpr : public Expr {
|
||||
public:
|
||||
InlineExpr(ScriptFuncPtr sf, ListExprPtr arg_args, std::vector<IDPtr> params, std::vector<bool> param_is_modified,
|
||||
StmtPtr body, int frame_offset, TypePtr ret_type);
|
||||
|
||||
bool IsPure() const override;
|
||||
|
||||
const ScriptFuncPtr& Func() const { return sf; }
|
||||
ListExprPtr Args() const { return args; }
|
||||
StmtPtr Body() const { return body; }
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override { return false; }
|
||||
bool WillTransform(Reducer* c) const override { return true; }
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
std::vector<IDPtr> params;
|
||||
std::vector<bool> param_is_modified;
|
||||
int frame_offset;
|
||||
ScriptFuncPtr sf;
|
||||
ListExprPtr args;
|
||||
StmtPtr body;
|
||||
};
|
||||
|
||||
// A companion to AddToExpr that's for vector-append, instantiated during
|
||||
// the reduction process.
|
||||
class AppendToExpr : public BinaryExpr {
|
||||
public:
|
||||
AppendToExpr(ExprPtr op1, ExprPtr op2);
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
};
|
||||
|
||||
// An internal class for reduced form.
|
||||
class IndexAssignExpr : public BinaryExpr {
|
||||
public:
|
||||
// "op1[op2] = op3", all reduced.
|
||||
IndexAssignExpr(ExprPtr op1, ExprPtr op2, ExprPtr op3);
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
ExprPtr GetOp3() const override final { return op3; }
|
||||
void SetOp3(ExprPtr _op) override final { op3 = std::move(_op); }
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
ExprPtr op3; // assignment RHS
|
||||
};
|
||||
|
||||
// An internal class for reduced form.
|
||||
class FieldLHSAssignExpr : public BinaryExpr {
|
||||
public:
|
||||
// "op1$field = RHS", where RHS is reduced with respect to
|
||||
// ReduceToFieldAssignment().
|
||||
FieldLHSAssignExpr(ExprPtr op1, ExprPtr op2, const char* field_name, int field);
|
||||
|
||||
const char* FieldName() const { return field_name; }
|
||||
int Field() const { return field; }
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
const char* field_name;
|
||||
int field;
|
||||
};
|
||||
|
||||
// Expression to explicitly capture conversion to an "any" type, rather
|
||||
// than it occurring implicitly during script interpretation.
|
||||
class CoerceToAnyExpr : public UnaryExpr {
|
||||
|
@ -1713,53 +1611,6 @@ protected:
|
|||
ExprPtr Duplicate() override;
|
||||
};
|
||||
|
||||
// ... and for conversion from a "vector of any" type.
|
||||
class CoerceFromAnyVecExpr : public UnaryExpr {
|
||||
public:
|
||||
// to_type is yield type, not VectorType.
|
||||
CoerceFromAnyVecExpr(ExprPtr op, TypePtr to_type);
|
||||
|
||||
// Can't use UnaryExpr's Eval() because it will do folding
|
||||
// over the individual vector elements.
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
protected:
|
||||
ExprPtr Duplicate() override;
|
||||
};
|
||||
|
||||
// Expression used to explicitly capture [a, b, c, ...] = x assignments.
|
||||
class AnyIndexExpr : public UnaryExpr {
|
||||
public:
|
||||
AnyIndexExpr(ExprPtr op, int index);
|
||||
|
||||
int Index() const { return index; }
|
||||
|
||||
protected:
|
||||
ValPtr Fold(Val* v) const override;
|
||||
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
int index;
|
||||
};
|
||||
|
||||
// Used internally for optimization, when a placeholder is needed.
|
||||
class NopExpr : public Expr {
|
||||
public:
|
||||
explicit NopExpr() : Expr(EXPR_NOP) {}
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
};
|
||||
|
||||
// Assigns v1[v2] = v3. Returns an error message, or nullptr on success.
|
||||
// Factored out so that compiled code can call it as well as the interpreter.
|
||||
extern const char* assign_to_index(ValPtr v1, ValPtr v2, ValPtr v3, bool& iterators_invalidated);
|
||||
|
|
|
@ -481,7 +481,8 @@ string CPPCompile::GenAddToExpr(const Expr* e, GenType gt, bool top_level) {
|
|||
if ( t->Tag() == TYPE_VECTOR ) {
|
||||
auto& rt = rhs->GetType();
|
||||
|
||||
if ( e->AsAddToExpr()->IsVectorElemAppend() )
|
||||
ASSERT(e->Tag() == EXPR_ADD_TO);
|
||||
if ( static_cast<const AddToExpr*>(e)->IsVectorElemAppend() )
|
||||
add_to_func = "vector_append__CPP";
|
||||
else
|
||||
add_to_func = "vector_vec_append__CPP";
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "zeek/script_opt/CSE.h"
|
||||
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
CSE_ValidityChecker::CSE_ValidityChecker(std::shared_ptr<ProfileFuncs> _pfs, const std::vector<const ID*>& _ids,
|
||||
|
@ -108,7 +110,7 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e) {
|
|||
case EXPR_FIELD_LHS_ASSIGN: {
|
||||
auto lhs = e->GetOp1();
|
||||
auto lhs_aggr_id = lhs->AsNameExpr()->Id();
|
||||
auto lhs_field = e->AsFieldLHSAssignExpr()->Field();
|
||||
auto lhs_field = static_cast<const FieldLHSAssignExpr*>(e)->Field();
|
||||
|
||||
if ( CheckID(lhs_aggr_id, true) )
|
||||
return TC_ABORTALL;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// Optimization-related methods for Expr classes.
|
||||
|
||||
#include "zeek/Expr.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Frame.h"
|
||||
|
@ -11,6 +11,7 @@
|
|||
#include "zeek/Scope.h"
|
||||
#include "zeek/Stmt.h"
|
||||
#include "zeek/Traverse.h"
|
||||
#include "zeek/script_opt/FuncInfo.h"
|
||||
#include "zeek/script_opt/Inline.h"
|
||||
#include "zeek/script_opt/Reduce.h"
|
||||
|
||||
|
@ -33,21 +34,16 @@ FieldExpr* Expr::AsFieldExpr() {
|
|||
return (FieldExpr*)this;
|
||||
}
|
||||
|
||||
FieldAssignExpr* Expr::AsFieldAssignExpr() {
|
||||
CHECK_TAG(tag, EXPR_FIELD_ASSIGN, "ExprVal::AsFieldAssignExpr", expr_name)
|
||||
return (FieldAssignExpr*)this;
|
||||
}
|
||||
|
||||
IntrusivePtr<FieldAssignExpr> Expr::AsFieldAssignExprPtr() {
|
||||
CHECK_TAG(tag, EXPR_FIELD_ASSIGN, "ExprVal::AsFieldAssignExpr", expr_name)
|
||||
return {NewRef{}, (FieldAssignExpr*)this};
|
||||
}
|
||||
|
||||
const IndexAssignExpr* Expr::AsIndexAssignExpr() const {
|
||||
CHECK_TAG(tag, EXPR_INDEX_ASSIGN, "ExprVal::AsIndexAssignExpr", expr_name)
|
||||
return (const IndexAssignExpr*)this;
|
||||
}
|
||||
|
||||
const FieldLHSAssignExpr* Expr::AsFieldLHSAssignExpr() const {
|
||||
CHECK_TAG(tag, EXPR_FIELD_LHS_ASSIGN, "ExprVal::AsFieldLHSAssignExpr", expr_name)
|
||||
return (const FieldLHSAssignExpr*)this;
|
||||
}
|
||||
|
||||
HasFieldExpr* Expr::AsHasFieldExpr() {
|
||||
CHECK_TAG(tag, EXPR_HAS_FIELD, "ExprVal::AsHasFieldExpr", expr_name)
|
||||
return (HasFieldExpr*)this;
|
||||
|
@ -58,11 +54,6 @@ const HasFieldExpr* Expr::AsHasFieldExpr() const {
|
|||
return (const HasFieldExpr*)this;
|
||||
}
|
||||
|
||||
const AddToExpr* Expr::AsAddToExpr() const {
|
||||
CHECK_TAG(tag, EXPR_ADD_TO, "ExprVal::AsAddToExpr", expr_name)
|
||||
return (const AddToExpr*)this;
|
||||
}
|
||||
|
||||
const IsExpr* Expr::AsIsExpr() const {
|
||||
CHECK_TAG(tag, EXPR_IS, "ExprVal::AsIsExpr", expr_name)
|
||||
return (const IsExpr*)this;
|
||||
|
@ -73,56 +64,11 @@ CallExpr* Expr::AsCallExpr() {
|
|||
return (CallExpr*)this;
|
||||
}
|
||||
|
||||
FieldAssignExpr* Expr::AsFieldAssignExpr() {
|
||||
CHECK_TAG(tag, EXPR_FIELD_ASSIGN, "ExprVal::AsFieldAssignExpr", expr_name)
|
||||
return (FieldAssignExpr*)this;
|
||||
}
|
||||
|
||||
const RecordCoerceExpr* Expr::AsRecordCoerceExpr() const {
|
||||
CHECK_TAG(tag, EXPR_RECORD_COERCE, "ExprVal::AsRecordCoerceExpr", expr_name)
|
||||
return (const RecordCoerceExpr*)this;
|
||||
}
|
||||
|
||||
RecordConstructorExpr* Expr::AsRecordConstructorExpr() {
|
||||
CHECK_TAG(tag, EXPR_RECORD_CONSTRUCTOR, "ExprVal::AsRecordConstructorExpr", expr_name)
|
||||
return (RecordConstructorExpr*)this;
|
||||
}
|
||||
|
||||
const RecordConstructorExpr* Expr::AsRecordConstructorExpr() const {
|
||||
CHECK_TAG(tag, EXPR_RECORD_CONSTRUCTOR, "ExprVal::AsRecordConstructorExpr", expr_name)
|
||||
return (const RecordConstructorExpr*)this;
|
||||
}
|
||||
|
||||
const TableConstructorExpr* Expr::AsTableConstructorExpr() const {
|
||||
CHECK_TAG(tag, EXPR_TABLE_CONSTRUCTOR, "ExprVal::AsTableConstructorExpr", expr_name)
|
||||
return (const TableConstructorExpr*)this;
|
||||
}
|
||||
|
||||
const SetConstructorExpr* Expr::AsSetConstructorExpr() const {
|
||||
CHECK_TAG(tag, EXPR_SET_CONSTRUCTOR, "ExprVal::AsSetConstructorExpr", expr_name)
|
||||
return (const SetConstructorExpr*)this;
|
||||
}
|
||||
|
||||
RefExpr* Expr::AsRefExpr() {
|
||||
CHECK_TAG(tag, EXPR_REF, "ExprVal::AsRefExpr", expr_name)
|
||||
return (RefExpr*)this;
|
||||
}
|
||||
|
||||
const InlineExpr* Expr::AsInlineExpr() const {
|
||||
CHECK_TAG(tag, EXPR_INLINE, "ExprVal::AsInlineExpr", expr_name)
|
||||
return (const InlineExpr*)this;
|
||||
}
|
||||
|
||||
AnyIndexExpr* Expr::AsAnyIndexExpr() {
|
||||
CHECK_TAG(tag, EXPR_ANY_INDEX, "ExprVal::AsAnyIndexExpr", expr_name)
|
||||
return (AnyIndexExpr*)this;
|
||||
}
|
||||
|
||||
const AnyIndexExpr* Expr::AsAnyIndexExpr() const {
|
||||
CHECK_TAG(tag, EXPR_ANY_INDEX, "ExprVal::AsAnyIndexExpr", expr_name)
|
||||
return (const AnyIndexExpr*)this;
|
||||
}
|
||||
|
||||
LambdaExpr* Expr::AsLambdaExpr() {
|
||||
CHECK_TAG(tag, EXPR_LAMBDA, "ExprVal::AsLambdaExpr", expr_name)
|
||||
return (LambdaExpr*)this;
|
||||
|
@ -994,7 +940,7 @@ ExprPtr ModExpr::Duplicate() {
|
|||
// nullptr, and the caller should have ensured that the starting point is
|
||||
// a disjunction (since a bare "/pat/ in var" by itself isn't a "cascade"
|
||||
// and doesn't present a potential optimization opportunity.
|
||||
static bool is_pattern_cascade(const ExprPtr& e, IDPtr& id, std::vector<ConstExprPtr>& patterns) {
|
||||
static bool is_pattern_cascade(const Expr* e, IDPtr& id, std::vector<ConstExprPtr>& patterns) {
|
||||
auto lhs = e->GetOp1();
|
||||
auto rhs = e->GetOp2();
|
||||
|
||||
|
@ -1016,7 +962,7 @@ static bool is_pattern_cascade(const ExprPtr& e, IDPtr& id, std::vector<ConstExp
|
|||
if ( e->Tag() != EXPR_OR_OR )
|
||||
return false;
|
||||
|
||||
return is_pattern_cascade(lhs, id, patterns) && is_pattern_cascade(rhs, id, patterns);
|
||||
return is_pattern_cascade(lhs.get(), id, patterns) && is_pattern_cascade(rhs.get(), id, patterns);
|
||||
}
|
||||
|
||||
// Given a set of pattern constants, returns a disjunction that
|
||||
|
@ -1043,10 +989,7 @@ bool BoolExpr::WillTransform(Reducer* c) const { return ! IsVector(op1->GetType(
|
|||
bool BoolExpr::WillTransformInConditional(Reducer* c) const {
|
||||
IDPtr common_id;
|
||||
std::vector<ConstExprPtr> patterns;
|
||||
|
||||
ExprPtr e_ptr = {NewRef{}, (Expr*)this};
|
||||
|
||||
return tag == EXPR_OR_OR && is_pattern_cascade(e_ptr, common_id, patterns);
|
||||
return tag == EXPR_OR_OR && is_pattern_cascade(this, common_id, patterns);
|
||||
}
|
||||
|
||||
ExprPtr BoolExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
|
||||
|
@ -1055,12 +998,8 @@ ExprPtr BoolExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
|
|||
// efficient to match.
|
||||
IDPtr common_id = nullptr;
|
||||
std::vector<ConstExprPtr> patterns;
|
||||
if ( tag == EXPR_OR_OR && is_pattern_cascade(ThisPtr(), common_id, patterns) ) {
|
||||
auto new_pat = build_disjunction(patterns, this);
|
||||
auto new_id = with_location_of(make_intrusive<NameExpr>(common_id), this);
|
||||
auto new_node = with_location_of(make_intrusive<InExpr>(new_pat, new_id), this);
|
||||
return new_node->Reduce(c, red_stmt);
|
||||
}
|
||||
if ( tag == EXPR_OR_OR && is_pattern_cascade(this, common_id, patterns) )
|
||||
return TransformToConditional(c, red_stmt);
|
||||
|
||||
// It's either an EXPR_AND_AND or an EXPR_OR_OR.
|
||||
bool is_and = (tag == EXPR_AND_AND);
|
||||
|
@ -1115,6 +1054,23 @@ ExprPtr BoolExpr::Reduce(Reducer* c, StmtPtr& red_stmt) {
|
|||
return TransformMe(cond_red, c, red_stmt);
|
||||
}
|
||||
|
||||
ExprPtr BoolExpr::TransformToConditional(Reducer* c, StmtPtr& red_stmt) {
|
||||
// This only happens for pattern cascades.
|
||||
|
||||
// Here in some contexts we're re-doing work that our caller did, but
|
||||
// these cascades are quite rare, and re-doing the work keeps the
|
||||
// coupling simpler.
|
||||
IDPtr common_id = nullptr;
|
||||
std::vector<ConstExprPtr> patterns;
|
||||
auto is_cascade = is_pattern_cascade(this, common_id, patterns);
|
||||
ASSERT(is_cascade);
|
||||
|
||||
auto new_pat = build_disjunction(patterns, this);
|
||||
auto new_id = with_location_of(make_intrusive<NameExpr>(common_id), this);
|
||||
auto new_node = with_location_of(make_intrusive<InExpr>(new_pat, new_id), this);
|
||||
return new_node->Reduce(c, red_stmt);
|
||||
}
|
||||
|
||||
bool BoolExpr::IsTrue(const ExprPtr& e) const {
|
||||
if ( ! e->IsConst() )
|
||||
return false;
|
||||
|
|
225
src/script_opt/Expr.h
Normal file
225
src/script_opt/Expr.h
Normal file
|
@ -0,0 +1,225 @@
|
|||
#include "zeek/Expr.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
class InlineExpr : public Expr {
|
||||
public:
|
||||
InlineExpr(ScriptFuncPtr sf, ListExprPtr arg_args, std::vector<IDPtr> params, std::vector<bool> param_is_modified,
|
||||
StmtPtr body, int frame_offset, TypePtr ret_type);
|
||||
|
||||
bool IsPure() const override;
|
||||
|
||||
const ScriptFuncPtr& Func() const { return sf; }
|
||||
ListExprPtr Args() const { return args; }
|
||||
StmtPtr Body() const { return body; }
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override { return false; }
|
||||
bool WillTransform(Reducer* c) const override { return true; }
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
std::vector<IDPtr> params;
|
||||
std::vector<bool> param_is_modified;
|
||||
int frame_offset;
|
||||
ScriptFuncPtr sf;
|
||||
ListExprPtr args;
|
||||
StmtPtr body;
|
||||
};
|
||||
|
||||
// A companion to AddToExpr that's for vector-append, instantiated during
|
||||
// the reduction process.
|
||||
class AppendToExpr : public BinaryExpr {
|
||||
public:
|
||||
AppendToExpr(ExprPtr op1, ExprPtr op2);
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
};
|
||||
|
||||
// An internal class for reduced form.
|
||||
class IndexAssignExpr : public BinaryExpr {
|
||||
public:
|
||||
// "op1[op2] = op3", all reduced.
|
||||
IndexAssignExpr(ExprPtr op1, ExprPtr op2, ExprPtr op3);
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
ExprPtr GetOp3() const override final { return op3; }
|
||||
void SetOp3(ExprPtr _op) override final { op3 = std::move(_op); }
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
ExprPtr op3; // assignment RHS
|
||||
};
|
||||
|
||||
// An internal class for reduced form.
|
||||
class FieldLHSAssignExpr : public BinaryExpr {
|
||||
public:
|
||||
// "op1$field = RHS", where RHS is reduced with respect to
|
||||
// ReduceToFieldAssignment().
|
||||
FieldLHSAssignExpr(ExprPtr op1, ExprPtr op2, const char* field_name, int field);
|
||||
|
||||
const char* FieldName() const { return field_name; }
|
||||
int Field() const { return field; }
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
bool IsPure() const override { return false; }
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
ExprPtr ReduceToSingleton(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
const char* field_name;
|
||||
int field;
|
||||
};
|
||||
|
||||
// ... and for conversion from a "vector of any" type.
|
||||
class CoerceFromAnyVecExpr : public UnaryExpr {
|
||||
public:
|
||||
// to_type is yield type, not VectorType.
|
||||
CoerceFromAnyVecExpr(ExprPtr op, TypePtr to_type);
|
||||
|
||||
// Can't use UnaryExpr's Eval() because it will do folding
|
||||
// over the individual vector elements.
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
protected:
|
||||
ExprPtr Duplicate() override;
|
||||
};
|
||||
|
||||
// Expression used to explicitly capture [a, b, c, ...] = x assignments.
|
||||
class AnyIndexExpr : public UnaryExpr {
|
||||
public:
|
||||
AnyIndexExpr(ExprPtr op, int index);
|
||||
|
||||
int Index() const { return index; }
|
||||
|
||||
protected:
|
||||
ValPtr Fold(Val* v) const override;
|
||||
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
int index;
|
||||
};
|
||||
|
||||
class ScriptOptBuiltinExpr : public Expr {
|
||||
public:
|
||||
enum SOBuiltInTag {
|
||||
MINIMUM,
|
||||
MAXIMUM,
|
||||
HAS_ELEMENTS,
|
||||
FUNC_ID_STRING,
|
||||
};
|
||||
|
||||
ScriptOptBuiltinExpr(SOBuiltInTag tag, ExprPtr arg1, ExprPtr arg2 = nullptr);
|
||||
ScriptOptBuiltinExpr(SOBuiltInTag tag, CallExprPtr call);
|
||||
|
||||
auto Tag() const { return tag; }
|
||||
|
||||
ExprPtr GetOp1() const override final { return arg1; }
|
||||
ExprPtr GetOp2() const override final { return arg2; }
|
||||
|
||||
void SetOp1(ExprPtr op) override final { arg1 = std::move(op); }
|
||||
void SetOp2(ExprPtr op) override final { arg2 = std::move(op); }
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
bool IsPure() const override;
|
||||
|
||||
// Optimization-related:
|
||||
ExprPtr Duplicate() override;
|
||||
bool IsReduced(Reducer* c) const override;
|
||||
bool HasReducedOps(Reducer* c) const override { return IsReduced(c); }
|
||||
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
|
||||
|
||||
void BuildEvalExpr();
|
||||
|
||||
SOBuiltInTag tag;
|
||||
ExprPtr arg1;
|
||||
ExprPtr arg2;
|
||||
ExprPtr eval_expr;
|
||||
CallExprPtr call;
|
||||
};
|
||||
|
||||
// Used internally for optimization, when a placeholder is needed.
|
||||
class NopExpr : public Expr {
|
||||
public:
|
||||
explicit NopExpr() : Expr(EXPR_NOP) {}
|
||||
|
||||
ValPtr Eval(Frame* f) const override;
|
||||
|
||||
ExprPtr Duplicate() override;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
||||
protected:
|
||||
void ExprDescribe(ODesc* d) const override;
|
||||
};
|
||||
|
||||
// Class for tracking whether a given expression has side effects. Currently,
|
||||
// we just need to know whether Yes-it-does or No-it-doesn't, so the structure
|
||||
// is very simple.
|
||||
|
||||
class ExprSideEffects {
|
||||
public:
|
||||
ExprSideEffects(bool _has_side_effects) : has_side_effects(_has_side_effects) {}
|
||||
|
||||
bool HasSideEffects() const { return has_side_effects; }
|
||||
|
||||
protected:
|
||||
bool has_side_effects;
|
||||
};
|
||||
|
||||
class ExprOptInfo {
|
||||
public:
|
||||
// The AST number of the statement in which this expression
|
||||
// appears.
|
||||
int stmt_num = -1; // -1 = not assigned yet
|
||||
|
||||
auto& SideEffects() { return side_effects; }
|
||||
|
||||
protected:
|
||||
// This optional value missing means "we haven't yet determined the
|
||||
// side effects".
|
||||
std::optional<ExprSideEffects> side_effects;
|
||||
};
|
||||
|
||||
}; // namespace zeek::detail
|
|
@ -1,38 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
// Auxiliary information associated with expressions to aid script
|
||||
// optimization.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
// Class for tracking whether a given expression has side effects. Currently,
|
||||
// we just need to know whether Yes-it-does or No-it-doesn't, so the structure
|
||||
// is very simple.
|
||||
|
||||
class ExprSideEffects {
|
||||
public:
|
||||
ExprSideEffects(bool _has_side_effects) : has_side_effects(_has_side_effects) {}
|
||||
|
||||
bool HasSideEffects() const { return has_side_effects; }
|
||||
|
||||
protected:
|
||||
bool has_side_effects;
|
||||
};
|
||||
|
||||
class ExprOptInfo {
|
||||
public:
|
||||
// The AST number of the statement in which this expression
|
||||
// appears.
|
||||
int stmt_num = -1; // -1 = not assigned yet
|
||||
|
||||
auto& SideEffects() { return side_effects; }
|
||||
|
||||
protected:
|
||||
// This optional value missing means "we haven't yet determined the
|
||||
// side effects".
|
||||
std::optional<ExprSideEffects> side_effects;
|
||||
};
|
||||
|
||||
} // namespace zeek::detail
|
|
@ -6,7 +6,7 @@
|
|||
#include "zeek/Expr.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Scope.h"
|
||||
#include "zeek/script_opt/ExprOptInfo.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/StmtOptInfo.h"
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "zeek/Desc.h"
|
||||
#include "zeek/EventRegistry.h"
|
||||
#include "zeek/module_util.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
#include "zeek/script_opt/FuncInfo.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "zeek/Frame.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Traverse.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
#include "zeek/script_opt/IDOptInfo.h"
|
||||
#include "zeek/script_opt/Reduce.h"
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "zeek/Event.h"
|
||||
#include "zeek/script_opt/Expr.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/UseDefs.h"
|
||||
#include "zeek/script_opt/ZAM/ZBody.h"
|
||||
|
|
|
@ -835,7 +835,8 @@ const ZAMStmt ZAMCompiler::BuildLambda(int n_slot, LambdaExpr* le) {
|
|||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::AssignVecElems(const Expr* e) {
|
||||
auto index_assign = e->AsIndexAssignExpr();
|
||||
ASSERT(e->Tag() == EXPR_INDEX_ASSIGN);
|
||||
auto index_assign = static_cast<const IndexAssignExpr*>(e);
|
||||
|
||||
auto op1 = index_assign->GetOp1();
|
||||
const auto& t1 = op1->GetType();
|
||||
|
@ -925,7 +926,8 @@ const ZAMStmt ZAMCompiler::AssignVecElems(const Expr* e) {
|
|||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::AssignTableElem(const Expr* e) {
|
||||
auto index_assign = e->AsIndexAssignExpr();
|
||||
ASSERT(e->Tag() == EXPR_INDEX_ASSIGN);
|
||||
auto index_assign = static_cast<const IndexAssignExpr*>(e);
|
||||
|
||||
auto op1 = index_assign->GetOp1()->AsNameExpr();
|
||||
auto op2 = index_assign->GetOp2()->AsListExpr();
|
||||
|
@ -1153,7 +1155,8 @@ const ZAMStmt ZAMCompiler::ConstructTable(const NameExpr* n, const Expr* e) {
|
|||
auto z = GenInst(OP_CONSTRUCT_TABLE_VV, n, width);
|
||||
z.aux = InternalBuildVals(con, width + 1);
|
||||
z.t = tt;
|
||||
z.aux->attrs = e->AsTableConstructorExpr()->GetAttrs();
|
||||
ASSERT(e->Tag() == EXPR_TABLE_CONSTRUCTOR);
|
||||
z.aux->attrs = static_cast<const TableConstructorExpr*>(e)->GetAttrs();
|
||||
|
||||
auto zstmt = AddInst(z);
|
||||
|
||||
|
@ -1191,13 +1194,15 @@ const ZAMStmt ZAMCompiler::ConstructSet(const NameExpr* n, const Expr* e) {
|
|||
auto z = GenInst(OP_CONSTRUCT_SET_VV, n, width);
|
||||
z.aux = InternalBuildVals(con, width);
|
||||
z.t = e->GetType();
|
||||
z.aux->attrs = e->AsSetConstructorExpr()->GetAttrs();
|
||||
ASSERT(e->Tag() == EXPR_SET_CONSTRUCTOR);
|
||||
z.aux->attrs = static_cast<const SetConstructorExpr*>(e)->GetAttrs();
|
||||
|
||||
return AddInst(z);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::ConstructRecord(const NameExpr* n, const Expr* e) {
|
||||
auto rc = e->AsRecordConstructorExpr();
|
||||
ASSERT(e->Tag() == EXPR_RECORD_CONSTRUCTOR);
|
||||
auto rc = static_cast<const RecordConstructorExpr*>(e);
|
||||
auto rt = e->GetType()->AsRecordType();
|
||||
|
||||
auto aux = InternalBuildVals(rc->Op().get());
|
||||
|
@ -1352,7 +1357,8 @@ const ZAMStmt ZAMCompiler::ArithCoerce(const NameExpr* n, const Expr* e) {
|
|||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::RecordCoerce(const NameExpr* n, const Expr* e) {
|
||||
auto r = e->AsRecordCoerceExpr();
|
||||
ASSERT(e->Tag() == EXPR_RECORD_COERCE);
|
||||
auto r = static_cast<const RecordCoerceExpr*>(e);
|
||||
auto op = r->GetOp1()->AsNameExpr();
|
||||
|
||||
int op_slot = FrameSlot(op);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue