mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 16:48:19 +00:00
implementation for Reduce class - code now links
This commit is contained in:
parent
7a9694a2a4
commit
607e9950bf
2 changed files with 283 additions and 0 deletions
|
@ -325,6 +325,7 @@ set(MAIN_SRCS
|
||||||
script_opt/Expr.cc
|
script_opt/Expr.cc
|
||||||
script_opt/Inline.cc
|
script_opt/Inline.cc
|
||||||
script_opt/ProfileFunc.cc
|
script_opt/ProfileFunc.cc
|
||||||
|
script_opt/Reduce.cc
|
||||||
script_opt/ScriptOpt.cc
|
script_opt/ScriptOpt.cc
|
||||||
script_opt/Stmt.cc
|
script_opt/Stmt.cc
|
||||||
script_opt/TempVar.cc
|
script_opt/TempVar.cc
|
||||||
|
|
282
src/script_opt/Reduce.cc
Normal file
282
src/script_opt/Reduce.cc
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#include "ID.h"
|
||||||
|
#include "Var.h"
|
||||||
|
#include "Scope.h"
|
||||||
|
#include "Expr.h"
|
||||||
|
#include "Stmt.h"
|
||||||
|
#include "Desc.h"
|
||||||
|
#include "ProfileFunc.h"
|
||||||
|
#include "Reporter.h"
|
||||||
|
#include "zeek/script_opt/Reduce.h"
|
||||||
|
#include "zeek/script_opt/TempVar.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace zeek::detail {
|
||||||
|
|
||||||
|
|
||||||
|
Reducer::Reducer(Scope* s)
|
||||||
|
{
|
||||||
|
scope = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reducer::~Reducer()
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < temps.length(); ++i )
|
||||||
|
delete temps[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprPtr Reducer::GenTemporaryExpr(const TypePtr& t, ExprPtr rhs)
|
||||||
|
{
|
||||||
|
auto e = make_intrusive<NameExpr>(GenTemporary(t, rhs));
|
||||||
|
e->SetLocationInfo(rhs->GetLocationInfo());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
NameExpr* Reducer::UpdateName(NameExpr* n)
|
||||||
|
{
|
||||||
|
if ( NameIsReduced(n) )
|
||||||
|
{
|
||||||
|
Ref(n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NameExpr(FindNewLocal(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::NameIsReduced(const NameExpr* n) const
|
||||||
|
{
|
||||||
|
auto id = n->Id();
|
||||||
|
return inline_block_level == 0 || id->IsGlobal() || IsTemporary(id) ||
|
||||||
|
IsNewLocal(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reducer::UpdateIDs(IDPList* ids)
|
||||||
|
{
|
||||||
|
loop_over_list(*ids, i)
|
||||||
|
{
|
||||||
|
IDPtr id = {NewRef{}, (*ids)[i]};
|
||||||
|
|
||||||
|
if ( ! ID_IsReduced(id) )
|
||||||
|
(*ids)[i] = UpdateID(id).release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reducer::UpdateIDs(std::vector<IDPtr>& ids)
|
||||||
|
{
|
||||||
|
for ( auto& id : ids )
|
||||||
|
if ( ! ID_IsReduced(id) )
|
||||||
|
id = UpdateID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::IDsAreReduced(const IDPList* ids) const
|
||||||
|
{
|
||||||
|
for ( auto& id : *ids )
|
||||||
|
if ( ! ID_IsReduced(id) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::IDsAreReduced(const std::vector<IDPtr>& ids) const
|
||||||
|
{
|
||||||
|
for ( auto& id : ids )
|
||||||
|
if ( ! ID_IsReduced(id) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDPtr Reducer::UpdateID(IDPtr id)
|
||||||
|
{
|
||||||
|
if ( ID_IsReduced(id) )
|
||||||
|
return id;
|
||||||
|
|
||||||
|
return FindNewLocal(id.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::ID_IsReduced(const ID* id) const
|
||||||
|
{
|
||||||
|
return inline_block_level == 0 || id->IsGlobal() || IsTemporary(id) ||
|
||||||
|
IsNewLocal(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
NameExprPtr Reducer::GenInlineBlockName(IDPtr id)
|
||||||
|
{
|
||||||
|
return make_intrusive<NameExpr>(GenLocal(id.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
NameExprPtr Reducer::PushInlineBlock(TypePtr type)
|
||||||
|
{
|
||||||
|
++inline_block_level;
|
||||||
|
|
||||||
|
if ( ! type || type->Tag() == TYPE_VOID )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
char buf[8192];
|
||||||
|
int n = new_locals.size();
|
||||||
|
snprintf(buf, sizeof buf, "@retvar");
|
||||||
|
|
||||||
|
IDPtr ret_id = install_ID(buf, "<internal>", false, false);
|
||||||
|
ret_id->SetType(type);
|
||||||
|
|
||||||
|
// Track this as a new local *if* we're in the outermost inlining
|
||||||
|
// block. If we're recursively deeper into inlining, then this
|
||||||
|
// variable will get mapped to a local anyway, so no need.
|
||||||
|
if ( inline_block_level == 1 )
|
||||||
|
new_locals.insert(ret_id.get());
|
||||||
|
|
||||||
|
return GenInlineBlockName(ret_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reducer::PopInlineBlock()
|
||||||
|
{
|
||||||
|
--inline_block_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::SameVal(const Val* v1, const Val* v2) const
|
||||||
|
{
|
||||||
|
if ( is_atomic_val(v1) )
|
||||||
|
return same_atomic_val(v1, v2);
|
||||||
|
else
|
||||||
|
return v1 == v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDPtr Reducer::GenTemporary(const TypePtr& t, ExprPtr rhs)
|
||||||
|
{
|
||||||
|
if ( Optimizing() )
|
||||||
|
reporter->InternalError("Generating a new temporary while optimizing");
|
||||||
|
|
||||||
|
auto temp = new TempVar(temps.length(), t, rhs);
|
||||||
|
IDPtr temp_id = install_ID(temp->Name(), "<internal>", false, false);
|
||||||
|
|
||||||
|
temp->SetID(temp_id);
|
||||||
|
temp_id->SetType(t);
|
||||||
|
|
||||||
|
temps.append(temp);
|
||||||
|
ids_to_temps[temp_id.get()] = temp;
|
||||||
|
|
||||||
|
return temp_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDPtr Reducer::FindNewLocal(ID* id)
|
||||||
|
{
|
||||||
|
auto mapping = orig_to_new_locals.find(id);
|
||||||
|
|
||||||
|
if ( mapping != orig_to_new_locals.end() )
|
||||||
|
return mapping->second;
|
||||||
|
|
||||||
|
return GenLocal(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDPtr Reducer::GenLocal(ID* orig)
|
||||||
|
{
|
||||||
|
if ( Optimizing() )
|
||||||
|
reporter->InternalError("Generating a new local while optimizing");
|
||||||
|
|
||||||
|
char buf[8192];
|
||||||
|
int n = new_locals.size();
|
||||||
|
snprintf(buf, sizeof buf, "%s.%d", orig->Name(), n);
|
||||||
|
|
||||||
|
IDPtr local_id = install_ID(buf, "<internal>", false, false);
|
||||||
|
local_id->SetType(orig->GetType());
|
||||||
|
|
||||||
|
new_locals.insert(local_id.get());
|
||||||
|
orig_to_new_locals[orig] = local_id;
|
||||||
|
|
||||||
|
return local_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reducer::IsNewLocal(const ID* id) const
|
||||||
|
{
|
||||||
|
ID* non_const_ID = (ID*) id; // I don't get why C++ requires this
|
||||||
|
return new_locals.count(non_const_ID) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempVar* Reducer::FindTemporary(const ID* id) const
|
||||||
|
{
|
||||||
|
auto tmp = ids_to_temps.find(id);
|
||||||
|
if ( tmp == ids_to_temps.end() )
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return tmp->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stmt* Reducer::MergeStmts(const NameExpr* lhs, ExprPtr rhs, Stmt* succ_stmt)
|
||||||
|
{
|
||||||
|
// First check for tmp=rhs.
|
||||||
|
auto lhs_id = lhs->Id();
|
||||||
|
auto lhs_tmp = FindTemporary(lhs_id);
|
||||||
|
|
||||||
|
if ( ! lhs_tmp )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// We have tmp=rhs. Now look for var=tmp.
|
||||||
|
if ( succ_stmt->Tag() != STMT_EXPR )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto s_e = succ_stmt->AsExprStmt()->StmtExpr();
|
||||||
|
if ( s_e->Tag() != EXPR_ASSIGN )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto a = s_e->AsAssignExpr();
|
||||||
|
auto a_lhs = a->GetOp1();
|
||||||
|
auto a_rhs = a->GetOp2();
|
||||||
|
|
||||||
|
if ( a_lhs->Tag() != EXPR_REF || a_rhs->Tag() != EXPR_NAME )
|
||||||
|
// Complex 2nd-statement assignment, or RHS not a candidate.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto a_lhs_deref = a_lhs->AsRefExprPtr()->GetOp1();
|
||||||
|
if ( a_lhs_deref->Tag() != EXPR_NAME )
|
||||||
|
// Complex 2nd-statement assignment.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto a_lhs_var = a_lhs_deref->AsNameExpr()->Id();
|
||||||
|
auto a_rhs_var = a_rhs->AsNameExpr()->Id();
|
||||||
|
|
||||||
|
if ( a_rhs_var != lhs_id )
|
||||||
|
// 2nd statement is var=something else.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( a_lhs_var->GetType()->Tag() != a_rhs_var->GetType()->Tag() )
|
||||||
|
// This can happen when we generate an assignment
|
||||||
|
// specifically to convert to/from an "any" type.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if ( FindTemporary(a_lhs_var) )
|
||||||
|
{
|
||||||
|
// "var" is itself a temporary. Don't complain, as
|
||||||
|
// complex reductions can generate these. We'll wind
|
||||||
|
// up folding the chain once it hits a regular variable.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Got it. Mark the original temporary as no longer relevant.
|
||||||
|
lhs_tmp->Deactivate();
|
||||||
|
auto merge_e = make_intrusive<AssignExpr>(a_lhs_deref, rhs, false,
|
||||||
|
nullptr, nullptr, false);
|
||||||
|
TrackExprReplacement(rhs.get(), merge_e.get());
|
||||||
|
|
||||||
|
return new ExprStmt(merge_e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reducer::TrackExprReplacement(const Expr* orig, const Expr* e)
|
||||||
|
{
|
||||||
|
new_expr_to_orig[e] = orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Expr* non_reduced_perp;
|
||||||
|
bool checking_reduction;
|
||||||
|
|
||||||
|
bool NonReduced(const Expr* perp)
|
||||||
|
{
|
||||||
|
if ( checking_reduction )
|
||||||
|
non_reduced_perp = perp;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // zeek::detail
|
Loading…
Add table
Add a link
Reference in a new issue