mirror of
https://github.com/zeek/zeek.git
synced 2025-10-17 05:58:20 +00:00
Reformat the world
This commit is contained in:
parent
194cb24547
commit
b2f171ec69
714 changed files with 35149 additions and 35203 deletions
|
@ -4,14 +4,15 @@
|
|||
// i.e., code improvement that's done after the compiler has generated
|
||||
// an initial, complete intermediary function body.
|
||||
|
||||
#include "zeek/input.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/input.h"
|
||||
#include "zeek/script_opt/Reduce.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
// Tracks per function its maximum remapped interpreter frame size. We
|
||||
// can't do this when compiling individual functions since for event handlers
|
||||
|
@ -42,8 +43,7 @@ void finalize_functions(const std::vector<FuncInfo>& funcs)
|
|||
// preserve the size they need.
|
||||
int size = func->FrameSize();
|
||||
|
||||
if ( f.Body()->Tag() != STMT_ZAM &&
|
||||
remapped_intrp_frame_sizes.count(func) > 0 &&
|
||||
if ( f.Body()->Tag() != STMT_ZAM && remapped_intrp_frame_sizes.count(func) > 0 &&
|
||||
size > remapped_intrp_frame_sizes[func] )
|
||||
remapped_intrp_frame_sizes[func] = size;
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ void finalize_functions(const std::vector<FuncInfo>& funcs)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// The following is for activating detailed dumping for debugging
|
||||
// optimizer problems.
|
||||
static bool dump_intermediaries = false;
|
||||
|
@ -133,15 +132,13 @@ void ZAMCompiler::OptimizeInsts()
|
|||
DumpInsts1(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( something_changed );
|
||||
} while ( something_changed );
|
||||
|
||||
ReMapFrame();
|
||||
ReMapInterpreterFrame();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ZAMCompiler::TallySwitchTargets(const CaseMapsI<T>& switches)
|
||||
template <typename T> void ZAMCompiler::TallySwitchTargets(const CaseMapsI<T>& switches)
|
||||
{
|
||||
for ( auto& targs : switches )
|
||||
for ( auto& targ : targs )
|
||||
|
@ -177,8 +174,7 @@ bool ZAMCompiler::RemoveDeadCode()
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( t && t->inst_num > i0->inst_num &&
|
||||
(! i1 || t->inst_num <= i1->inst_num) )
|
||||
if ( t && t->inst_num > i0->inst_num && (! i1 || t->inst_num <= i1->inst_num) )
|
||||
{
|
||||
// This is effectively a branch to the next
|
||||
// instruction. Even if i0 is conditional, there's
|
||||
|
@ -362,106 +358,105 @@ void ZAMCompiler::ComputeFrameLifetimes()
|
|||
CheckSlotAssignment(inst->v1, inst);
|
||||
|
||||
// Some special-casing.
|
||||
switch ( inst->op ) {
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
switch ( inst->op )
|
||||
{
|
||||
// These assign to an arbitrary long list of variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
auto depth = inst->loop_depth;
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
{
|
||||
// These assign to an arbitrary long list of variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
auto depth = inst->loop_depth;
|
||||
|
||||
for ( auto v : iter_vars )
|
||||
{
|
||||
CheckSlotAssignment(v, inst);
|
||||
for ( auto v : iter_vars )
|
||||
{
|
||||
CheckSlotAssignment(v, inst);
|
||||
|
||||
// Also mark it as usage throughout the
|
||||
// loop. Otherwise, we risk pruning the
|
||||
// variable if it happens to not be used
|
||||
// (which will mess up the iteration logic)
|
||||
// or doubling it up with some other value
|
||||
// inside the loop (which will fail when
|
||||
// the loop var has memory management
|
||||
// associated with it).
|
||||
ExtendLifetime(v, EndOfLoop(inst, depth));
|
||||
}
|
||||
// Also mark it as usage throughout the
|
||||
// loop. Otherwise, we risk pruning the
|
||||
// variable if it happens to not be used
|
||||
// (which will mess up the iteration logic)
|
||||
// or doubling it up with some other value
|
||||
// inside the loop (which will fail when
|
||||
// the loop var has memory management
|
||||
// associated with it).
|
||||
ExtendLifetime(v, EndOfLoop(inst, depth));
|
||||
}
|
||||
|
||||
// No need to check the additional "var" associated
|
||||
// with OP_NEXT_TABLE_ITER_VAL_VAR_VVV as that's
|
||||
// a slot-1 assignment. However, similar to other
|
||||
// loop variables, mark this as a usage.
|
||||
if ( inst->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV )
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEXT_TABLE_ITER_NO_VARS_VV:
|
||||
break;
|
||||
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV:
|
||||
{
|
||||
auto depth = inst->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEXT_VECTOR_ITER_VVV:
|
||||
case OP_NEXT_STRING_ITER_VVV:
|
||||
// Sometimes loops are written that don't actually
|
||||
// use the iteration variable. However, we still
|
||||
// need to mark the variable as having usage
|
||||
// throughout the loop, lest we elide the iteration
|
||||
// instruction. An alternative would be to transform
|
||||
// such iterators into variable-less versions. That
|
||||
// optimization hardly seems worth the trouble, though,
|
||||
// given the presumed rarity of such loops.
|
||||
ExtendLifetime(inst->v1,
|
||||
EndOfLoop(inst, inst->loop_depth));
|
||||
break;
|
||||
|
||||
case OP_INIT_TABLE_LOOP_VV:
|
||||
case OP_INIT_VECTOR_LOOP_VV:
|
||||
case OP_INIT_STRING_LOOP_VV:
|
||||
{
|
||||
// For all of these, the scope of the aggregate being
|
||||
// looped over is the entire loop, even if it doesn't
|
||||
// directly appear in it, and not just the initializer.
|
||||
// For all three, the aggregate is in v1.
|
||||
ASSERT(i < insts1.size() - 1);
|
||||
auto succ = insts1[i+1];
|
||||
ASSERT(succ->live);
|
||||
auto depth = succ->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(succ, depth));
|
||||
|
||||
// Important: we skip the usual UsesSlots analysis
|
||||
// below since we've already set it, and don't want
|
||||
// to perturb ExtendLifetime's consistency check.
|
||||
continue;
|
||||
}
|
||||
|
||||
case OP_STORE_GLOBAL_V:
|
||||
{
|
||||
// Use of the global goes to here.
|
||||
auto slot = frame_layout1[globalsI[inst->v1].id.get()];
|
||||
ExtendLifetime(slot, EndOfLoop(inst, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Look for slots in auxiliary information.
|
||||
auto aux = inst->aux;
|
||||
if ( ! aux || ! aux->slots )
|
||||
// No need to check the additional "var" associated
|
||||
// with OP_NEXT_TABLE_ITER_VAL_VAR_VVV as that's
|
||||
// a slot-1 assignment. However, similar to other
|
||||
// loop variables, mark this as a usage.
|
||||
if ( inst->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV )
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
for ( auto j = 0; j < aux->n; ++j )
|
||||
{
|
||||
if ( aux->slots[j] < 0 )
|
||||
continue;
|
||||
case OP_NEXT_TABLE_ITER_NO_VARS_VV:
|
||||
break;
|
||||
|
||||
ExtendLifetime(aux->slots[j],
|
||||
EndOfLoop(inst, 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV:
|
||||
{
|
||||
auto depth = inst->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEXT_VECTOR_ITER_VVV:
|
||||
case OP_NEXT_STRING_ITER_VVV:
|
||||
// Sometimes loops are written that don't actually
|
||||
// use the iteration variable. However, we still
|
||||
// need to mark the variable as having usage
|
||||
// throughout the loop, lest we elide the iteration
|
||||
// instruction. An alternative would be to transform
|
||||
// such iterators into variable-less versions. That
|
||||
// optimization hardly seems worth the trouble, though,
|
||||
// given the presumed rarity of such loops.
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, inst->loop_depth));
|
||||
break;
|
||||
|
||||
case OP_INIT_TABLE_LOOP_VV:
|
||||
case OP_INIT_VECTOR_LOOP_VV:
|
||||
case OP_INIT_STRING_LOOP_VV:
|
||||
{
|
||||
// For all of these, the scope of the aggregate being
|
||||
// looped over is the entire loop, even if it doesn't
|
||||
// directly appear in it, and not just the initializer.
|
||||
// For all three, the aggregate is in v1.
|
||||
ASSERT(i < insts1.size() - 1);
|
||||
auto succ = insts1[i + 1];
|
||||
ASSERT(succ->live);
|
||||
auto depth = succ->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(succ, depth));
|
||||
|
||||
// Important: we skip the usual UsesSlots analysis
|
||||
// below since we've already set it, and don't want
|
||||
// to perturb ExtendLifetime's consistency check.
|
||||
continue;
|
||||
}
|
||||
|
||||
case OP_STORE_GLOBAL_V:
|
||||
{
|
||||
// Use of the global goes to here.
|
||||
auto slot = frame_layout1[globalsI[inst->v1].id.get()];
|
||||
ExtendLifetime(slot, EndOfLoop(inst, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Look for slots in auxiliary information.
|
||||
auto aux = inst->aux;
|
||||
if ( ! aux || ! aux->slots )
|
||||
break;
|
||||
|
||||
for ( auto j = 0; j < aux->n; ++j )
|
||||
{
|
||||
if ( aux->slots[j] < 0 )
|
||||
continue;
|
||||
|
||||
ExtendLifetime(aux->slots[j], EndOfLoop(inst, 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int s1, s2, s3, s4;
|
||||
|
||||
|
@ -560,47 +555,49 @@ void ZAMCompiler::ReMapFrame()
|
|||
}
|
||||
|
||||
// Handle special cases.
|
||||
switch ( inst->op ) {
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
switch ( inst->op )
|
||||
{
|
||||
// Rewrite iteration variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
for ( auto& v : iter_vars )
|
||||
{
|
||||
ASSERT(v >= 0 && v < n1_slots);
|
||||
v = frame1_to_frame2[v];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Update slots in auxiliary information.
|
||||
auto aux = inst->aux;
|
||||
if ( ! aux || ! aux->slots )
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
{
|
||||
// Rewrite iteration variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
for ( auto& v : iter_vars )
|
||||
{
|
||||
ASSERT(v >= 0 && v < n1_slots);
|
||||
v = frame1_to_frame2[v];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
for ( auto j = 0; j < aux->n; ++j )
|
||||
{
|
||||
auto& slot = aux->slots[j];
|
||||
default:
|
||||
// Update slots in auxiliary information.
|
||||
auto aux = inst->aux;
|
||||
if ( ! aux || ! aux->slots )
|
||||
break;
|
||||
|
||||
if ( slot < 0 )
|
||||
// This is instead a constant.
|
||||
continue;
|
||||
|
||||
auto new_slot = frame1_to_frame2[slot];
|
||||
|
||||
if ( new_slot < 0 )
|
||||
for ( auto j = 0; j < aux->n; ++j )
|
||||
{
|
||||
ODesc d;
|
||||
inst->stmt->GetLocationInfo()->Describe(&d);
|
||||
reporter->Error("%s: value used but not set: %s", d.Description(), frame_denizens[slot]->Name());
|
||||
}
|
||||
auto& slot = aux->slots[j];
|
||||
|
||||
slot = new_slot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( slot < 0 )
|
||||
// This is instead a constant.
|
||||
continue;
|
||||
|
||||
auto new_slot = frame1_to_frame2[slot];
|
||||
|
||||
if ( new_slot < 0 )
|
||||
{
|
||||
ODesc d;
|
||||
inst->stmt->GetLocationInfo()->Describe(&d);
|
||||
reporter->Error("%s: value used but not set: %s", d.Description(),
|
||||
frame_denizens[slot]->Name());
|
||||
}
|
||||
|
||||
slot = new_slot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( inst->IsGlobalLoad() )
|
||||
{
|
||||
|
@ -686,8 +683,7 @@ void ZAMCompiler::ReMapVar(ID* id, int slot, bro_uint_t inst)
|
|||
// ZAM instructions are careful to allow operands and
|
||||
// assignment destinations to refer to the same slot.
|
||||
|
||||
if ( s.scope_end <= static_cast<int>(inst) &&
|
||||
s.is_managed == is_managed )
|
||||
if ( s.scope_end <= static_cast<int>(inst) && s.is_managed == is_managed )
|
||||
{ // It's compatible.
|
||||
if ( s.scope_end == static_cast<int>(inst) )
|
||||
{ // It ends right on the money.
|
||||
|
@ -728,8 +724,7 @@ void ZAMCompiler::ReMapVar(ID* id, int slot, bro_uint_t inst)
|
|||
|
||||
void ZAMCompiler::CheckSlotAssignment(int slot, const ZInstI* inst)
|
||||
{
|
||||
ASSERT(slot >= 0 &&
|
||||
static_cast<bro_uint_t>(slot) < frame_denizens.size());
|
||||
ASSERT(slot >= 0 && static_cast<bro_uint_t>(slot) < frame_denizens.size());
|
||||
|
||||
// We construct temporaries such that their values are never used
|
||||
// earlier than their definitions in loop bodies. For other
|
||||
|
@ -774,7 +769,8 @@ void ZAMCompiler::CheckSlotUse(int slot, const ZInstI* inst)
|
|||
{
|
||||
ODesc d;
|
||||
inst->stmt->GetLocationInfo()->Describe(&d);
|
||||
reporter->Error("%s: value used but not set: %s", d.Description(), frame_denizens[slot]->Name());
|
||||
reporter->Error("%s: value used but not set: %s", d.Description(),
|
||||
frame_denizens[slot]->Name());
|
||||
}
|
||||
|
||||
// See comment above about temporaries not having their values
|
||||
|
@ -808,17 +804,15 @@ void ZAMCompiler::ExtendLifetime(int slot, const ZInstI* inst)
|
|||
// extended lifetimes, as that can happen if they're
|
||||
// used as a "for" loop-over target, which already
|
||||
// extends lifetime across the body of the loop.
|
||||
if ( inst->loop_depth > 0 &&
|
||||
reducer->IsTemporary(frame_denizens[slot]) &&
|
||||
if ( inst->loop_depth > 0 && reducer->IsTemporary(frame_denizens[slot]) &&
|
||||
old_inst->inst_num >= inst->inst_num )
|
||||
return;
|
||||
|
||||
// We expect to only be increasing the slot's lifetime ...
|
||||
// *unless* we're inside a nested loop, in which case
|
||||
// *unless* we're inside a nested loop, in which case
|
||||
// the slot might have already been extended to the
|
||||
// end of the outer loop.
|
||||
ASSERT(old_inst->inst_num <= inst->inst_num ||
|
||||
inst->loop_depth > 1);
|
||||
ASSERT(old_inst->inst_num <= inst->inst_num || inst->loop_depth > 1);
|
||||
|
||||
if ( old_inst->inst_num < inst->inst_num )
|
||||
{ // Extend.
|
||||
|
@ -898,8 +892,7 @@ bool ZAMCompiler::VarIsAssigned(int slot, const ZInstI* i) const
|
|||
// Special-case for table iterators, which assign to a bunch
|
||||
// of variables but they're not immediately visible in the
|
||||
// instruction layout.
|
||||
if ( i->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV ||
|
||||
i->op == OP_NEXT_TABLE_ITER_VV )
|
||||
if ( i->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV || i->op == OP_NEXT_TABLE_ITER_VV )
|
||||
{
|
||||
auto& iter_vars = i->aux->loop_vars;
|
||||
for ( auto v : iter_vars )
|
||||
|
@ -1061,4 +1054,4 @@ void ZAMCompiler::KillInsts(bro_uint_t i)
|
|||
}
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
// Methods for dealing with ZAM branches.
|
||||
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
void ZAMCompiler::PushGoTos(GoToSets& gotos)
|
||||
{
|
||||
|
@ -63,7 +63,7 @@ InstLabel ZAMCompiler::GoToTargetBeyond(const ZAMStmt s)
|
|||
return pending_inst;
|
||||
}
|
||||
|
||||
return insts1[n+1];
|
||||
return insts1[n + 1];
|
||||
}
|
||||
|
||||
void ZAMCompiler::SetTarget(ZInstI* inst, const InstLabel l, int slot)
|
||||
|
@ -89,10 +89,9 @@ ZInstI* ZAMCompiler::FindLiveTarget(ZInstI* goto_target)
|
|||
return insts1[idx];
|
||||
}
|
||||
|
||||
void ZAMCompiler::ConcretizeBranch(ZInstI* inst, ZInstI* target,
|
||||
int target_slot)
|
||||
void ZAMCompiler::ConcretizeBranch(ZInstI* inst, ZInstI* target, int target_slot)
|
||||
{
|
||||
int t; // instruction number of target
|
||||
int t; // instruction number of target
|
||||
|
||||
if ( target == pending_inst )
|
||||
{
|
||||
|
@ -106,15 +105,24 @@ void ZAMCompiler::ConcretizeBranch(ZInstI* inst, ZInstI* target,
|
|||
else
|
||||
t = target->inst_num;
|
||||
|
||||
switch ( target_slot ) {
|
||||
case 1: inst->v1 = t; break;
|
||||
case 2: inst->v2 = t; break;
|
||||
case 3: inst->v3 = t; break;
|
||||
case 4: inst->v4 = t; break;
|
||||
switch ( target_slot )
|
||||
{
|
||||
case 1:
|
||||
inst->v1 = t;
|
||||
break;
|
||||
case 2:
|
||||
inst->v2 = t;
|
||||
break;
|
||||
case 3:
|
||||
inst->v3 = t;
|
||||
break;
|
||||
case 4:
|
||||
inst->v4 = t;
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad GoTo target");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad GoTo target");
|
||||
}
|
||||
}
|
||||
|
||||
void ZAMCompiler::SetV1(ZAMStmt s, const InstLabel l)
|
||||
|
@ -168,4 +176,4 @@ void ZAMCompiler::SetV4(ZAMStmt s, const InstLabel l)
|
|||
inst->op_type = OP_VVVV_I4;
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
bool ZAMCompiler::IsZAM_BuiltIn(const Expr* e)
|
||||
{
|
||||
|
@ -36,44 +37,36 @@ bool ZAMCompiler::IsZAM_BuiltIn(const Expr* e)
|
|||
|
||||
auto& args = c->Args()->Exprs();
|
||||
|
||||
const NameExpr* n = nullptr; // name to assign to, if any
|
||||
const NameExpr* n = nullptr; // name to assign to, if any
|
||||
|
||||
if ( e->Tag() != EXPR_CALL )
|
||||
n = e->GetOp1()->AsRefExpr()->GetOp1()->AsNameExpr();
|
||||
|
||||
using GenBuiltIn = bool (ZAMCompiler::*)(const NameExpr* n,
|
||||
const ExprPList& args);
|
||||
using GenBuiltIn = bool (ZAMCompiler::*)(const NameExpr* n, const ExprPList& args);
|
||||
static std::vector<std::pair<const char*, GenBuiltIn>> builtins = {
|
||||
{ "Analyzer::__name", &ZAMCompiler::BuiltIn_Analyzer__name },
|
||||
{ "Broker::__flush_logs",
|
||||
&ZAMCompiler::BuiltIn_Broker__flush_logs },
|
||||
{ "Files::__enable_reassembly",
|
||||
&ZAMCompiler::BuiltIn_Files__enable_reassembly },
|
||||
{ "Files::__set_reassembly_buffer",
|
||||
&ZAMCompiler::BuiltIn_Files__set_reassembly_buffer },
|
||||
{ "Log::__write", &ZAMCompiler::BuiltIn_Log__write },
|
||||
{ "current_time", &ZAMCompiler::BuiltIn_current_time },
|
||||
{ "get_port_transport_proto",
|
||||
&ZAMCompiler::BuiltIn_get_port_etc },
|
||||
{ "network_time", &ZAMCompiler::BuiltIn_network_time },
|
||||
{ "reading_live_traffic",
|
||||
&ZAMCompiler::BuiltIn_reading_live_traffic },
|
||||
{ "reading_traces", &ZAMCompiler::BuiltIn_reading_traces },
|
||||
{ "strstr", &ZAMCompiler::BuiltIn_strstr },
|
||||
{ "sub_bytes", &ZAMCompiler::BuiltIn_sub_bytes },
|
||||
{ "to_lower", &ZAMCompiler::BuiltIn_to_lower },
|
||||
{"Analyzer::__name", &ZAMCompiler::BuiltIn_Analyzer__name},
|
||||
{"Broker::__flush_logs", &ZAMCompiler::BuiltIn_Broker__flush_logs},
|
||||
{"Files::__enable_reassembly", &ZAMCompiler::BuiltIn_Files__enable_reassembly},
|
||||
{"Files::__set_reassembly_buffer", &ZAMCompiler::BuiltIn_Files__set_reassembly_buffer},
|
||||
{"Log::__write", &ZAMCompiler::BuiltIn_Log__write},
|
||||
{"current_time", &ZAMCompiler::BuiltIn_current_time},
|
||||
{"get_port_transport_proto", &ZAMCompiler::BuiltIn_get_port_etc},
|
||||
{"network_time", &ZAMCompiler::BuiltIn_network_time},
|
||||
{"reading_live_traffic", &ZAMCompiler::BuiltIn_reading_live_traffic},
|
||||
{"reading_traces", &ZAMCompiler::BuiltIn_reading_traces},
|
||||
{"strstr", &ZAMCompiler::BuiltIn_strstr},
|
||||
{"sub_bytes", &ZAMCompiler::BuiltIn_sub_bytes},
|
||||
{"to_lower", &ZAMCompiler::BuiltIn_to_lower},
|
||||
};
|
||||
|
||||
for ( auto& b : builtins )
|
||||
if ( util::streq(func->Name(), b.first) )
|
||||
return (this->*(b.second))(n ,args);
|
||||
return (this->*(b.second))(n, args);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ZAMCompiler::BuiltIn_Analyzer__name(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_Analyzer__name(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( ! n )
|
||||
{
|
||||
|
@ -97,20 +90,17 @@ bool ZAMCompiler::BuiltIn_Analyzer__name(const NameExpr* n,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ZAMCompiler::BuiltIn_Broker__flush_logs(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_Broker__flush_logs(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( n )
|
||||
AddInst(ZInstI(OP_BROKER_FLUSH_LOGS_V,
|
||||
Frame1Slot(n, OP1_WRITE)));
|
||||
AddInst(ZInstI(OP_BROKER_FLUSH_LOGS_V, Frame1Slot(n, OP1_WRITE)));
|
||||
else
|
||||
AddInst(ZInstI(OP_BROKER_FLUSH_LOGS_X));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZAMCompiler::BuiltIn_Files__enable_reassembly(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_Files__enable_reassembly(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( n )
|
||||
// While this built-in nominally returns a value, existing
|
||||
|
@ -129,8 +119,7 @@ bool ZAMCompiler::BuiltIn_Files__enable_reassembly(const NameExpr* n,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ZAMCompiler::BuiltIn_Files__set_reassembly_buffer(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_Files__set_reassembly_buffer(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( n )
|
||||
// See above for enable_reassembly
|
||||
|
@ -151,8 +140,7 @@ bool ZAMCompiler::BuiltIn_Files__set_reassembly_buffer(const NameExpr* n,
|
|||
z.op_type = OP_VV_I2;
|
||||
}
|
||||
else
|
||||
z = ZInstI(OP_FILES__SET_REASSEMBLY_BUFFER_VV, arg_f,
|
||||
FrameSlot(args[1]->AsNameExpr()));
|
||||
z = ZInstI(OP_FILES__SET_REASSEMBLY_BUFFER_VV, arg_f, FrameSlot(args[1]->AsNameExpr()));
|
||||
|
||||
AddInst(z);
|
||||
|
||||
|
@ -191,8 +179,7 @@ bool ZAMCompiler::BuiltIn_Log__write(const NameExpr* n, const ExprPList& args)
|
|||
z.aux = aux;
|
||||
}
|
||||
else
|
||||
z = ZInstI(OP_LOG_WRITE_VVV, nslot,
|
||||
FrameSlot(id->AsNameExpr()), col_slot);
|
||||
z = ZInstI(OP_LOG_WRITE_VVV, nslot, FrameSlot(id->AsNameExpr()), col_slot);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -202,8 +189,7 @@ bool ZAMCompiler::BuiltIn_Log__write(const NameExpr* n, const ExprPList& args)
|
|||
z.aux = aux;
|
||||
}
|
||||
else
|
||||
z = ZInstI(OP_LOG_WRITE_VV, FrameSlot(id->AsNameExpr()),
|
||||
col_slot);
|
||||
z = ZInstI(OP_LOG_WRITE_VV, FrameSlot(id->AsNameExpr()), col_slot);
|
||||
}
|
||||
|
||||
z.SetType(columns_n->GetType());
|
||||
|
@ -264,8 +250,7 @@ bool ZAMCompiler::BuiltIn_network_time(const NameExpr* n, const ExprPList& args)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ZAMCompiler::BuiltIn_reading_live_traffic(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_reading_live_traffic(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( ! n )
|
||||
{
|
||||
|
@ -280,8 +265,7 @@ bool ZAMCompiler::BuiltIn_reading_live_traffic(const NameExpr* n,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ZAMCompiler::BuiltIn_reading_traces(const NameExpr* n,
|
||||
const ExprPList& args)
|
||||
bool ZAMCompiler::BuiltIn_reading_traces(const NameExpr* n, const ExprPList& args)
|
||||
{
|
||||
if ( ! n )
|
||||
{
|
||||
|
@ -308,8 +292,7 @@ bool ZAMCompiler::BuiltIn_strstr(const NameExpr* n, const ExprPList& args)
|
|||
auto little = args[1];
|
||||
|
||||
auto big_n = big->Tag() == EXPR_NAME ? big->AsNameExpr() : nullptr;
|
||||
auto little_n = little->Tag() == EXPR_NAME ?
|
||||
little->AsNameExpr() : nullptr;
|
||||
auto little_n = little->Tag() == EXPR_NAME ? little->AsNameExpr() : nullptr;
|
||||
|
||||
ZInstI z;
|
||||
|
||||
|
@ -349,54 +332,55 @@ bool ZAMCompiler::BuiltIn_sub_bytes(const NameExpr* n, const ExprPList& args)
|
|||
|
||||
ZInstI z;
|
||||
|
||||
switch ( ConstArgsMask(args, 3) ) {
|
||||
case 0x0: // all variable
|
||||
z = ZInstI(OP_SUB_BYTES_VVVV, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV;
|
||||
break;
|
||||
switch ( ConstArgsMask(args, 3) )
|
||||
{
|
||||
case 0x0: // all variable
|
||||
z = ZInstI(OP_SUB_BYTES_VVVV, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV;
|
||||
break;
|
||||
|
||||
case 0x1: // last argument a constant
|
||||
z = ZInstI(OP_SUB_BYTES_VVVi, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV_I4;
|
||||
break;
|
||||
case 0x1: // last argument a constant
|
||||
z = ZInstI(OP_SUB_BYTES_VVVi, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV_I4;
|
||||
break;
|
||||
|
||||
case 0x2: // 2nd argument a constant; flip!
|
||||
z = ZInstI(OP_SUB_BYTES_VViV, nslot, v2, v4, v3);
|
||||
z.op_type = OP_VVVV_I4;
|
||||
break;
|
||||
case 0x2: // 2nd argument a constant; flip!
|
||||
z = ZInstI(OP_SUB_BYTES_VViV, nslot, v2, v4, v3);
|
||||
z.op_type = OP_VVVV_I4;
|
||||
break;
|
||||
|
||||
case 0x3: // both 2nd and third are constants
|
||||
z = ZInstI(OP_SUB_BYTES_VVii, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV_I3_I4;
|
||||
break;
|
||||
case 0x3: // both 2nd and third are constants
|
||||
z = ZInstI(OP_SUB_BYTES_VVii, nslot, v2, v3, v4);
|
||||
z.op_type = OP_VVVV_I3_I4;
|
||||
break;
|
||||
|
||||
case 0x4: // first argument a constant
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_VVVC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC;
|
||||
break;
|
||||
case 0x4: // first argument a constant
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_VVVC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC;
|
||||
break;
|
||||
|
||||
case 0x5: // first and third constant
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_VViC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC_I3;
|
||||
break;
|
||||
case 0x5: // first and third constant
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_VViC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC_I3;
|
||||
break;
|
||||
|
||||
case 0x6: // first and second constant - flip!
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_ViVC, nslot, v4, v3, c);
|
||||
z.op_type = OP_VVVC_I3;
|
||||
break;
|
||||
case 0x6: // first and second constant - flip!
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_ViVC, nslot, v4, v3, c);
|
||||
z.op_type = OP_VVVC_I3;
|
||||
break;
|
||||
|
||||
case 0x7: // whole shebang
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_ViiC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC_I2_I3;
|
||||
break;
|
||||
case 0x7: // whole shebang
|
||||
ASSERT(c);
|
||||
z = ZInstI(OP_SUB_BYTES_ViiC, nslot, v3, v4, c);
|
||||
z.op_type = OP_VVVC_I2_I3;
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad constant mask");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad constant mask");
|
||||
}
|
||||
|
||||
AddInst(z);
|
||||
|
||||
|
@ -448,4 +432,4 @@ bro_uint_t ZAMCompiler::ConstArgsMask(const ExprPList& args, int nargs) const
|
|||
return mask;
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
#include "zeek/script_opt/UseDefs.h"
|
||||
#include "zeek/script_opt/ZAM/ZBody.h"
|
||||
|
||||
namespace zeek {
|
||||
namespace zeek
|
||||
{
|
||||
class EventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
class NameExpr;
|
||||
class ConstExpr;
|
||||
|
@ -31,50 +33,48 @@ using InstLabel = ZInstI*;
|
|||
// but related to, the ZAM instruction(s) generated for that compilation.)
|
||||
// Designed to be fully opaque, but also effective without requiring pointer
|
||||
// management.
|
||||
class ZAMStmt {
|
||||
class ZAMStmt
|
||||
{
|
||||
protected:
|
||||
friend class ZAMCompiler;
|
||||
|
||||
ZAMStmt() { stmt_num = -1; /* flag that it needs to be set */ }
|
||||
ZAMStmt(int _stmt_num) { stmt_num = _stmt_num; }
|
||||
ZAMStmt() { stmt_num = -1; /* flag that it needs to be set */ }
|
||||
ZAMStmt(int _stmt_num) { stmt_num = _stmt_num; }
|
||||
|
||||
int stmt_num;
|
||||
};
|
||||
};
|
||||
|
||||
// Class that holds values that only have meaning to the ZAM compiler,
|
||||
// but that needs to be held (opaquely, via a pointer) by external
|
||||
// objects.
|
||||
class OpaqueVals {
|
||||
class OpaqueVals
|
||||
{
|
||||
public:
|
||||
OpaqueVals(ZInstAux* _aux) { aux = _aux; }
|
||||
OpaqueVals(ZInstAux* _aux) { aux = _aux; }
|
||||
|
||||
ZInstAux* aux;
|
||||
};
|
||||
};
|
||||
|
||||
class ZAMCompiler {
|
||||
class ZAMCompiler
|
||||
{
|
||||
public:
|
||||
ZAMCompiler(ScriptFunc* f, std::shared_ptr<ProfileFunc> pf,
|
||||
ScopePtr scope, StmtPtr body, std::shared_ptr<UseDefs> ud,
|
||||
std::shared_ptr<Reducer> rd);
|
||||
ZAMCompiler(ScriptFunc* f, std::shared_ptr<ProfileFunc> pf, ScopePtr scope, StmtPtr body,
|
||||
std::shared_ptr<UseDefs> ud, std::shared_ptr<Reducer> rd);
|
||||
|
||||
StmtPtr CompileBody();
|
||||
|
||||
const FrameReMap& FrameDenizens() const
|
||||
{ return shared_frame_denizens_final; }
|
||||
const FrameReMap& FrameDenizens() const { return shared_frame_denizens_final; }
|
||||
|
||||
const std::vector<int>& ManagedSlots() const
|
||||
{ return managed_slotsI; }
|
||||
const std::vector<int>& ManagedSlots() const { return managed_slotsI; }
|
||||
|
||||
const std::vector<GlobalInfo>& Globals() const
|
||||
{ return globalsI; }
|
||||
const std::vector<GlobalInfo>& Globals() const { return globalsI; }
|
||||
|
||||
bool NonRecursive() const { return non_recursive; }
|
||||
bool NonRecursive() const { return non_recursive; }
|
||||
|
||||
const TableIterVec& GetTableIters() const { return table_iters; }
|
||||
int NumStepIters() const { return num_step_iters; }
|
||||
const TableIterVec& GetTableIters() const { return table_iters; }
|
||||
int NumStepIters() const { return num_step_iters; }
|
||||
|
||||
template <typename T>
|
||||
const CaseMaps<T>& GetCases() const
|
||||
template <typename T> const CaseMaps<T>& GetCases() const
|
||||
{
|
||||
if constexpr ( std::is_same_v<T, bro_int_t> )
|
||||
return int_cases;
|
||||
|
@ -109,24 +109,21 @@ private:
|
|||
// switches.
|
||||
// See ZBody.h for their concrete counterparts, which we've
|
||||
// already #include'd.
|
||||
template<typename T> using CaseMapI = std::map<T, InstLabel>;
|
||||
template<typename T> using CaseMapsI = std::vector<CaseMapI<T>>;
|
||||
template <typename T> using CaseMapI = std::map<T, InstLabel>;
|
||||
template <typename T> using CaseMapsI = std::vector<CaseMapI<T>>;
|
||||
|
||||
template <typename T>
|
||||
void ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases,
|
||||
CaseMaps<T>& concrete_cases);
|
||||
void ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases, CaseMaps<T>& concrete_cases);
|
||||
|
||||
template <typename T>
|
||||
void DumpCases(const T& cases, const char* type_name) const;
|
||||
template <typename T> void DumpCases(const T& cases, const char* type_name) const;
|
||||
void DumpInsts1(const FrameReMap* remappings);
|
||||
|
||||
#include "zeek/ZAM-MethodDecls.h"
|
||||
|
||||
const ZAMStmt CompileStmt(const StmtPtr& body)
|
||||
{ return CompileStmt(body.get()); }
|
||||
const ZAMStmt CompileStmt(const StmtPtr& body) { return CompileStmt(body.get()); }
|
||||
const ZAMStmt CompileStmt(const Stmt* body);
|
||||
|
||||
void SetCurrStmt(const Stmt* stmt) { curr_stmt = stmt; }
|
||||
void SetCurrStmt(const Stmt* stmt) { curr_stmt = stmt; }
|
||||
|
||||
const ZAMStmt CompilePrint(const PrintStmt* ps);
|
||||
const ZAMStmt CompileExpr(const ExprStmt* es);
|
||||
|
@ -142,105 +139,89 @@ private:
|
|||
const ZAMStmt CompileInit(const InitStmt* is);
|
||||
const ZAMStmt CompileWhen(const WhenStmt* ws);
|
||||
|
||||
const ZAMStmt CompileNext()
|
||||
{ return GenGoTo(nexts.back()); }
|
||||
const ZAMStmt CompileBreak()
|
||||
{ return GenGoTo(breaks.back()); }
|
||||
const ZAMStmt CompileFallThrough()
|
||||
{ return GenGoTo(fallthroughs.back()); }
|
||||
const ZAMStmt CompileCatchReturn()
|
||||
{ return GenGoTo(catches.back()); }
|
||||
const ZAMStmt CompileNext() { return GenGoTo(nexts.back()); }
|
||||
const ZAMStmt CompileBreak() { return GenGoTo(breaks.back()); }
|
||||
const ZAMStmt CompileFallThrough() { return GenGoTo(fallthroughs.back()); }
|
||||
const ZAMStmt CompileCatchReturn() { return GenGoTo(catches.back()); }
|
||||
|
||||
const ZAMStmt IfElse(const Expr* e, const Stmt* s1, const Stmt* s2);
|
||||
const ZAMStmt While(const Stmt* cond_stmt, const Expr* cond,
|
||||
const Stmt* body);
|
||||
const ZAMStmt While(const Stmt* cond_stmt, const Expr* cond, const Stmt* body);
|
||||
|
||||
const ZAMStmt InitRecord(IDPtr id, RecordType* rt);
|
||||
const ZAMStmt InitVector(IDPtr id, VectorType* vt);
|
||||
const ZAMStmt InitTable(IDPtr id, TableType* tt, Attributes* attrs);
|
||||
|
||||
const ZAMStmt ValueSwitch(const SwitchStmt* sw, const NameExpr* v,
|
||||
const ConstExpr* c);
|
||||
const ZAMStmt TypeSwitch(const SwitchStmt* sw, const NameExpr* v,
|
||||
const ConstExpr* c);
|
||||
const ZAMStmt ValueSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
const ZAMStmt TypeSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c);
|
||||
|
||||
void PushNexts() { PushGoTos(nexts); }
|
||||
void PushBreaks() { PushGoTos(breaks); }
|
||||
void PushFallThroughs() { PushGoTos(fallthroughs); }
|
||||
void PushCatchReturns() { PushGoTos(catches); }
|
||||
|
||||
void ResolveNexts(const InstLabel l)
|
||||
{ ResolveGoTos(nexts, l); }
|
||||
void ResolveBreaks(const InstLabel l)
|
||||
{ ResolveGoTos(breaks, l); }
|
||||
void ResolveFallThroughs(const InstLabel l)
|
||||
{ ResolveGoTos(fallthroughs, l); }
|
||||
void ResolveCatchReturns(const InstLabel l)
|
||||
{ ResolveGoTos(catches, l); }
|
||||
void PushNexts() { PushGoTos(nexts); }
|
||||
void PushBreaks() { PushGoTos(breaks); }
|
||||
void PushFallThroughs() { PushGoTos(fallthroughs); }
|
||||
void PushCatchReturns() { PushGoTos(catches); }
|
||||
|
||||
void ResolveNexts(const InstLabel l) { ResolveGoTos(nexts, l); }
|
||||
void ResolveBreaks(const InstLabel l) { ResolveGoTos(breaks, l); }
|
||||
void ResolveFallThroughs(const InstLabel l) { ResolveGoTos(fallthroughs, l); }
|
||||
void ResolveCatchReturns(const InstLabel l) { ResolveGoTos(catches, l); }
|
||||
|
||||
const ZAMStmt LoopOverTable(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverVector(const ForStmt* f, const NameExpr* val);
|
||||
const ZAMStmt LoopOverString(const ForStmt* f, const Expr* e);
|
||||
|
||||
const ZAMStmt FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt,
|
||||
const Stmt* body, int iter_slot,
|
||||
bool is_table);
|
||||
const ZAMStmt FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt, const Stmt* body,
|
||||
int iter_slot, bool is_table);
|
||||
|
||||
const ZAMStmt Loop(const Stmt* body);
|
||||
|
||||
|
||||
const ZAMStmt CompileExpr(const ExprPtr& e)
|
||||
{ return CompileExpr(e.get()); }
|
||||
const ZAMStmt CompileExpr(const ExprPtr& e) { return CompileExpr(e.get()); }
|
||||
const ZAMStmt CompileExpr(const Expr* body);
|
||||
|
||||
const ZAMStmt CompileIncrExpr(const IncrExpr* e);
|
||||
const ZAMStmt CompileAppendToExpr(const AppendToExpr* e);
|
||||
const ZAMStmt CompileAssignExpr(const AssignExpr* e);
|
||||
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs,
|
||||
const IndexExpr* rhs);
|
||||
const ZAMStmt CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs);
|
||||
const ZAMStmt CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e);
|
||||
const ZAMStmt CompileScheduleExpr(const ScheduleExpr* e);
|
||||
const ZAMStmt CompileSchedule(const NameExpr* n, const ConstExpr* c,
|
||||
int is_interval, EventHandler* h,
|
||||
const ListExpr* l);
|
||||
const ZAMStmt CompileSchedule(const NameExpr* n, const ConstExpr* c, int is_interval,
|
||||
EventHandler* h, const ListExpr* l);
|
||||
const ZAMStmt CompileEvent(EventHandler* h, const ListExpr* l);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2,
|
||||
const NameExpr* n3)
|
||||
{ return CompileInExpr(n1, n2, nullptr, n3, nullptr); }
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const NameExpr* n3)
|
||||
{
|
||||
return CompileInExpr(n1, n2, nullptr, n3, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2,
|
||||
const ConstExpr* c)
|
||||
{ return CompileInExpr(n1, n2, nullptr, nullptr, c); }
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c)
|
||||
{
|
||||
return CompileInExpr(n1, n2, nullptr, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ConstExpr* c,
|
||||
const NameExpr* n3)
|
||||
{ return CompileInExpr(n1, nullptr, c, n3, nullptr); }
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ConstExpr* c, const NameExpr* n3)
|
||||
{
|
||||
return CompileInExpr(n1, nullptr, c, n3, nullptr);
|
||||
}
|
||||
|
||||
// In the following, one of n2 or c2 (likewise, n3/c3) will be nil.
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2,
|
||||
const ConstExpr* c2, const NameExpr* n3,
|
||||
const ConstExpr* c3);
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c2,
|
||||
const NameExpr* n3, const ConstExpr* c3);
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
||||
const NameExpr* n2)
|
||||
{ return CompileInExpr(n1, l, n2, nullptr); }
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2)
|
||||
{
|
||||
return CompileInExpr(n1, l, n2, nullptr);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n, const ListExpr* l,
|
||||
const ConstExpr* c)
|
||||
{ return CompileInExpr(n, l, nullptr, c); }
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n, const ListExpr* l, const ConstExpr* c)
|
||||
{
|
||||
return CompileInExpr(n, l, nullptr, c);
|
||||
}
|
||||
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
||||
const NameExpr* n2, const ConstExpr* c);
|
||||
const ZAMStmt CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2,
|
||||
const ConstExpr* c);
|
||||
|
||||
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const NameExpr* n2,
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const NameExpr* n2, const ListExpr* l);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const ConstExpr* c, const ListExpr* l);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, int n2_slot, const TypePtr& n2_type,
|
||||
const ListExpr* l);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, const ConstExpr* c,
|
||||
const ListExpr* l);
|
||||
const ZAMStmt CompileIndex(const NameExpr* n1, int n2_slot,
|
||||
const TypePtr& n2_type, const ListExpr* l);
|
||||
|
||||
// Second argument is which instruction slot holds the branch target.
|
||||
const ZAMStmt GenCond(const Expr* e, int& branch_v);
|
||||
|
@ -252,8 +233,8 @@ private:
|
|||
const ZAMStmt AssignVecElems(const Expr* e);
|
||||
const ZAMStmt AssignTableElem(const Expr* e);
|
||||
|
||||
const ZAMStmt AppendToField(const NameExpr* n1, const NameExpr* n2,
|
||||
const ConstExpr* c, int offset);
|
||||
const ZAMStmt AppendToField(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c,
|
||||
int offset);
|
||||
|
||||
const ZAMStmt ConstructTable(const NameExpr* n, const Expr* e);
|
||||
const ZAMStmt ConstructSet(const NameExpr* n, const Expr* e);
|
||||
|
@ -267,9 +248,8 @@ private:
|
|||
|
||||
const ZAMStmt Is(const NameExpr* n, const Expr* e);
|
||||
|
||||
|
||||
#include "zeek/script_opt/ZAM/Inst-Gen.h"
|
||||
#include "zeek/script_opt/ZAM/BuiltIn.h"
|
||||
#include "zeek/script_opt/ZAM/Inst-Gen.h"
|
||||
|
||||
// A bit weird, but handy for switch statements used in built-in
|
||||
// operations: returns a bit mask of which of the arguments in the
|
||||
|
@ -295,7 +275,6 @@ private:
|
|||
return e->AsConstExpr()->Value()->AsCount();
|
||||
}
|
||||
|
||||
|
||||
using GoToSet = std::vector<ZAMStmt>;
|
||||
using GoToSets = std::vector<GoToSet>;
|
||||
|
||||
|
@ -335,9 +314,7 @@ private:
|
|||
void SetV2(ZAMStmt s, const InstLabel l);
|
||||
void SetV3(ZAMStmt s, const InstLabel l);
|
||||
void SetV4(ZAMStmt s, const InstLabel l);
|
||||
void SetGoTo(ZAMStmt s, const InstLabel targ)
|
||||
{ SetV1(s, targ); }
|
||||
|
||||
void SetGoTo(ZAMStmt s, const InstLabel targ) { SetV1(s, targ); }
|
||||
|
||||
const ZAMStmt StartingBlock();
|
||||
const ZAMStmt FinishBlock(const ZAMStmt start);
|
||||
|
@ -368,8 +345,7 @@ private:
|
|||
|
||||
// Returns the most recent added instruction *other* than those
|
||||
// added for bookkeeping.
|
||||
ZInstI* TopMainInst() { return insts1[top_main_inst]; }
|
||||
|
||||
ZInstI* TopMainInst() { return insts1[top_main_inst]; }
|
||||
|
||||
bool IsUnused(const IDPtr& id, const Stmt* where) const;
|
||||
|
||||
|
@ -378,7 +354,7 @@ private:
|
|||
|
||||
int AddToFrame(ID*);
|
||||
|
||||
int FrameSlot(const IDPtr& id) { return FrameSlot(id.get()); }
|
||||
int FrameSlot(const IDPtr& id) { return FrameSlot(id.get()); }
|
||||
int FrameSlot(const ID* id);
|
||||
int FrameSlotIfName(const Expr* e)
|
||||
{
|
||||
|
@ -386,25 +362,20 @@ private:
|
|||
return n ? FrameSlot(n->Id()) : 0;
|
||||
}
|
||||
|
||||
int FrameSlot(const NameExpr* id)
|
||||
{ return FrameSlot(id->AsNameExpr()->Id()); }
|
||||
int Frame1Slot(const NameExpr* id, ZOp op)
|
||||
{ return Frame1Slot(id->AsNameExpr()->Id(), op); }
|
||||
int FrameSlot(const NameExpr* id) { return FrameSlot(id->AsNameExpr()->Id()); }
|
||||
int Frame1Slot(const NameExpr* id, ZOp op) { return Frame1Slot(id->AsNameExpr()->Id(), op); }
|
||||
|
||||
int Frame1Slot(const ID* id, ZOp op)
|
||||
{ return Frame1Slot(id, op1_flavor[op]); }
|
||||
int Frame1Slot(const NameExpr* n, ZAMOp1Flavor fl)
|
||||
{ return Frame1Slot(n->Id(), fl); }
|
||||
int Frame1Slot(const ID* id, ZOp op) { return Frame1Slot(id, op1_flavor[op]); }
|
||||
int Frame1Slot(const NameExpr* n, ZAMOp1Flavor fl) { return Frame1Slot(n->Id(), fl); }
|
||||
int Frame1Slot(const ID* id, ZAMOp1Flavor fl);
|
||||
|
||||
// The slot without doing any global-related checking.
|
||||
int RawSlot(const NameExpr* n) { return RawSlot(n->Id()); }
|
||||
int RawSlot(const NameExpr* n) { return RawSlot(n->Id()); }
|
||||
int RawSlot(const ID* id);
|
||||
|
||||
bool HasFrameSlot(const ID* id) const;
|
||||
|
||||
int NewSlot(const TypePtr& t)
|
||||
{ return NewSlot(ZVal::IsManagedType(t)); }
|
||||
int NewSlot(const TypePtr& t) { return NewSlot(ZVal::IsManagedType(t)); }
|
||||
int NewSlot(bool is_managed);
|
||||
|
||||
int TempForConst(const ConstExpr* c);
|
||||
|
@ -421,8 +392,7 @@ private:
|
|||
|
||||
// Tracks which instructions can be branched to via the given
|
||||
// set of switches.
|
||||
template<typename T>
|
||||
void TallySwitchTargets(const CaseMapsI<T>& switches);
|
||||
template <typename T> void TallySwitchTargets(const CaseMapsI<T>& switches);
|
||||
|
||||
// Remove code that can't be reached. True if some removal happened.
|
||||
bool RemoveDeadCode();
|
||||
|
@ -504,18 +474,20 @@ private:
|
|||
return FirstLiveInst(insts1[i->inst_num + 1], follow_gotos);
|
||||
}
|
||||
int NextLiveInst(int i, bool follow_gotos = false)
|
||||
{ return FirstLiveInst(i + 1, follow_gotos); }
|
||||
{
|
||||
return FirstLiveInst(i + 1, follow_gotos);
|
||||
}
|
||||
|
||||
// Mark an instruction as unnecessary and remove its influence on
|
||||
// other statements. The instruction is indicated as an offset
|
||||
// into insts1; any labels associated with it are transferred
|
||||
// to its next live successor, if any.
|
||||
void KillInst(ZInstI* i) { KillInst(i->inst_num); }
|
||||
void KillInst(ZInstI* i) { KillInst(i->inst_num); }
|
||||
void KillInst(bro_uint_t i);
|
||||
|
||||
// The same, but kills any successor instructions until finding
|
||||
// one that's labeled.
|
||||
void KillInsts(ZInstI* i) { KillInsts(i->inst_num); }
|
||||
void KillInsts(ZInstI* i) { KillInsts(i->inst_num); }
|
||||
void KillInsts(bro_uint_t i);
|
||||
|
||||
// The first of these is used as we compile down to ZInstI's.
|
||||
|
@ -569,8 +541,7 @@ private:
|
|||
|
||||
// A type for mapping an instruction to a set of locals associated
|
||||
// with it.
|
||||
using AssociatedLocals =
|
||||
std::unordered_map<const ZInstI*, std::unordered_set<ID*>>;
|
||||
using AssociatedLocals = std::unordered_map<const ZInstI*, std::unordered_set<ID*>>;
|
||||
|
||||
// Maps (live) instructions to which frame denizens begin their
|
||||
// lifetime via an initialization at that instruction, if any ...
|
||||
|
@ -595,7 +566,7 @@ private:
|
|||
// values that get finalized when constructing the corresponding
|
||||
// ZBody.
|
||||
std::vector<GlobalInfo> globalsI;
|
||||
std::unordered_map<const ID*, int> global_id_to_info; // inverse
|
||||
std::unordered_map<const ID*, int> global_id_to_info; // inverse
|
||||
|
||||
// Intermediary switch tables (branching to ZInst's rather
|
||||
// than concrete instruction offsets).
|
||||
|
@ -629,11 +600,10 @@ private:
|
|||
// AddInst. If >= 0, then upon adding the next instruction,
|
||||
// it should be followed by Store-Global for the given slot.
|
||||
int pending_global_store = -1;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Invokes after compiling all of the function bodies.
|
||||
class FuncInfo;
|
||||
extern void finalize_functions(const std::vector<FuncInfo>& funcs);
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -3,23 +3,20 @@
|
|||
// Driver (and other high-level) methods for ZAM compilation.
|
||||
|
||||
#include "zeek/CompHash.h"
|
||||
#include "zeek/RE.h"
|
||||
#include "zeek/Frame.h"
|
||||
#include "zeek/module_util.h"
|
||||
#include "zeek/Scope.h"
|
||||
#include "zeek/RE.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/Scope.h"
|
||||
#include "zeek/module_util.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
|
||||
ZAMCompiler::ZAMCompiler(ScriptFunc* f, std::shared_ptr<ProfileFunc> _pf,
|
||||
ScopePtr _scope, StmtPtr _body,
|
||||
std::shared_ptr<UseDefs> _ud,
|
||||
std::shared_ptr<Reducer> _rd)
|
||||
ZAMCompiler::ZAMCompiler(ScriptFunc* f, std::shared_ptr<ProfileFunc> _pf, ScopePtr _scope,
|
||||
StmtPtr _body, std::shared_ptr<UseDefs> _ud, std::shared_ptr<Reducer> _rd)
|
||||
{
|
||||
func = f;
|
||||
pf = std::move(_pf);
|
||||
|
@ -71,8 +68,7 @@ void ZAMCompiler::InitGlobals()
|
|||
|
||||
void ZAMCompiler::InitArgs()
|
||||
{
|
||||
auto uds = ud->HasUsage(body.get()) ? ud->GetUsage(body.get()) :
|
||||
nullptr;
|
||||
auto uds = ud->HasUsage(body.get()) ? ud->GetUsage(body.get()) : nullptr;
|
||||
|
||||
auto args = scope->OrderedVars();
|
||||
int nparam = func->GetType()->Params()->NumFields();
|
||||
|
@ -108,7 +104,7 @@ void ZAMCompiler::InitLocals()
|
|||
// Don't worry about unused variables, those will get
|
||||
// removed during low-level ZAM optimization.
|
||||
if ( ! HasFrameSlot(non_const_l) )
|
||||
(void) AddToFrame(non_const_l);
|
||||
(void)AddToFrame(non_const_l);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +127,7 @@ StmtPtr ZAMCompiler::CompileBody()
|
|||
if ( func->Flavor() == FUNC_FLAVOR_HOOK )
|
||||
PushBreaks();
|
||||
|
||||
(void) CompileStmt(body);
|
||||
(void)CompileStmt(body);
|
||||
|
||||
if ( reporter->Errors() > 0 )
|
||||
return nullptr;
|
||||
|
@ -265,8 +261,7 @@ void ZAMCompiler::ComputeLoopLevels()
|
|||
// We're extending an existing loop. Find
|
||||
// its current end.
|
||||
auto depth = t->loop_depth;
|
||||
while ( j < i &&
|
||||
insts1[j]->loop_depth == depth )
|
||||
while ( j < i && insts1[j]->loop_depth == depth )
|
||||
++j;
|
||||
|
||||
ASSERT(insts1[j]->loop_depth == depth - 1);
|
||||
|
@ -315,8 +310,7 @@ void ZAMCompiler::RemapFrameDenizens(const std::vector<int>& inst1_to_inst2)
|
|||
// the form "slotX = slotX". In that
|
||||
// case, look forward for the next viable
|
||||
// instruction.
|
||||
while ( start < insts1.size() &&
|
||||
inst1_to_inst2[start] == -1 )
|
||||
while ( start < insts1.size() && inst1_to_inst2[start] == -1 )
|
||||
++start;
|
||||
|
||||
ASSERT(start < insts1.size());
|
||||
|
@ -356,7 +350,7 @@ void ZAMCompiler::ConcretizeSwitches()
|
|||
|
||||
template <typename T>
|
||||
void ZAMCompiler::ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases,
|
||||
CaseMaps<T>& concrete_cases)
|
||||
CaseMaps<T>& concrete_cases)
|
||||
{
|
||||
for ( auto& targs : abstract_cases )
|
||||
{
|
||||
|
@ -367,10 +361,8 @@ void ZAMCompiler::ConcretizeSwitchTables(const CaseMapsI<T>& abstract_cases,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#include "ZAM-MethodDefs.h"
|
||||
|
||||
|
||||
void ZAMCompiler::Dump()
|
||||
{
|
||||
bool remapped_frame = ! analysis_options.no_ZAM_opt;
|
||||
|
@ -440,8 +432,7 @@ void ZAMCompiler::Dump()
|
|||
DumpCases(str_casesI, "str");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ZAMCompiler::DumpCases(const T& cases, const char* type_name) const
|
||||
template <typename T> void ZAMCompiler::DumpCases(const T& cases, const char* type_name) const
|
||||
{
|
||||
for ( auto i = 0U; i < cases.size(); ++i )
|
||||
{
|
||||
|
@ -451,8 +442,7 @@ void ZAMCompiler::DumpCases(const T& cases, const char* type_name) const
|
|||
std::string case_val;
|
||||
if constexpr ( std::is_same_v<T, std::string> )
|
||||
case_val = m.first;
|
||||
else if constexpr ( std::is_same_v<T, bro_int_t> ||
|
||||
std::is_same_v<T, bro_uint_t> ||
|
||||
else if constexpr ( std::is_same_v<T, bro_int_t> || std::is_same_v<T, bro_uint_t> ||
|
||||
std::is_same_v<T, double> )
|
||||
case_val = std::to_string(m.first);
|
||||
|
||||
|
@ -471,7 +461,7 @@ void ZAMCompiler::DumpInsts1(const FrameReMap* remappings)
|
|||
if ( inst->target )
|
||||
// To get meaningful branch information in the dump,
|
||||
// we need to concretize the branch slots
|
||||
ConcretizeBranch(inst, inst->target, inst->target_slot);
|
||||
ConcretizeBranch(inst, inst->target, inst->target_slot);
|
||||
|
||||
std::string liveness, depth;
|
||||
|
||||
|
@ -489,5 +479,4 @@ void ZAMCompiler::DumpInsts1(const FrameReMap* remappings)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -2,56 +2,58 @@
|
|||
|
||||
// Methods for traversing Expr AST nodes to generate ZAM code.
|
||||
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileExpr(const Expr* e)
|
||||
{
|
||||
switch ( e->Tag() ) {
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR:
|
||||
return CompileIncrExpr(static_cast<const IncrExpr*>(e));
|
||||
|
||||
case EXPR_APPEND_TO:
|
||||
return CompileAppendToExpr(static_cast<const AppendToExpr*>(e));
|
||||
|
||||
case EXPR_ASSIGN:
|
||||
return CompileAssignExpr(static_cast<const AssignExpr*>(e));
|
||||
|
||||
case EXPR_INDEX_ASSIGN:
|
||||
switch ( e->Tag() )
|
||||
{
|
||||
auto iae = static_cast<const IndexAssignExpr*>(e);
|
||||
auto t = iae->GetOp1()->GetType()->Tag();
|
||||
if ( t == TYPE_VECTOR )
|
||||
return AssignVecElems(iae);
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR:
|
||||
return CompileIncrExpr(static_cast<const IncrExpr*>(e));
|
||||
|
||||
ASSERT(t == TYPE_TABLE);
|
||||
return AssignTableElem(iae);
|
||||
case EXPR_APPEND_TO:
|
||||
return CompileAppendToExpr(static_cast<const AppendToExpr*>(e));
|
||||
|
||||
case EXPR_ASSIGN:
|
||||
return CompileAssignExpr(static_cast<const AssignExpr*>(e));
|
||||
|
||||
case EXPR_INDEX_ASSIGN:
|
||||
{
|
||||
auto iae = static_cast<const IndexAssignExpr*>(e);
|
||||
auto t = iae->GetOp1()->GetType()->Tag();
|
||||
if ( t == TYPE_VECTOR )
|
||||
return AssignVecElems(iae);
|
||||
|
||||
ASSERT(t == TYPE_TABLE);
|
||||
return AssignTableElem(iae);
|
||||
}
|
||||
|
||||
case EXPR_FIELD_LHS_ASSIGN:
|
||||
{
|
||||
auto flhs = static_cast<const FieldLHSAssignExpr*>(e);
|
||||
return CompileFieldLHSAssignExpr(flhs);
|
||||
}
|
||||
|
||||
case EXPR_SCHEDULE:
|
||||
return CompileScheduleExpr(static_cast<const ScheduleExpr*>(e));
|
||||
|
||||
case EXPR_EVENT:
|
||||
{
|
||||
auto ee = static_cast<const EventExpr*>(e);
|
||||
auto h = ee->Handler().Ptr();
|
||||
auto args = ee->Args();
|
||||
return EventHL(h, args);
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad statement type in ZAMCompile::CompileExpr");
|
||||
}
|
||||
|
||||
case EXPR_FIELD_LHS_ASSIGN:
|
||||
{
|
||||
auto flhs = static_cast<const FieldLHSAssignExpr*>(e);
|
||||
return CompileFieldLHSAssignExpr(flhs);
|
||||
}
|
||||
|
||||
case EXPR_SCHEDULE:
|
||||
return CompileScheduleExpr(static_cast<const ScheduleExpr*>(e));
|
||||
|
||||
case EXPR_EVENT:
|
||||
{
|
||||
auto ee = static_cast<const EventExpr*>(e);
|
||||
auto h = ee->Handler().Ptr();
|
||||
auto args = ee->Args();
|
||||
return EventHL(h, args);
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad statement type in ZAMCompile::CompileExpr");
|
||||
}
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileIncrExpr(const IncrExpr* e)
|
||||
|
@ -92,15 +94,14 @@ const ZAMStmt ZAMCompiler::CompileAppendToExpr(const AppendToExpr* e)
|
|||
return n2 ? AppendToVV(n1, n2) : AppendToVC(n1, cc);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::AppendToField(const NameExpr* n1, const NameExpr* n2,
|
||||
const ConstExpr* c, int offset)
|
||||
const ZAMStmt ZAMCompiler::AppendToField(const NameExpr* n1, const NameExpr* n2, const ConstExpr* c,
|
||||
int offset)
|
||||
{
|
||||
ZInstI z;
|
||||
|
||||
if ( n2 )
|
||||
{
|
||||
z = ZInstI(OP_APPENDTOFIELD_VVi, FrameSlot(n1), FrameSlot(n2),
|
||||
offset);
|
||||
z = ZInstI(OP_APPENDTOFIELD_VVi, FrameSlot(n1), FrameSlot(n2), offset);
|
||||
z.op_type = OP_VVV_I3;
|
||||
}
|
||||
else
|
||||
|
@ -125,16 +126,16 @@ const ZAMStmt ZAMCompiler::CompileAssignExpr(const AssignExpr* e)
|
|||
auto rhs = op2.get();
|
||||
auto r1 = rhs->GetOp1();
|
||||
|
||||
if ( rhs->Tag() == EXPR_INDEX &&
|
||||
(r1->Tag() == EXPR_NAME || r1->Tag() == EXPR_CONST) )
|
||||
if ( rhs->Tag() == EXPR_INDEX && (r1->Tag() == EXPR_NAME || r1->Tag() == EXPR_CONST) )
|
||||
return CompileAssignToIndex(lhs, rhs->AsIndexExpr());
|
||||
|
||||
switch ( rhs->Tag() ) {
|
||||
switch ( rhs->Tag() )
|
||||
{
|
||||
#include "ZAM-DirectDefs.h"
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto rt = rhs->GetType();
|
||||
|
||||
|
@ -176,13 +177,10 @@ const ZAMStmt ZAMCompiler::CompileAssignExpr(const AssignExpr* e)
|
|||
}
|
||||
|
||||
if ( rhs->Tag() == EXPR_ANY_INDEX )
|
||||
return AnyIndexVVi(lhs, r1->AsNameExpr(),
|
||||
rhs->AsAnyIndexExpr()->Index());
|
||||
return AnyIndexVVi(lhs, r1->AsNameExpr(), rhs->AsAnyIndexExpr()->Index());
|
||||
|
||||
if ( rhs->Tag() == EXPR_COND && r1->GetType()->Tag() == TYPE_VECTOR )
|
||||
return Bool_Vec_CondVVVV(lhs, r1->AsNameExpr(),
|
||||
r2->AsNameExpr(),
|
||||
r3->AsNameExpr());
|
||||
return Bool_Vec_CondVVVV(lhs, r1->AsNameExpr(), r2->AsNameExpr(), r3->AsNameExpr());
|
||||
|
||||
if ( rhs->Tag() == EXPR_COND && r2->IsConst() && r3->IsConst() )
|
||||
{
|
||||
|
@ -191,7 +189,7 @@ const ZAMStmt ZAMCompiler::CompileAssignExpr(const AssignExpr* e)
|
|||
auto n1 = r1->AsNameExpr();
|
||||
auto c2 = r2->AsConstExpr();
|
||||
auto c3 = r3->AsConstExpr();
|
||||
(void) CondC1VVC(lhs, n1, c2);
|
||||
(void)CondC1VVC(lhs, n1, c2);
|
||||
return CondC2VVC(lhs, n1, c3);
|
||||
}
|
||||
|
||||
|
@ -202,7 +200,8 @@ const ZAMStmt ZAMCompiler::CompileAssignExpr(const AssignExpr* e)
|
|||
|
||||
if ( v1 != v2 && rhs->Tag() != EXPR_IN )
|
||||
{
|
||||
reporter->Error("deprecated mixed vector/scalar operation not supported for ZAM compiling");
|
||||
reporter->Error(
|
||||
"deprecated mixed vector/scalar operation not supported for ZAM compiling");
|
||||
return ErrorStmt();
|
||||
}
|
||||
}
|
||||
|
@ -210,18 +209,17 @@ const ZAMStmt ZAMCompiler::CompileAssignExpr(const AssignExpr* e)
|
|||
if ( r1 && r1->IsConst() )
|
||||
#include "ZAM-GenExprsDefsC1.h"
|
||||
|
||||
else if ( r2 && r2->IsConst() )
|
||||
else if ( r2 && r2->IsConst() )
|
||||
#include "ZAM-GenExprsDefsC2.h"
|
||||
|
||||
else if ( r3 && r3->IsConst() )
|
||||
else if ( r3 && r3->IsConst() )
|
||||
#include "ZAM-GenExprsDefsC3.h"
|
||||
|
||||
else
|
||||
else
|
||||
#include "ZAM-GenExprsDefsV.h"
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileAssignToIndex(const NameExpr* lhs,
|
||||
const IndexExpr* rhs)
|
||||
const ZAMStmt ZAMCompiler::CompileAssignToIndex(const NameExpr* lhs, const IndexExpr* rhs)
|
||||
{
|
||||
auto aggr = rhs->GetOp1();
|
||||
auto const_aggr = aggr->Tag() == EXPR_CONST;
|
||||
|
@ -232,8 +230,7 @@ const ZAMStmt ZAMCompiler::CompileAssignToIndex(const NameExpr* lhs,
|
|||
auto n = const_aggr ? nullptr : aggr->AsNameExpr();
|
||||
auto con = const_aggr ? aggr->AsConstExpr() : nullptr;
|
||||
|
||||
if ( indexes.length() == 1 &&
|
||||
indexes[0]->GetType()->Tag() == TYPE_VECTOR )
|
||||
if ( indexes.length() == 1 && indexes[0]->GetType()->Tag() == TYPE_VECTOR )
|
||||
{
|
||||
auto index1 = indexes[0];
|
||||
if ( index1->Tag() == EXPR_CONST )
|
||||
|
@ -246,16 +243,14 @@ const ZAMStmt ZAMCompiler::CompileAssignToIndex(const NameExpr* lhs,
|
|||
auto ind_t = index->GetType()->AsVectorType();
|
||||
|
||||
if ( IsBool(ind_t->Yield()->Tag()) )
|
||||
return const_aggr ?
|
||||
IndexVecBoolSelectVCV(lhs, con, index) :
|
||||
IndexVecBoolSelectVVV(lhs, n, index);
|
||||
return const_aggr ? IndexVecBoolSelectVCV(lhs, con, index)
|
||||
: IndexVecBoolSelectVVV(lhs, n, index);
|
||||
|
||||
return const_aggr ? IndexVecIntSelectVCV(lhs, con, index) :
|
||||
IndexVecIntSelectVVV(lhs, n, index);
|
||||
return const_aggr ? IndexVecIntSelectVCV(lhs, con, index)
|
||||
: IndexVecIntSelectVVV(lhs, n, index);
|
||||
}
|
||||
|
||||
return const_aggr ? IndexVCL(lhs, con, indexes_expr) :
|
||||
IndexVVL(lhs, n, indexes_expr);
|
||||
return const_aggr ? IndexVCL(lhs, con, indexes_expr) : IndexVVL(lhs, n, indexes_expr);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e)
|
||||
|
@ -277,20 +272,18 @@ const ZAMStmt ZAMCompiler::CompileFieldLHSAssignExpr(const FieldLHSAssignExpr* e
|
|||
{
|
||||
auto rhs_f = rhs->AsFieldExpr();
|
||||
if ( r1->Tag() == EXPR_NAME )
|
||||
return Field_LHS_AssignFVi(e, r1->AsNameExpr(),
|
||||
rhs_f->Field());
|
||||
return Field_LHS_AssignFVi(e, r1->AsNameExpr(), rhs_f->Field());
|
||||
|
||||
return Field_LHS_AssignFCi(e, r1->AsConstExpr(),
|
||||
rhs_f->Field());
|
||||
return Field_LHS_AssignFCi(e, r1->AsConstExpr(), rhs_f->Field());
|
||||
}
|
||||
|
||||
if ( r1 && r1->IsConst() )
|
||||
#include "ZAM-GenFieldsDefsC1.h"
|
||||
|
||||
else if ( r2 && r2->IsConst() )
|
||||
else if ( r2 && r2->IsConst() )
|
||||
#include "ZAM-GenFieldsDefsC2.h"
|
||||
|
||||
else
|
||||
else
|
||||
#include "ZAM-GenFieldsDefsV.h"
|
||||
}
|
||||
|
||||
|
@ -305,15 +298,12 @@ const ZAMStmt ZAMCompiler::CompileScheduleExpr(const ScheduleExpr* e)
|
|||
bool is_interval = when->GetType()->Tag() == TYPE_INTERVAL;
|
||||
|
||||
if ( when->Tag() == EXPR_NAME )
|
||||
return ScheduleViHL(when->AsNameExpr(), is_interval,
|
||||
handler.Ptr(), event_args);
|
||||
return ScheduleViHL(when->AsNameExpr(), is_interval, handler.Ptr(), event_args);
|
||||
else
|
||||
return ScheduleCiHL(when->AsConstExpr(), is_interval,
|
||||
handler.Ptr(), event_args);
|
||||
return ScheduleCiHL(when->AsConstExpr(), is_interval, handler.Ptr(), event_args);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileSchedule(const NameExpr* n,
|
||||
const ConstExpr* c, int is_interval,
|
||||
const ZAMStmt ZAMCompiler::CompileSchedule(const NameExpr* n, const ConstExpr* c, int is_interval,
|
||||
EventHandler* h, const ListExpr* l)
|
||||
{
|
||||
int len = l->Exprs().length();
|
||||
|
@ -321,8 +311,8 @@ const ZAMStmt ZAMCompiler::CompileSchedule(const NameExpr* n,
|
|||
|
||||
if ( len == 0 )
|
||||
{
|
||||
z = n ? ZInstI(OP_SCHEDULE0_ViH, FrameSlot(n), is_interval) :
|
||||
ZInstI(OP_SCHEDULE0_CiH, is_interval, c);
|
||||
z = n ? ZInstI(OP_SCHEDULE0_ViH, FrameSlot(n), is_interval)
|
||||
: ZInstI(OP_SCHEDULE0_CiH, is_interval, c);
|
||||
z.op_type = n ? OP_VV_I2 : OP_VC_I1;
|
||||
}
|
||||
|
||||
|
@ -429,17 +419,17 @@ const ZAMStmt ZAMCompiler::CompileEvent(EventHandler* h, const ListExpr* l)
|
|||
return AddInst(z);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1,
|
||||
const NameExpr* n2,
|
||||
const ConstExpr* c2,
|
||||
const NameExpr* n3,
|
||||
const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const NameExpr* n2,
|
||||
const ConstExpr* c2, const NameExpr* n3,
|
||||
const ConstExpr* c3)
|
||||
{
|
||||
const Expr* op2 = n2;
|
||||
const Expr* op3 = n3;
|
||||
|
||||
if ( ! op2 ) op2 = c2;
|
||||
if ( ! op3 ) op3 = c3;
|
||||
if ( ! op2 )
|
||||
op2 = c2;
|
||||
if ( ! op3 )
|
||||
op3 = c3;
|
||||
|
||||
ZOp a;
|
||||
|
||||
|
@ -449,8 +439,7 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1,
|
|||
else if ( op2->GetType()->Tag() == TYPE_STRING )
|
||||
a = n2 ? (n3 ? OP_S_IN_S_VVV : OP_S_IN_S_VVC) : OP_S_IN_S_VCV;
|
||||
|
||||
else if ( op2->GetType()->Tag() == TYPE_ADDR &&
|
||||
op3->GetType()->Tag() == TYPE_SUBNET )
|
||||
else if ( op2->GetType()->Tag() == TYPE_ADDR && op3->GetType()->Tag() == TYPE_SUBNET )
|
||||
a = n2 ? (n3 ? OP_A_IN_S_VVV : OP_A_IN_S_VVC) : OP_A_IN_S_VCV;
|
||||
|
||||
else if ( op3->GetType()->Tag() == TYPE_TABLE )
|
||||
|
@ -489,8 +478,8 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1,
|
|||
return AddInst(z);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
||||
const NameExpr* n2, const ConstExpr* c)
|
||||
const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l, const NameExpr* n2,
|
||||
const ConstExpr* c)
|
||||
{
|
||||
auto& l_e = l->Exprs();
|
||||
int n = l_e.length();
|
||||
|
@ -505,16 +494,14 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
if ( l_e[0]->Tag() == EXPR_NAME )
|
||||
{
|
||||
auto l_e0_n = l_e[0]->AsNameExpr();
|
||||
ZOp op = is_vec ? OP_VAL_IS_IN_VECTOR_VVV :
|
||||
OP_VAL_IS_IN_TABLE_VVV;
|
||||
ZOp op = is_vec ? OP_VAL_IS_IN_VECTOR_VVV : OP_VAL_IS_IN_TABLE_VVV;
|
||||
z = GenInst(op, n1, l_e0_n, n2);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
auto l_e0_c = l_e[0]->AsConstExpr();
|
||||
ZOp op = is_vec ? OP_CONST_IS_IN_VECTOR_VCV :
|
||||
OP_CONST_IS_IN_TABLE_VCV;
|
||||
ZOp op = is_vec ? OP_CONST_IS_IN_VECTOR_VCV : OP_CONST_IS_IN_TABLE_VCV;
|
||||
z = GenInst(op, n1, l_e0_c, n2);
|
||||
}
|
||||
|
||||
|
@ -525,8 +512,7 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
// Also somewhat common is a 2-element index. Here, one or both of
|
||||
// the elements might be a constant, which makes things messier.
|
||||
|
||||
if ( n == 2 && n2 &&
|
||||
(l_e[0]->Tag() == EXPR_NAME || l_e[1]->Tag() == EXPR_NAME) )
|
||||
if ( n == 2 && n2 && (l_e[0]->Tag() == EXPR_NAME || l_e[1]->Tag() == EXPR_NAME) )
|
||||
{
|
||||
auto is_name0 = l_e[0]->Tag() == EXPR_NAME;
|
||||
auto is_name1 = l_e[1]->Tag() == EXPR_NAME;
|
||||
|
@ -541,8 +527,7 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
|
||||
if ( l_e0_n && l_e1_n )
|
||||
{
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVVV,
|
||||
n1, l_e0_n, l_e1_n, n2);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVVV, n1, l_e0_n, l_e1_n, n2);
|
||||
z.t2 = l_e0_n->GetType();
|
||||
}
|
||||
|
||||
|
@ -550,8 +535,7 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
{
|
||||
ASSERT(l_e1_c);
|
||||
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVVC,
|
||||
n1, l_e0_n, n2, l_e1_c);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVVC, n1, l_e0_n, n2, l_e1_c);
|
||||
z.t2 = l_e0_n->GetType();
|
||||
}
|
||||
|
||||
|
@ -559,21 +543,19 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
{
|
||||
ASSERT(l_e0_c);
|
||||
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVCV,
|
||||
n1, l_e1_n, n2, l_e0_c);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_VVCV, n1, l_e1_n, n2, l_e0_c);
|
||||
z.t2 = l_e1_n->GetType();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Ugh, both are constants. Assign first to
|
||||
// a temporary.
|
||||
// a temporary.
|
||||
ASSERT(l_e0_c);
|
||||
ASSERT(l_e1_c);
|
||||
|
||||
auto slot = TempForConst(l_e0_c);
|
||||
z = ZInstI(OP_VAL2_IS_IN_TABLE_VVVC, FrameSlot(n1),
|
||||
slot, FrameSlot(n2), l_e1_c);
|
||||
z = ZInstI(OP_VAL2_IS_IN_TABLE_VVVC, FrameSlot(n1), slot, FrameSlot(n2), l_e1_c);
|
||||
z.op_type = OP_VVVC;
|
||||
z.t2 = l_e0_c->GetType();
|
||||
}
|
||||
|
@ -581,7 +563,7 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
return AddInst(z);
|
||||
}
|
||||
|
||||
auto aggr = n2 ? (Expr*) n2 : (Expr*) c;
|
||||
auto aggr = n2 ? (Expr*)n2 : (Expr*)c;
|
||||
|
||||
ASSERT(aggr->GetType()->Tag() != TYPE_VECTOR);
|
||||
|
||||
|
@ -599,21 +581,19 @@ const ZAMStmt ZAMCompiler::CompileInExpr(const NameExpr* n1, const ListExpr* l,
|
|||
return AddInst(z);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, const NameExpr* n2,
|
||||
const ListExpr* l)
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, const NameExpr* n2, const ListExpr* l)
|
||||
{
|
||||
return CompileIndex(n1, FrameSlot(n2), n2->GetType(), l);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n, const ConstExpr* c,
|
||||
const ListExpr* l)
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n, const ConstExpr* c, const ListExpr* l)
|
||||
{
|
||||
auto tmp = TempForConst(c);
|
||||
return CompileIndex(n, tmp, c->GetType(), l);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
||||
const TypePtr& n2t, const ListExpr* l)
|
||||
const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot, const TypePtr& n2t,
|
||||
const ListExpr* l)
|
||||
{
|
||||
ZInstI z;
|
||||
|
||||
|
@ -642,14 +622,12 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
|||
{
|
||||
int n3_slot = FrameSlot(n3);
|
||||
auto zop = OP_INDEX_STRING_VVV;
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop),
|
||||
n2_slot, n3_slot);
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, n3_slot);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto zop = OP_INDEX_STRINGC_VVV;
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop),
|
||||
n2_slot, c);
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, c);
|
||||
z.op_type = OP_VVV_I3;
|
||||
}
|
||||
|
||||
|
@ -664,15 +642,12 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
|||
if ( n3 )
|
||||
{
|
||||
int n3_slot = FrameSlot(n3);
|
||||
auto zop = is_any ? OP_INDEX_ANY_VEC_VVV :
|
||||
OP_INDEX_VEC_VVV;
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop),
|
||||
n2_slot, n3_slot);
|
||||
auto zop = is_any ? OP_INDEX_ANY_VEC_VVV : OP_INDEX_VEC_VVV;
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, n3_slot);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto zop = is_any ? OP_INDEX_ANY_VECC_VVV :
|
||||
OP_INDEX_VECC_VVV;
|
||||
auto zop = is_any ? OP_INDEX_ANY_VECC_VVV : OP_INDEX_VECC_VVV;
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, c);
|
||||
z.op_type = OP_VVV_I3;
|
||||
}
|
||||
|
@ -686,10 +661,8 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
|||
if ( n3 )
|
||||
{
|
||||
int n3_slot = FrameSlot(n3);
|
||||
auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVV,
|
||||
n1->GetType()->Tag());
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot,
|
||||
n3_slot);
|
||||
auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVV, n1->GetType()->Tag());
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, n3_slot);
|
||||
z.SetType(n3->GetType());
|
||||
}
|
||||
|
||||
|
@ -697,10 +670,8 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
|||
{
|
||||
ASSERT(c3);
|
||||
|
||||
auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVC,
|
||||
n1->GetType()->Tag());
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop),
|
||||
n2_slot, c3);
|
||||
auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVC, n1->GetType()->Tag());
|
||||
z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, c3);
|
||||
}
|
||||
|
||||
return AddInst(z);
|
||||
|
@ -711,28 +682,29 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot,
|
|||
|
||||
ZOp op;
|
||||
|
||||
switch ( n2tag ) {
|
||||
case TYPE_VECTOR:
|
||||
op = OP_INDEX_VEC_SLICE_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n2t);
|
||||
break;
|
||||
switch ( n2tag )
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
op = OP_INDEX_VEC_SLICE_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n2t);
|
||||
break;
|
||||
|
||||
case TYPE_TABLE:
|
||||
op = OP_TABLE_INDEX_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n1->GetType());
|
||||
break;
|
||||
case TYPE_TABLE:
|
||||
op = OP_TABLE_INDEX_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n1->GetType());
|
||||
break;
|
||||
|
||||
case TYPE_STRING:
|
||||
op = OP_INDEX_STRING_SLICE_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n1->GetType());
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
op = OP_INDEX_STRING_SLICE_VV;
|
||||
z = ZInstI(op, Frame1Slot(n1, op), n2_slot);
|
||||
z.SetType(n1->GetType());
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad aggregate type when compiling index");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad aggregate type when compiling index");
|
||||
}
|
||||
|
||||
z.aux = InternalBuildVals(l);
|
||||
z.CheckIfManaged(n1->GetType());
|
||||
|
@ -763,8 +735,7 @@ const ZAMStmt ZAMCompiler::AssignVecElems(const Expr* e)
|
|||
ASSERT(t1->Tag() == TYPE_VECTOR);
|
||||
ASSERT(t3->Tag() == TYPE_VECTOR);
|
||||
|
||||
auto z = GenInst(OP_VECTOR_SLICE_ASSIGN_VV,
|
||||
lhs, op3->AsNameExpr());
|
||||
auto z = GenInst(OP_VECTOR_SLICE_ASSIGN_VV, lhs, op3->AsNameExpr());
|
||||
|
||||
z.aux = InternalBuildVals(indexes_expr);
|
||||
|
||||
|
@ -784,11 +755,9 @@ const ZAMStmt ZAMCompiler::AssignVecElems(const Expr* e)
|
|||
auto c = op2->AsConstExpr();
|
||||
auto tmp = TempForConst(c);
|
||||
|
||||
auto zop = any_vec ? OP_ANY_VECTOR_ELEM_ASSIGN_VVC :
|
||||
OP_VECTOR_ELEM_ASSIGN_VVC;
|
||||
auto zop = any_vec ? OP_ANY_VECTOR_ELEM_ASSIGN_VVC : OP_VECTOR_ELEM_ASSIGN_VVC;
|
||||
|
||||
return AddInst(ZInstI(zop, Frame1Slot(lhs, zop), tmp,
|
||||
op3->AsConstExpr()));
|
||||
return AddInst(ZInstI(zop, Frame1Slot(lhs, zop), tmp, op3->AsConstExpr()));
|
||||
}
|
||||
|
||||
if ( op2->Tag() == EXPR_NAME )
|
||||
|
@ -892,7 +861,7 @@ const ZAMStmt ZAMCompiler::DoCall(const CallExpr* c, const NameExpr* n)
|
|||
bool indirect = ! func_id->IsGlobal() || ! func_id->GetVal();
|
||||
|
||||
if ( indirect )
|
||||
call_case = -1; // force default of CallN
|
||||
call_case = -1; // force default of CallN
|
||||
|
||||
auto nt = n ? n->GetType()->Tag() : TYPE_VOID;
|
||||
auto n_slot = n ? Frame1Slot(n, OP1_WRITE) : -1;
|
||||
|
@ -910,21 +879,17 @@ const ZAMStmt ZAMCompiler::DoCall(const CallExpr* c, const NameExpr* n)
|
|||
else if ( call_case == 1 )
|
||||
{
|
||||
auto arg0 = args[0];
|
||||
auto n0 = arg0->Tag() == EXPR_NAME ?
|
||||
arg0->AsNameExpr() : nullptr;
|
||||
auto c0 = arg0->Tag() == EXPR_CONST ?
|
||||
arg0->AsConstExpr() : nullptr;
|
||||
auto n0 = arg0->Tag() == EXPR_NAME ? arg0->AsNameExpr() : nullptr;
|
||||
auto c0 = arg0->Tag() == EXPR_CONST ? arg0->AsConstExpr() : nullptr;
|
||||
|
||||
if ( n )
|
||||
{
|
||||
if ( n0 )
|
||||
z = ZInstI(AssignmentFlavor(OP_CALL1_VV, nt),
|
||||
n_slot, FrameSlot(n0));
|
||||
z = ZInstI(AssignmentFlavor(OP_CALL1_VV, nt), n_slot, FrameSlot(n0));
|
||||
else
|
||||
{
|
||||
ASSERT(c0);
|
||||
z = ZInstI(AssignmentFlavor(OP_CALL1_VC, nt),
|
||||
n_slot, c0);
|
||||
z = ZInstI(AssignmentFlavor(OP_CALL1_VC, nt), n_slot, c0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -957,19 +922,28 @@ const ZAMStmt ZAMCompiler::DoCall(const CallExpr* c, const NameExpr* n)
|
|||
|
||||
ZOp op;
|
||||
|
||||
switch ( call_case ) {
|
||||
case 2: op = n ? OP_CALL2_V : OP_CALL2_X; break;
|
||||
case 3: op = n ? OP_CALL3_V : OP_CALL3_X; break;
|
||||
case 4: op = n ? OP_CALL4_V : OP_CALL4_X; break;
|
||||
case 5: op = n ? OP_CALL5_V : OP_CALL5_X; break;
|
||||
switch ( call_case )
|
||||
{
|
||||
case 2:
|
||||
op = n ? OP_CALL2_V : OP_CALL2_X;
|
||||
break;
|
||||
case 3:
|
||||
op = n ? OP_CALL3_V : OP_CALL3_X;
|
||||
break;
|
||||
case 4:
|
||||
op = n ? OP_CALL4_V : OP_CALL4_X;
|
||||
break;
|
||||
case 5:
|
||||
op = n ? OP_CALL5_V : OP_CALL5_X;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( indirect )
|
||||
op = n ? OP_INDCALLN_VV : OP_INDCALLN_V;
|
||||
else
|
||||
op = n ? OP_CALLN_V : OP_CALLN_X;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if ( indirect )
|
||||
op = n ? OP_INDCALLN_VV : OP_INDCALLN_V;
|
||||
else
|
||||
op = n ? OP_CALLN_V : OP_CALLN_X;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( n )
|
||||
{
|
||||
|
@ -1134,37 +1108,38 @@ const ZAMStmt ZAMCompiler::ArithCoerce(const NameExpr* n, const Expr* e)
|
|||
|
||||
ZOp a;
|
||||
|
||||
switch ( targ_it ) {
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
switch ( targ_it )
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_DI_VEC_VV : OP_COERCE_DI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_DU_VEC_VV : OP_COERCE_DU_VV;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_DI_VEC_VV : OP_COERCE_DI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_DU_VEC_VV : OP_COERCE_DU_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_INT:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_UNSIGNED )
|
||||
a = nt_is_vec ? OP_COERCE_IU_VEC_VV : OP_COERCE_IU_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_ID_VEC_VV : OP_COERCE_ID_VV;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_INT:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_UNSIGNED )
|
||||
a = nt_is_vec ? OP_COERCE_IU_VEC_VV : OP_COERCE_IU_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_ID_VEC_VV : OP_COERCE_ID_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_UI_VEC_VV : OP_COERCE_UI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_UD_VEC_VV : OP_COERCE_UD_VV;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_UI_VEC_VV : OP_COERCE_UI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_UD_VEC_VV : OP_COERCE_UD_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad target internal type in coercion");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad target internal type in coercion");
|
||||
}
|
||||
|
||||
return AddInst(GenInst(a, n, op->AsNameExpr()));
|
||||
}
|
||||
|
@ -1232,4 +1207,4 @@ const ZAMStmt ZAMCompiler::Is(const NameExpr* n, const Expr* e)
|
|||
return AddInst(z);
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,48 +10,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
// An instruction can have one of four basic classes.
|
||||
enum ZAM_InstClass {
|
||||
ZIC_REGULAR, // a non-complicated instruction
|
||||
ZIC_COND, // a conditional branch
|
||||
ZIC_VEC, // a vector operation
|
||||
ZIC_FIELD, // a record field assignment
|
||||
};
|
||||
enum ZAM_InstClass
|
||||
{
|
||||
ZIC_REGULAR, // a non-complicated instruction
|
||||
ZIC_COND, // a conditional branch
|
||||
ZIC_VEC, // a vector operation
|
||||
ZIC_FIELD, // a record field assignment
|
||||
};
|
||||
|
||||
// For a given instruction operand, its general type.
|
||||
enum ZAM_OperandType {
|
||||
ZAM_OT_CONSTANT, // uses the instruction's associated constant
|
||||
ZAM_OT_EVENT_HANDLER, // uses the associated event handler
|
||||
ZAM_OT_INT, // directly specified integer
|
||||
ZAM_OT_VAR, // frame slot associated with a variable
|
||||
enum ZAM_OperandType
|
||||
{
|
||||
ZAM_OT_CONSTANT, // uses the instruction's associated constant
|
||||
ZAM_OT_EVENT_HANDLER, // uses the associated event handler
|
||||
ZAM_OT_INT, // directly specified integer
|
||||
ZAM_OT_VAR, // frame slot associated with a variable
|
||||
|
||||
ZAM_OT_ASSIGN_FIELD, // record field offset to assign to
|
||||
ZAM_OT_RECORD_FIELD, // record field offset to access
|
||||
ZAM_OT_ASSIGN_FIELD, // record field offset to assign to
|
||||
ZAM_OT_RECORD_FIELD, // record field offset to access
|
||||
|
||||
// The following wind up the same in the ultimate instruction,
|
||||
// but they differ in the calling sequences used to generate
|
||||
// the instruction.
|
||||
ZAM_OT_AUX, // uses the instruction's "aux" field
|
||||
ZAM_OT_LIST, // a list, managed via the "aux" field
|
||||
ZAM_OT_AUX, // uses the instruction's "aux" field
|
||||
ZAM_OT_LIST, // a list, managed via the "aux" field
|
||||
|
||||
ZAM_OT_NONE, // instruction has no direct operands
|
||||
};
|
||||
ZAM_OT_NONE, // instruction has no direct operands
|
||||
};
|
||||
|
||||
// For instructions corresponding to evaluating expressions, the type
|
||||
// of a given operand. The generator uses these to transform the operand's
|
||||
// low-level ZVal into a higher-level type expected by the associated
|
||||
// evaluation code.
|
||||
enum ZAM_ExprType {
|
||||
enum ZAM_ExprType
|
||||
{
|
||||
ZAM_EXPR_TYPE_ADDR,
|
||||
ZAM_EXPR_TYPE_ANY,
|
||||
ZAM_EXPR_TYPE_DOUBLE,
|
||||
|
@ -77,7 +80,7 @@ enum ZAM_ExprType {
|
|||
// expression deals directly with the operand's ZVal, rather
|
||||
// than the generator providing a higher-level version.
|
||||
ZAM_EXPR_TYPE_NONE,
|
||||
};
|
||||
};
|
||||
|
||||
// We only use the following in the context where the vector's elements
|
||||
// are individual words from the same line. We don't use it in other
|
||||
|
@ -85,15 +88,17 @@ enum ZAM_ExprType {
|
|||
using Words = vector<string>;
|
||||
|
||||
// Used for error-reporting.
|
||||
struct InputLoc {
|
||||
struct InputLoc
|
||||
{
|
||||
const char* file_name;
|
||||
int line_num = 0;
|
||||
};
|
||||
};
|
||||
|
||||
// An EmitTarget is a generated file to which code will be emitted.
|
||||
// The different values are used to instruct the generator which target
|
||||
// is currently of interest.
|
||||
enum EmitTarget {
|
||||
enum EmitTarget
|
||||
{
|
||||
// Indicates that no generated file has yet been specified.
|
||||
None,
|
||||
|
||||
|
@ -169,12 +174,13 @@ enum EmitTarget {
|
|||
// output. For example, for OP_NEGATE_VV_I the corresponding
|
||||
// string is "negate-VV-I".
|
||||
OpName,
|
||||
};
|
||||
};
|
||||
|
||||
// A helper class for managing the (ordered) collection of ZAM_OperandType's
|
||||
// associated with an instruction in order to generate C++ calling sequences
|
||||
// (both parameters for declarations, and arguments for invocations).
|
||||
class ArgsManager {
|
||||
class ArgsManager
|
||||
{
|
||||
public:
|
||||
// Constructed by providing the various ZAM_OperandType's along
|
||||
// with the instruction's class.
|
||||
|
@ -183,15 +189,15 @@ public:
|
|||
// Returns a string defining the parameters for a declaration;
|
||||
// these have full C++ type information along with the parameter
|
||||
// name.
|
||||
string Decls() const { return full_decl; }
|
||||
string Decls() const { return full_decl; }
|
||||
|
||||
// Returns a string for passing the parameters in a function
|
||||
// call. This is a comma-separated list of the parameter names,
|
||||
// with no associated C++ types.
|
||||
string Params() const { return full_params; }
|
||||
string Params() const { return full_params; }
|
||||
|
||||
// Returns the name of the given parameter, indexed starting with 0.
|
||||
const string& NthParam(int n) const { return params[n]; }
|
||||
const string& NthParam(int n) const { return params[n]; }
|
||||
|
||||
private:
|
||||
// Makes sure that each parameter has a unique name. For any
|
||||
|
@ -201,20 +207,20 @@ private:
|
|||
|
||||
// Maps ZAM_OperandType's to their associated C++ type and
|
||||
// canonical parameter name.
|
||||
static std::unordered_map<ZAM_OperandType,
|
||||
std::pair<const char*, const char*>> ot_to_args;
|
||||
static std::unordered_map<ZAM_OperandType, std::pair<const char*, const char*>> ot_to_args;
|
||||
|
||||
// For a single argument/parameter, tracks its declaration name,
|
||||
// C++ type, and the name to use when providing it as a parameter.
|
||||
// These last two names are potentially distinct when we're
|
||||
// assigning to record field (which is tracked by the is_field
|
||||
// member variable), hence the need to track both.
|
||||
struct Arg {
|
||||
struct Arg
|
||||
{
|
||||
string decl_name;
|
||||
string decl_type;
|
||||
string param_name;
|
||||
bool is_field;
|
||||
};
|
||||
};
|
||||
|
||||
// All of the argument/parameters associated with the collection
|
||||
// of ZAM_OperandType's.
|
||||
|
@ -226,7 +232,7 @@ private:
|
|||
// See Decls() and Params() above.
|
||||
string full_decl;
|
||||
string full_params;
|
||||
};
|
||||
};
|
||||
|
||||
// There are two mutually interacting classes: ZAMGen is the overall
|
||||
// driver for the ZAM generator, while ZAM_OpTemplate represents a
|
||||
|
@ -234,12 +240,13 @@ private:
|
|||
// operations.
|
||||
class ZAMGen;
|
||||
|
||||
class ZAM_OpTemplate {
|
||||
class ZAM_OpTemplate
|
||||
{
|
||||
public:
|
||||
// Instantiated by passing in the ZAMGen driver and the generic
|
||||
// name for the operation.
|
||||
ZAM_OpTemplate(ZAMGen* _g, string _base_name);
|
||||
virtual ~ZAM_OpTemplate() { }
|
||||
virtual ~ZAM_OpTemplate() { }
|
||||
|
||||
// Constructs the template's data structures by parsing its
|
||||
// description (beyond the initial description of the type of
|
||||
|
@ -251,70 +258,64 @@ public:
|
|||
virtual void Instantiate();
|
||||
|
||||
// Returns the generic name for the operation.
|
||||
const string& BaseName() const { return base_name; }
|
||||
const string& BaseName() const { return base_name; }
|
||||
|
||||
// Returns the canonical name for the operation. This is a
|
||||
// version of the name that, for expression-based operations,
|
||||
// can be concatenated with "EXPR_" to get the name of the
|
||||
// corresponding AST node.
|
||||
const string& CanonicalName() const { return cname; }
|
||||
const string& CanonicalName() const { return cname; }
|
||||
|
||||
// Returns a string version of the ZAMOp1Flavor associated
|
||||
// with this operation.
|
||||
const string& GetOp1Flavor() const { return op1_flavor; }
|
||||
const string& GetOp1Flavor() const { return op1_flavor; }
|
||||
|
||||
// True if this is an operation with side effects (see OpSideEffects
|
||||
// above).
|
||||
bool HasSideEffects() const { return has_side_effects; }
|
||||
bool HasSideEffects() const { return has_side_effects; }
|
||||
|
||||
protected:
|
||||
// Append to the list of operand types associated with this operation.
|
||||
void AddOpType(ZAM_OperandType ot)
|
||||
{ op_types.push_back(ot); }
|
||||
void AddOpType(ZAM_OperandType ot) { op_types.push_back(ot); }
|
||||
// Retrieve the list of operand types associated with this operation.
|
||||
const vector<ZAM_OperandType>& OperandTypes() const
|
||||
{ return op_types; }
|
||||
const vector<ZAM_OperandType>& OperandTypes() const { return op_types; }
|
||||
|
||||
// Specify the ZAMOp1Flavor associated with this operation. See
|
||||
// GetOp1Flavor() above for the corresponding accessor.
|
||||
void SetOp1Flavor(string fl) { op1_flavor = fl; }
|
||||
void SetOp1Flavor(string fl) { op1_flavor = fl; }
|
||||
|
||||
// Specify/fetch the parameter (operand) from which to take the
|
||||
// primary type of this operation.
|
||||
void SetTypeParam(int param) { type_param = param; }
|
||||
int GetTypeParam() const { return type_param; }
|
||||
void SetTypeParam(int param) { type_param = param; }
|
||||
int GetTypeParam() const { return type_param; }
|
||||
|
||||
// Specify/fetch the parameter (operand) from which to take the
|
||||
// secondary type of this operation.
|
||||
void SetType2Param(int param) { type2_param = param; }
|
||||
int GetType2Param() const { return type2_param; }
|
||||
void SetType2Param(int param) { type2_param = param; }
|
||||
int GetType2Param() const { return type2_param; }
|
||||
|
||||
// Tracking of assignment values (C++ variables that hold the
|
||||
// value that should be assigned to usual frame slot).
|
||||
void SetAssignVal(string _av) { av = _av; }
|
||||
bool HasAssignVal() const { return ! av.empty(); }
|
||||
const string& GetAssignVal() const { return av; }
|
||||
void SetAssignVal(string _av) { av = _av; }
|
||||
bool HasAssignVal() const { return ! av.empty(); }
|
||||
const string& GetAssignVal() const { return av; }
|
||||
|
||||
// Management of C++ evaluation blocks. These are built up
|
||||
// line-by-line.
|
||||
void AddEval(string line) { eval += line; }
|
||||
bool HasEval() const { return ! eval.empty(); }
|
||||
const string& GetEval() const { return eval; }
|
||||
void AddEval(string line) { eval += line; }
|
||||
bool HasEval() const { return ! eval.empty(); }
|
||||
const string& GetEval() const { return eval; }
|
||||
|
||||
// Management of custom methods to be used rather than generating
|
||||
// a method.
|
||||
void SetCustomMethod(string cm) { custom_method = SkipWS(cm); }
|
||||
bool HasCustomMethod() const
|
||||
{ return ! custom_method.empty(); }
|
||||
const string& GetCustomMethod() const
|
||||
{ return custom_method; }
|
||||
void SetCustomMethod(string cm) { custom_method = SkipWS(cm); }
|
||||
bool HasCustomMethod() const { return ! custom_method.empty(); }
|
||||
const string& GetCustomMethod() const { return custom_method; }
|
||||
|
||||
// Management of code to execute at the end of a generated method.
|
||||
void SetPostMethod(string cm) { post_method = SkipWS(cm); }
|
||||
bool HasPostMethod() const
|
||||
{ return ! post_method.empty(); }
|
||||
const string& GetPostMethod() const
|
||||
{ return post_method; }
|
||||
void SetPostMethod(string cm) { post_method = SkipWS(cm); }
|
||||
bool HasPostMethod() const { return ! post_method.empty(); }
|
||||
const string& GetPostMethod() const { return post_method; }
|
||||
|
||||
// Predicates indicating whether a subclass supports a given
|
||||
// property. These are whether the operation: (1) should include
|
||||
|
@ -323,45 +324,42 @@ protected:
|
|||
// not have a corresponding AST node, (4) is a direct assignment
|
||||
// (not an assignment to an expression), (5) is a direct assignment
|
||||
// to a record field.
|
||||
virtual bool IncludesFieldOp() const { return false; }
|
||||
virtual bool IsConditionalOp() const { return false; }
|
||||
virtual bool IsInternalOp() const { return false; }
|
||||
virtual bool IsAssignOp() const { return false; }
|
||||
virtual bool IsFieldOp() const { return false; }
|
||||
virtual bool IncludesFieldOp() const { return false; }
|
||||
virtual bool IsConditionalOp() const { return false; }
|
||||
virtual bool IsInternalOp() const { return false; }
|
||||
virtual bool IsAssignOp() const { return false; }
|
||||
virtual bool IsFieldOp() const { return false; }
|
||||
|
||||
// Whether this operation does not have any C++ evaluation associated
|
||||
// with it. Used for custom methods that compile into internal
|
||||
// ZAM operations.
|
||||
bool NoEval() const { return no_eval; }
|
||||
void SetNoEval() { no_eval = true; }
|
||||
bool NoEval() const { return no_eval; }
|
||||
void SetNoEval() { no_eval = true; }
|
||||
|
||||
// Whether this operation does not have a version where one of
|
||||
// its operands is a constant.
|
||||
bool NoConst() const { return no_const; }
|
||||
void SetNoConst() { no_const = true; }
|
||||
bool NoConst() const { return no_const; }
|
||||
void SetNoConst() { no_const = true; }
|
||||
|
||||
// Whether this operation also has a vectorized form.
|
||||
bool IncludesVectorOp() const { return includes_vector_op; }
|
||||
void SetIncludesVectorOp() { includes_vector_op = true; }
|
||||
bool IncludesVectorOp() const { return includes_vector_op; }
|
||||
void SetIncludesVectorOp() { includes_vector_op = true; }
|
||||
|
||||
// Whether this operation has side effects, and thus should
|
||||
// not be elided even if its result is used in a dead assignment.
|
||||
void SetHasSideEffects() { has_side_effects = true; }
|
||||
void SetHasSideEffects() { has_side_effects = true; }
|
||||
|
||||
// An "assignment-less" operation is one that, if its result
|
||||
// is used in a dead assignment, should be converted to a different
|
||||
// operation that explictly omits any assignment.
|
||||
bool HasAssignmentLess() const
|
||||
{ return ! assignment_less_op.empty(); }
|
||||
bool HasAssignmentLess() const { return ! assignment_less_op.empty(); }
|
||||
void SetAssignmentLess(string op, string op_type)
|
||||
{
|
||||
assignment_less_op = op;
|
||||
assignment_less_op_type = op_type;
|
||||
}
|
||||
const string& AssignmentLessOp() const
|
||||
{ return assignment_less_op; }
|
||||
const string& AssignmentLessOpType() const
|
||||
{ return assignment_less_op_type; }
|
||||
const string& AssignmentLessOp() const { return assignment_less_op; }
|
||||
const string& AssignmentLessOpType() const { return assignment_less_op_type; }
|
||||
|
||||
// Builds the instructions associated with this operation, assuming
|
||||
// a single operand.
|
||||
|
@ -373,8 +371,7 @@ protected:
|
|||
// for parsing when that's necessary, and for error reporting.
|
||||
// "words" is "line" split into a vector of whitespace-delimited
|
||||
// words.
|
||||
virtual void Parse(const string& attr, const string& line,
|
||||
const Words& words);
|
||||
virtual void Parse(const string& attr, const string& line, const Words& words);
|
||||
|
||||
// Scans in a C++ evaluation block, which continues until encountering
|
||||
// a line that does not start with whitespace, or that's empty.
|
||||
|
@ -391,8 +388,7 @@ protected:
|
|||
|
||||
// Generates one specific flavor ("zc") of the given operation,
|
||||
// using a method named 'm', the given operand types, and the class.
|
||||
void InstantiateOp(const string& m, const vector<ZAM_OperandType>& ot,
|
||||
ZAM_InstClass zc);
|
||||
void InstantiateOp(const string& m, const vector<ZAM_OperandType>& ot, ZAM_InstClass zc);
|
||||
|
||||
// Generates the "assignment-less" version of the given op-code.
|
||||
void GenAssignmentlessVersion(string op);
|
||||
|
@ -401,56 +397,49 @@ protected:
|
|||
// a (potentially empty) string differentiating the method from
|
||||
// others for that operation, and "ot" and "zc" are the same
|
||||
// as above.
|
||||
void InstantiateMethod(const string& m, const string& suffix,
|
||||
const vector<ZAM_OperandType>& ot,
|
||||
void InstantiateMethod(const string& m, const string& suffix, const vector<ZAM_OperandType>& ot,
|
||||
ZAM_InstClass zc);
|
||||
|
||||
// Generates the main logic of an operation's method, given the
|
||||
// specific operand types, an associated suffix for differentiating
|
||||
// ZAM instructions, and the instruction class.
|
||||
void InstantiateMethodCore(const vector<ZAM_OperandType>& ot,
|
||||
string suffix, ZAM_InstClass zc);
|
||||
void InstantiateMethodCore(const vector<ZAM_OperandType>& ot, string suffix, ZAM_InstClass zc);
|
||||
|
||||
// Generates the specific code to create a ZInst for the given
|
||||
// operation, operands, parameters to "GenInst", and suffix and
|
||||
// class per the above.
|
||||
virtual void BuildInstruction(const vector<ZAM_OperandType>& ot,
|
||||
const string& params,
|
||||
virtual void BuildInstruction(const vector<ZAM_OperandType>& ot, const string& params,
|
||||
const string& suffix, ZAM_InstClass zc);
|
||||
|
||||
// Top-level driver for generating the C++ evaluation code for
|
||||
// a given flavor of operation.
|
||||
virtual void InstantiateEval(const vector<ZAM_OperandType>& ot,
|
||||
const string& suffix, ZAM_InstClass zc);
|
||||
virtual void InstantiateEval(const vector<ZAM_OperandType>& ot, const string& suffix,
|
||||
ZAM_InstClass zc);
|
||||
|
||||
// Generates the C++ case statement for evaluating the given flavor
|
||||
// of operation.
|
||||
void InstantiateEval(EmitTarget et, const string& op_suffix,
|
||||
const string& eval, ZAM_InstClass zc);
|
||||
void InstantiateEval(EmitTarget et, const string& op_suffix, const string& eval,
|
||||
ZAM_InstClass zc);
|
||||
|
||||
// Generates a set of assignment C++ evaluations, one per each
|
||||
// possible Zeek scripting type of operand.
|
||||
void InstantiateAssignOp(const vector<ZAM_OperandType>& ot,
|
||||
const string& suffix);
|
||||
void InstantiateAssignOp(const vector<ZAM_OperandType>& ot, const string& suffix);
|
||||
|
||||
// Generates a C++ evaluation for an assignment of the type
|
||||
// corresponding to "accessor". If "is_managed" is true then
|
||||
// generates the associated memory management, too.
|
||||
void GenAssignOpCore(const vector<ZAM_OperandType>& ot,
|
||||
const string& eval, const string& accessor,
|
||||
bool is_managed);
|
||||
void GenAssignOpCore(const vector<ZAM_OperandType>& ot, const string& eval,
|
||||
const string& accessor, bool is_managed);
|
||||
|
||||
// The same, but for when there's an explicit assignment value.
|
||||
void GenAssignOpValCore(const string& eval, const string& accessor,
|
||||
bool is_managed);
|
||||
void GenAssignOpValCore(const string& eval, const string& accessor, bool is_managed);
|
||||
|
||||
// Returns the name of the method associated with the particular
|
||||
// list of operand types.
|
||||
string MethodName(const vector<ZAM_OperandType>& ot) const;
|
||||
|
||||
// Returns the parameter declarations to use in declaring a method.
|
||||
string MethodDeclare(const vector<ZAM_OperandType>& ot,
|
||||
ZAM_InstClass zc);
|
||||
string MethodDeclare(const vector<ZAM_OperandType>& ot, ZAM_InstClass zc);
|
||||
|
||||
// Returns a suffix that differentiates an operation name for
|
||||
// a specific list of operand types.
|
||||
|
@ -461,7 +450,7 @@ protected:
|
|||
string SkipWS(const string& s) const;
|
||||
|
||||
// Set the target to use for subsequent code emission.
|
||||
void EmitTo(EmitTarget et) { curr_et = et; }
|
||||
void EmitTo(EmitTarget et) { curr_et = et; }
|
||||
|
||||
// Emit the given string to the currently selected EmitTarget.
|
||||
void Emit(const string& s);
|
||||
|
@ -479,15 +468,22 @@ protected:
|
|||
|
||||
// Emit a newline. Implementation doesn't actually include a
|
||||
// newline since that's implicit in a call to Emit().
|
||||
void NL() { Emit(""); }
|
||||
void NL() { Emit(""); }
|
||||
|
||||
// Increase/decrease the indentation level, with the last two
|
||||
// being used for brace-delimited code blocks.
|
||||
void IndentUp();
|
||||
void IndentDown();
|
||||
void BeginBlock() { IndentUp(); Emit("{"); }
|
||||
void EndBlock() { Emit("}"); IndentDown(); }
|
||||
|
||||
void BeginBlock()
|
||||
{
|
||||
IndentUp();
|
||||
Emit("{");
|
||||
}
|
||||
void EndBlock()
|
||||
{
|
||||
Emit("}");
|
||||
IndentDown();
|
||||
}
|
||||
|
||||
// Maps an operand type to a character mnemonic used to distinguish
|
||||
// it from others.
|
||||
|
@ -517,7 +513,7 @@ protected:
|
|||
|
||||
// Tracks the result of ExtractTypeParam() used for "type" and
|
||||
// "type2" attributes.
|
||||
int type_param = 0; // 0 = not set
|
||||
int type_param = 0; // 0 = not set
|
||||
int type2_param = 0;
|
||||
|
||||
// If non-empty, the value to assign to the target in an assignment
|
||||
|
@ -553,24 +549,27 @@ protected:
|
|||
// and the operand type (like "OP_V") of that associated operation.
|
||||
string assignment_less_op;
|
||||
string assignment_less_op_type;
|
||||
};
|
||||
};
|
||||
|
||||
// A subclass used for "unary-op" templates.
|
||||
class ZAM_UnaryOpTemplate : public ZAM_OpTemplate {
|
||||
class ZAM_UnaryOpTemplate : public ZAM_OpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_UnaryOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_OpTemplate(_g, _base_name) { }
|
||||
ZAM_UnaryOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { }
|
||||
|
||||
protected:
|
||||
void Instantiate() override;
|
||||
};
|
||||
};
|
||||
|
||||
// A subclass for unary operations that are directly instantiated using
|
||||
// custom methods.
|
||||
class ZAM_DirectUnaryOpTemplate : public ZAM_OpTemplate {
|
||||
class ZAM_DirectUnaryOpTemplate : public ZAM_OpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_DirectUnaryOpTemplate(ZAMGen* _g, string _base_name, string _direct)
|
||||
: ZAM_OpTemplate(_g, _base_name), direct(_direct) { }
|
||||
: ZAM_OpTemplate(_g, _base_name), direct(_direct)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void Instantiate() override;
|
||||
|
@ -578,12 +577,13 @@ protected:
|
|||
private:
|
||||
// The ZAMCompiler method to call to compile the operation.
|
||||
string direct;
|
||||
};
|
||||
};
|
||||
|
||||
// A helper class for the ZAM_ExprOpTemplate class (which follows).
|
||||
// This class tracks a single instance of creating an evaluation for
|
||||
// an AST expression.
|
||||
class EvalInstance {
|
||||
class EvalInstance
|
||||
{
|
||||
public:
|
||||
// Initialized using the types of the LHS (result) and the
|
||||
// first and second operand. Often all three types are the
|
||||
|
@ -592,8 +592,8 @@ public:
|
|||
// "is_def" is true if this instance is for the default catch-all
|
||||
// where the operand types don't match any of the explicitly
|
||||
// specified evaluations;
|
||||
EvalInstance(ZAM_ExprType lhs_et, ZAM_ExprType op1_et,
|
||||
ZAM_ExprType op2_et, string eval, bool is_def);
|
||||
EvalInstance(ZAM_ExprType lhs_et, ZAM_ExprType op1_et, ZAM_ExprType op2_et, string eval,
|
||||
bool is_def);
|
||||
|
||||
// Returns the accessor to use for assigning to the LHS. "is_ptr"
|
||||
// indicates whether the value to which we're applying the
|
||||
|
@ -601,10 +601,8 @@ public:
|
|||
string LHSAccessor(bool is_ptr = false) const;
|
||||
|
||||
// Same but for access to the first or second operand.
|
||||
string Op1Accessor(bool is_ptr = false) const
|
||||
{ return Accessor(op1_et, is_ptr); }
|
||||
string Op2Accessor(bool is_ptr = false) const
|
||||
{ return Accessor(op2_et, is_ptr); }
|
||||
string Op1Accessor(bool is_ptr = false) const { return Accessor(op1_et, is_ptr); }
|
||||
string Op2Accessor(bool is_ptr = false) const { return Accessor(op2_et, is_ptr); }
|
||||
|
||||
// Provides an accessor for an operand of the given type.
|
||||
string Accessor(ZAM_ExprType et, bool is_ptr = false) const;
|
||||
|
@ -613,9 +611,9 @@ public:
|
|||
// flavor of expression-evaluation instruction.
|
||||
string OpMarker() const;
|
||||
|
||||
const string& Eval() const { return eval; }
|
||||
ZAM_ExprType LHS_ET() const { return lhs_et; }
|
||||
bool IsDefault() const { return is_def; }
|
||||
const string& Eval() const { return eval; }
|
||||
ZAM_ExprType LHS_ET() const { return lhs_et; }
|
||||
bool IsDefault() const { return is_def; }
|
||||
|
||||
private:
|
||||
ZAM_ExprType lhs_et;
|
||||
|
@ -623,37 +621,37 @@ private:
|
|||
ZAM_ExprType op2_et;
|
||||
string eval;
|
||||
bool is_def;
|
||||
};
|
||||
};
|
||||
|
||||
// A subclass for AST "Expr" nodes in reduced form.
|
||||
class ZAM_ExprOpTemplate : public ZAM_OpTemplate {
|
||||
class ZAM_ExprOpTemplate : public ZAM_OpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_ExprOpTemplate(ZAMGen* _g, string _base_name);
|
||||
|
||||
// The number of operands the operation takes (not including its
|
||||
// assignment target). A value of 0 is used for expressions that
|
||||
// require special handling.
|
||||
virtual int Arity() const { return 0; }
|
||||
virtual int Arity() const { return 0; }
|
||||
|
||||
int HasExplicitResultType() const { return explicit_res_type; }
|
||||
void SetHasExplicitResultType() { explicit_res_type = true; }
|
||||
int HasExplicitResultType() const { return explicit_res_type; }
|
||||
void SetHasExplicitResultType() { explicit_res_type = true; }
|
||||
|
||||
void AddExprType(ZAM_ExprType et)
|
||||
{ expr_types.insert(et); }
|
||||
const std::unordered_set<ZAM_ExprType>& ExprTypes() const
|
||||
{ return expr_types; }
|
||||
void AddExprType(ZAM_ExprType et) { expr_types.insert(et); }
|
||||
const std::unordered_set<ZAM_ExprType>& ExprTypes() const { return expr_types; }
|
||||
|
||||
void AddEvalSet(ZAM_ExprType et, string ev)
|
||||
{ eval_set[et] += ev; }
|
||||
void AddEvalSet(ZAM_ExprType et, string ev) { eval_set[et] += ev; }
|
||||
void AddEvalSet(ZAM_ExprType et1, ZAM_ExprType et2, string ev)
|
||||
{ eval_mixed_set[et1][et2] += ev; }
|
||||
{
|
||||
eval_mixed_set[et1][et2] += ev;
|
||||
}
|
||||
|
||||
bool IncludesFieldOp() const override { return includes_field_op; }
|
||||
void SetIncludesFieldOp() { includes_field_op = true; }
|
||||
bool IncludesFieldOp() const override { return includes_field_op; }
|
||||
void SetIncludesFieldOp() { includes_field_op = true; }
|
||||
|
||||
bool HasPreEval() const { return ! pre_eval.empty(); }
|
||||
void SetPreEval(string pe) { pre_eval = SkipWS(pe); }
|
||||
const string& GetPreEval() const { return pre_eval; }
|
||||
bool HasPreEval() const { return ! pre_eval.empty(); }
|
||||
void SetPreEval(string pe) { pre_eval = SkipWS(pe); }
|
||||
const string& GetPreEval() const { return pre_eval; }
|
||||
|
||||
protected:
|
||||
// Returns a regular expression used to access the value of the
|
||||
|
@ -670,8 +668,7 @@ protected:
|
|||
|
||||
// Instantiates versions of the operation that have a constant
|
||||
// as the first, second, or third operand ...
|
||||
void InstantiateC1(const vector<ZAM_OperandType>& ots, int arity,
|
||||
bool do_vec = false);
|
||||
void InstantiateC1(const vector<ZAM_OperandType>& ots, int arity, bool do_vec = false);
|
||||
void InstantiateC2(const vector<ZAM_OperandType>& ots, int arity);
|
||||
void InstantiateC3(const vector<ZAM_OperandType>& ots);
|
||||
|
||||
|
@ -685,17 +682,15 @@ protected:
|
|||
|
||||
// Iterates over the different Zeek types specified for an expression's
|
||||
// operands and generates instructions for each.
|
||||
void BuildInstructionCore(const string& params, const string& suffix,
|
||||
ZAM_InstClass zc);
|
||||
void BuildInstructionCore(const string& params, const string& suffix, ZAM_InstClass zc);
|
||||
|
||||
// Generates an if-else cascade element that matches one of the
|
||||
// specific Zeek types associated with the instruction.
|
||||
void GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2,
|
||||
const string& params, const string& suffix,
|
||||
bool do_else, ZAM_InstClass zc);
|
||||
void GenMethodTest(ZAM_ExprType et1, ZAM_ExprType et2, const string& params,
|
||||
const string& suffix, bool do_else, ZAM_InstClass zc);
|
||||
|
||||
void InstantiateEval(const vector<ZAM_OperandType>& ot,
|
||||
const string& suffix, ZAM_InstClass zc) override;
|
||||
void InstantiateEval(const vector<ZAM_OperandType>& ot, const string& suffix,
|
||||
ZAM_InstClass zc) override;
|
||||
|
||||
private:
|
||||
// The Zeek types that can appear as operands for the expression.
|
||||
|
@ -706,9 +701,7 @@ private:
|
|||
|
||||
// Some expressions take two operands of different types. This
|
||||
// holds their C++ evaluation template.
|
||||
std::unordered_map<ZAM_ExprType,
|
||||
std::unordered_map<ZAM_ExprType, string>>
|
||||
eval_mixed_set;
|
||||
std::unordered_map<ZAM_ExprType, std::unordered_map<ZAM_ExprType, string>> eval_mixed_set;
|
||||
|
||||
// Whether this expression's operand is a field access (and thus
|
||||
// needs both the record as an operand and an additional constant
|
||||
|
@ -721,38 +714,37 @@ private:
|
|||
// If true, then the evaluations will take care of ensuring
|
||||
// proper result types when assigning to $$.
|
||||
bool explicit_res_type = false;
|
||||
};
|
||||
};
|
||||
|
||||
// A version of ZAM_ExprOpTemplate for unary expressions.
|
||||
class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate {
|
||||
class ZAM_UnaryExprOpTemplate : public ZAM_ExprOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_ExprOpTemplate(_g, _base_name) { }
|
||||
ZAM_UnaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { }
|
||||
|
||||
bool IncludesFieldOp() const override
|
||||
{ return ExprTypes().count(ZAM_EXPR_TYPE_NONE) == 0; }
|
||||
bool IncludesFieldOp() const override { return ExprTypes().count(ZAM_EXPR_TYPE_NONE) == 0; }
|
||||
|
||||
int Arity() const override { return 1; }
|
||||
int Arity() const override { return 1; }
|
||||
|
||||
protected:
|
||||
void Parse(const string& attr, const string& line, const Words& words) override;
|
||||
void Instantiate() override;
|
||||
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot,
|
||||
const string& params, const string& suffix,
|
||||
ZAM_InstClass zc) override;
|
||||
};
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot, const string& params,
|
||||
const string& suffix, ZAM_InstClass zc) override;
|
||||
};
|
||||
|
||||
// A version of ZAM_UnaryExprOpTemplate where the point of the expression
|
||||
// is to capture a direct assignment operation.
|
||||
class ZAM_AssignOpTemplate : public ZAM_UnaryExprOpTemplate {
|
||||
class ZAM_AssignOpTemplate : public ZAM_UnaryExprOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_AssignOpTemplate(ZAMGen* _g, string _base_name);
|
||||
|
||||
bool IsAssignOp() const override { return true; }
|
||||
bool IncludesFieldOp() const override { return false; }
|
||||
bool IsFieldOp() const override { return field_op; }
|
||||
void SetFieldOp() { field_op = true; }
|
||||
bool IsAssignOp() const override { return true; }
|
||||
bool IncludesFieldOp() const override { return false; }
|
||||
bool IsFieldOp() const override { return field_op; }
|
||||
void SetFieldOp() { field_op = true; }
|
||||
|
||||
protected:
|
||||
void Parse(const string& attr, const string& line, const Words& words) override;
|
||||
|
@ -760,34 +752,36 @@ protected:
|
|||
|
||||
private:
|
||||
bool field_op = false;
|
||||
};
|
||||
};
|
||||
|
||||
// A version of ZAM_ExprOpTemplate for binary expressions.
|
||||
class ZAM_BinaryExprOpTemplate : public ZAM_ExprOpTemplate {
|
||||
class ZAM_BinaryExprOpTemplate : public ZAM_ExprOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_BinaryExprOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_ExprOpTemplate(_g, _base_name) { }
|
||||
ZAM_BinaryExprOpTemplate(ZAMGen* _g, string _base_name) : ZAM_ExprOpTemplate(_g, _base_name) { }
|
||||
|
||||
bool IncludesFieldOp() const override { return true; }
|
||||
bool IncludesFieldOp() const override { return true; }
|
||||
|
||||
int Arity() const override { return 2; }
|
||||
int Arity() const override { return 2; }
|
||||
|
||||
protected:
|
||||
void Instantiate() override;
|
||||
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot,
|
||||
const string& params, const string& suffix,
|
||||
ZAM_InstClass zc) override;
|
||||
};
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot, const string& params,
|
||||
const string& suffix, ZAM_InstClass zc) override;
|
||||
};
|
||||
|
||||
// A version of ZAM_BinaryExprOpTemplate for relationals.
|
||||
class ZAM_RelationalExprOpTemplate : public ZAM_BinaryExprOpTemplate {
|
||||
class ZAM_RelationalExprOpTemplate : public ZAM_BinaryExprOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_RelationalExprOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_BinaryExprOpTemplate(_g, _base_name) { }
|
||||
: ZAM_BinaryExprOpTemplate(_g, _base_name)
|
||||
{
|
||||
}
|
||||
|
||||
bool IncludesFieldOp() const override { return false; }
|
||||
bool IsConditionalOp() const override { return true; }
|
||||
bool IncludesFieldOp() const override { return false; }
|
||||
bool IsConditionalOp() const override { return true; }
|
||||
|
||||
protected:
|
||||
const char* VecEvalRE(bool have_target) const override
|
||||
|
@ -800,49 +794,51 @@ protected:
|
|||
|
||||
void Instantiate() override;
|
||||
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot,
|
||||
const string& params, const string& suffix,
|
||||
ZAM_InstClass zc) override;
|
||||
};
|
||||
void BuildInstruction(const vector<ZAM_OperandType>& ot, const string& params,
|
||||
const string& suffix, ZAM_InstClass zc) override;
|
||||
};
|
||||
|
||||
// A version of ZAM_BinaryExprOpTemplate for binary operations generated
|
||||
// by custom methods rather than directly from the AST.
|
||||
class ZAM_InternalBinaryOpTemplate : public ZAM_BinaryExprOpTemplate {
|
||||
class ZAM_InternalBinaryOpTemplate : public ZAM_BinaryExprOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_InternalBinaryOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_BinaryExprOpTemplate(_g, _base_name) { }
|
||||
: ZAM_BinaryExprOpTemplate(_g, _base_name)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsInternalOp() const override { return true; }
|
||||
bool IsInternalOp() const override { return true; }
|
||||
|
||||
// The accessors used to get to the underlying Zeek script value
|
||||
// of the first and second operand.
|
||||
void SetOp1Accessor(string accessor) { op1_accessor = accessor; }
|
||||
void SetOp2Accessor(string accessor) { op2_accessor = accessor; }
|
||||
void SetOp1Accessor(string accessor) { op1_accessor = accessor; }
|
||||
void SetOp2Accessor(string accessor) { op2_accessor = accessor; }
|
||||
void SetOpAccessor(string accessor)
|
||||
{
|
||||
SetOp1Accessor(accessor);
|
||||
SetOp1Accessor(accessor);
|
||||
SetOp2Accessor(accessor);
|
||||
}
|
||||
|
||||
protected:
|
||||
void Parse(const string& attr, const string& line, const Words& words) override;
|
||||
|
||||
void InstantiateEval(const vector<ZAM_OperandType>& ot,
|
||||
const string& suffix, ZAM_InstClass zc) override;
|
||||
void InstantiateEval(const vector<ZAM_OperandType>& ot, const string& suffix,
|
||||
ZAM_InstClass zc) override;
|
||||
|
||||
private:
|
||||
string op1_accessor;
|
||||
string op2_accessor;
|
||||
};
|
||||
};
|
||||
|
||||
// A version of ZAM_OpTemplate for operations used internally (and not
|
||||
// corresponding to AST elements).
|
||||
class ZAM_InternalOpTemplate : public ZAM_OpTemplate {
|
||||
class ZAM_InternalOpTemplate : public ZAM_OpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_InternalOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_OpTemplate(_g, _base_name) { }
|
||||
ZAM_InternalOpTemplate(ZAMGen* _g, string _base_name) : ZAM_OpTemplate(_g, _base_name) { }
|
||||
|
||||
bool IsInternalOp() const override { return true; }
|
||||
bool IsInternalOp() const override { return true; }
|
||||
|
||||
protected:
|
||||
void Parse(const string& attr, const string& line, const Words& words) override;
|
||||
|
@ -851,31 +847,34 @@ private:
|
|||
// True if the internal operation corresponds to an indirect call,
|
||||
// i.e., one through a variable rather than one directly specified.
|
||||
bool is_indirect_call = false;
|
||||
};
|
||||
};
|
||||
|
||||
// An internal operation that assigns a result to a frame element.
|
||||
class ZAM_InternalAssignOpTemplate : public ZAM_InternalOpTemplate {
|
||||
class ZAM_InternalAssignOpTemplate : public ZAM_InternalOpTemplate
|
||||
{
|
||||
public:
|
||||
ZAM_InternalAssignOpTemplate(ZAMGen* _g, string _base_name)
|
||||
: ZAM_InternalOpTemplate(_g, _base_name) { }
|
||||
|
||||
bool IsAssignOp() const override { return true; }
|
||||
};
|
||||
: ZAM_InternalOpTemplate(_g, _base_name)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsAssignOp() const override { return true; }
|
||||
};
|
||||
|
||||
// Helper classes for managing input from the template file, including
|
||||
// low-level scanning.
|
||||
|
||||
class TemplateInput {
|
||||
class TemplateInput
|
||||
{
|
||||
public:
|
||||
// Program name and file name are for generating error messages.
|
||||
TemplateInput(FILE* _f, const char* _prog_name, const char* _file_name)
|
||||
: f(_f), prog_name(_prog_name)
|
||||
: f(_f), prog_name(_prog_name)
|
||||
{
|
||||
loc.file_name = _file_name;
|
||||
}
|
||||
|
||||
const InputLoc& CurrLoc() const { return loc; }
|
||||
const InputLoc& CurrLoc() const { return loc; }
|
||||
|
||||
// Fetch the next line of input, including trailing newline.
|
||||
// Returns true on success, false on EOF or error. Skips over
|
||||
|
@ -891,24 +890,24 @@ public:
|
|||
|
||||
// Puts back the given line so that the next call to ScanLine will
|
||||
// return it. Does not nest.
|
||||
void PutBack(const string& line) { put_back = line; }
|
||||
void PutBack(const string& line) { put_back = line; }
|
||||
|
||||
// Report an error and exit.
|
||||
[[noreturn]] void Gripe(const char* msg, const string& input) const;
|
||||
[[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const;
|
||||
|
||||
private:
|
||||
string put_back; // if non-empty, use this for the next ScanLine
|
||||
string put_back; // if non-empty, use this for the next ScanLine
|
||||
|
||||
FILE* f;
|
||||
const char* prog_name;
|
||||
InputLoc loc;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Driver class for the ZAM instruction generator.
|
||||
|
||||
class ZAMGen {
|
||||
class ZAMGen
|
||||
{
|
||||
public:
|
||||
ZAMGen(int argc, char** argv);
|
||||
|
||||
|
@ -928,25 +927,21 @@ public:
|
|||
|
||||
// These methods provide low-level parsing (and error-reporting)
|
||||
// access to ZAM_OpTemplate objects.
|
||||
const InputLoc& CurrLoc() const { return ti->CurrLoc(); }
|
||||
bool ScanLine(string& line) { return ti->ScanLine(line); }
|
||||
Words SplitIntoWords(const string& line) const
|
||||
{ return ti->SplitIntoWords(line); }
|
||||
string SkipWords(const string& line, int n) const
|
||||
{ return ti->SkipWords(line, n); }
|
||||
void PutBack(const string& line) { ti->PutBack(line); }
|
||||
const InputLoc& CurrLoc() const { return ti->CurrLoc(); }
|
||||
bool ScanLine(string& line) { return ti->ScanLine(line); }
|
||||
Words SplitIntoWords(const string& line) const { return ti->SplitIntoWords(line); }
|
||||
string SkipWords(const string& line, int n) const { return ti->SkipWords(line, n); }
|
||||
void PutBack(const string& line) { ti->PutBack(line); }
|
||||
|
||||
// Methods made public to ZAM_OpTemplate objects for emitting code.
|
||||
void Emit(EmitTarget et, const string& s);
|
||||
|
||||
void IndentUp() { ++indent_level; }
|
||||
void IndentDown() { --indent_level; }
|
||||
void SetNoNL(bool _no_NL) { no_NL = _no_NL; }
|
||||
void IndentUp() { ++indent_level; }
|
||||
void IndentDown() { --indent_level; }
|
||||
void SetNoNL(bool _no_NL) { no_NL = _no_NL; }
|
||||
|
||||
[[noreturn]] void Gripe(const char* msg, const string& input) const
|
||||
{ ti->Gripe(msg, input); }
|
||||
[[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const
|
||||
{ ti->Gripe(msg, loc); }
|
||||
[[noreturn]] void Gripe(const char* msg, const string& input) const { ti->Gripe(msg, input); }
|
||||
[[noreturn]] void Gripe(const char* msg, const InputLoc& loc) const { ti->Gripe(msg, loc); }
|
||||
|
||||
private:
|
||||
// Opens all of the code generation targets, and creates prologs
|
||||
|
@ -988,4 +983,4 @@ private:
|
|||
|
||||
// If true, refrain from appending a newline to any emitted lines.
|
||||
bool no_NL = false;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op)
|
||||
{
|
||||
|
@ -24,8 +24,7 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, int i)
|
|||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const ConstExpr* c, const NameExpr* v1,
|
||||
int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const ConstExpr* c, const NameExpr* v1, int i)
|
||||
{
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), i, c);
|
||||
z.op_type = OP_VVC_I2;
|
||||
|
@ -38,16 +37,15 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2)
|
|||
return ZInstI(op, Frame1Slot(v1, op), nv2);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
int nv3 = FrameSlot(v3);
|
||||
return ZInstI(op, Frame1Slot(v1, op), nv2, nv3);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, const NameExpr* v4)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3,
|
||||
const NameExpr* v4)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
int nv3 = FrameSlot(v3);
|
||||
|
@ -70,30 +68,28 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const ConstExpr* ce, const NameExpr* v1)
|
|||
return ZInstI(op, Frame1Slot(v1, op), ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* ce,
|
||||
const NameExpr* v2)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* ce, const NameExpr* v2)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
return ZInstI(op, Frame1Slot(v1, op), nv2, ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* ce)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
return ZInstI(op, Frame1Slot(v1, op), nv2, ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3,
|
||||
const ConstExpr* ce)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
return ZInstI(op, Frame1Slot(v1, op), nv2, ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, const ConstExpr* ce)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
int nv3 = FrameSlot(v3);
|
||||
return ZInstI(op, Frame1Slot(v1, op), nv2, nv3, ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const ConstExpr* ce, const NameExpr* v3)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* ce,
|
||||
const NameExpr* v3)
|
||||
{
|
||||
// Note that here we reverse the order of the arguments; saves
|
||||
// us from needing to implement a redundant constructor.
|
||||
|
@ -102,16 +98,14 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
|||
return ZInstI(op, Frame1Slot(v1, op), nv2, nv3, ce);
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c,
|
||||
int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c, int i)
|
||||
{
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), i, c);
|
||||
z.op_type = OP_VVC_I2;
|
||||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, int i)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), nv2, i);
|
||||
|
@ -119,8 +113,7 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
|||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
int i1, int i2)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, int i1, int i2)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), nv2, i1, i2);
|
||||
|
@ -128,16 +121,15 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
|||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v, const ConstExpr* c,
|
||||
int i1, int i2)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v, const ConstExpr* c, int i1, int i2)
|
||||
{
|
||||
auto z = ZInstI(op, Frame1Slot(v, op), i1, i2, c);
|
||||
z.op_type = OP_VVVC_I2_I3;
|
||||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3,
|
||||
int i)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
int nv3 = FrameSlot(v3);
|
||||
|
@ -146,8 +138,8 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
|||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const ConstExpr* c, int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* c,
|
||||
int i)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), nv2, i, c);
|
||||
|
@ -155,8 +147,8 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
|||
return z;
|
||||
}
|
||||
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c,
|
||||
const NameExpr* v2, int i)
|
||||
ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c, const NameExpr* v2,
|
||||
int i)
|
||||
{
|
||||
int nv2 = FrameSlot(v2);
|
||||
auto z = ZInstI(op, Frame1Slot(v1, op), nv2, i, c);
|
||||
|
@ -164,4 +156,4 @@ ZInstI ZAMCompiler::GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c,
|
|||
return z;
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -12,28 +12,22 @@ ZInstI GenInst(ZOp op, const NameExpr* v1);
|
|||
ZInstI GenInst(ZOp op, const NameExpr* v1, int i);
|
||||
ZInstI GenInst(ZOp op, const ConstExpr* c, const NameExpr* v1, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, const NameExpr* v4);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3,
|
||||
const NameExpr* v4);
|
||||
ZInstI GenInst(ZOp op, const ConstExpr* ce);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* ce);
|
||||
ZInstI GenInst(ZOp op, const ConstExpr* ce, const NameExpr* v1);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* ce,
|
||||
const NameExpr* v2);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* ce, const NameExpr* v2);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* ce);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3,
|
||||
const ConstExpr* ce);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, const ConstExpr* ce);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const ConstExpr* ce, const NameExpr* v3);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* ce,
|
||||
const NameExpr* v3);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, int i1, int i2);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v, const ConstExpr* c, int i1, int i2);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const NameExpr* v3, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2,
|
||||
const ConstExpr* c, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c,
|
||||
const NameExpr* v2, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const NameExpr* v3, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const NameExpr* v2, const ConstExpr* c, int i);
|
||||
ZInstI GenInst(ZOp op, const NameExpr* v1, const ConstExpr* c, const NameExpr* v2, int i);
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/script_opt/ZAM/ZInst.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
// Class for iterating over the elements of a table. Requires some care
|
||||
// because the dictionary iterators need to be destructed when done.
|
||||
|
||||
class TableIterInfo {
|
||||
class TableIterInfo
|
||||
{
|
||||
public:
|
||||
// No constructor needed, as all of our member variables are
|
||||
// instead instantiated via BeginLoop(). This allows us to
|
||||
|
@ -22,7 +24,7 @@ public:
|
|||
|
||||
// We do, however, want to make sure that when we go out of scope,
|
||||
// if we have any pending iterators we clear them.
|
||||
~TableIterInfo() { Clear(); }
|
||||
~TableIterInfo() { Clear(); }
|
||||
|
||||
// Start looping over the elements of the given table. "_aux"
|
||||
// provides information about the index variables, their types,
|
||||
|
@ -37,16 +39,10 @@ public:
|
|||
}
|
||||
|
||||
// True if we're done iterating, false if not.
|
||||
bool IsDoneIterating() const
|
||||
{
|
||||
return *tbl_iter == *tbl_end;
|
||||
}
|
||||
bool IsDoneIterating() const { return *tbl_iter == *tbl_end; }
|
||||
|
||||
// Indicates that the current iteration is finished.
|
||||
void IterFinished()
|
||||
{
|
||||
++*tbl_iter;
|
||||
}
|
||||
void IterFinished() { ++*tbl_iter; }
|
||||
|
||||
// Performs the next iteration (assuming IsDoneIterating() returned
|
||||
// false), assigning to the index variables.
|
||||
|
@ -74,7 +70,7 @@ public:
|
|||
}
|
||||
|
||||
// Called upon finishing the iteration.
|
||||
void EndIter() { Clear(); }
|
||||
void EndIter() { Clear(); }
|
||||
|
||||
// Called to explicitly clear any iteration state.
|
||||
void Clear()
|
||||
|
@ -94,12 +90,13 @@ private:
|
|||
|
||||
std::optional<DictIterator> tbl_iter;
|
||||
std::optional<DictIterator> tbl_end;
|
||||
};
|
||||
};
|
||||
|
||||
// Class for simple step-wise iteration across an integer range.
|
||||
// Suitable for iterating over vectors or strings.
|
||||
|
||||
class StepIterInfo {
|
||||
class StepIterInfo
|
||||
{
|
||||
public:
|
||||
// We do some cycle-squeezing by not having a constructor to
|
||||
// initialize our member variables, since we impose a discipline
|
||||
|
@ -123,24 +120,18 @@ public:
|
|||
}
|
||||
|
||||
// True if we're done iterating, false if not.
|
||||
bool IsDoneIterating() const
|
||||
{
|
||||
return iter >= n;
|
||||
}
|
||||
bool IsDoneIterating() const { return iter >= n; }
|
||||
|
||||
// Indicates that the current iteration is finished.
|
||||
void IterFinished()
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
void IterFinished() { ++iter; }
|
||||
|
||||
// Counter of where we are in the iteration.
|
||||
bro_uint_t iter; // initialized to 0 at start of loop
|
||||
bro_uint_t n; // we loop from 0 ... n-1
|
||||
bro_uint_t iter; // initialized to 0 at start of loop
|
||||
bro_uint_t n; // we loop from 0 ... n-1
|
||||
|
||||
// The low-level value we're iterating over.
|
||||
const std::vector<std::optional<ZVal>>* vv;
|
||||
const String* s;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
// Methods relating to low-level ZAM instruction manipulation.
|
||||
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
const ZAMStmt ZAMCompiler::StartingBlock()
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ ZInstAux* ZAMCompiler::InternalBuildVals(const ListExpr* l, int stride)
|
|||
|
||||
auto aux = new ZInstAux(n * stride);
|
||||
|
||||
int offset = 0; // offset into aux info
|
||||
int offset = 0; // offset into aux info
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
auto& e = exprs[i];
|
||||
|
@ -168,5 +168,4 @@ ZAMStmt ZAMCompiler::PrevStmt(const ZAMStmt s)
|
|||
return ZAMStmt(s.stmt_num - 1);
|
||||
}
|
||||
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -8,82 +8,84 @@
|
|||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompileStmt(const Stmt* s)
|
||||
{
|
||||
SetCurrStmt(s);
|
||||
|
||||
switch ( s->Tag() ) {
|
||||
case STMT_PRINT:
|
||||
return CompilePrint(static_cast<const PrintStmt*>(s));
|
||||
|
||||
case STMT_EXPR:
|
||||
return CompileExpr(static_cast<const ExprStmt*>(s));
|
||||
|
||||
case STMT_IF:
|
||||
return CompileIf(static_cast<const IfStmt*>(s));
|
||||
|
||||
case STMT_SWITCH:
|
||||
return CompileSwitch(static_cast<const SwitchStmt*>(s));
|
||||
|
||||
case STMT_ADD:
|
||||
return CompileAdd(static_cast<const AddStmt*>(s));
|
||||
|
||||
case STMT_DELETE:
|
||||
return CompileDel(static_cast<const DelStmt*>(s));
|
||||
|
||||
case STMT_EVENT:
|
||||
switch ( s->Tag() )
|
||||
{
|
||||
auto es = static_cast<const EventStmt*>(s);
|
||||
auto e = static_cast<const EventExpr*>(es->StmtExpr());
|
||||
return CompileExpr(e);
|
||||
case STMT_PRINT:
|
||||
return CompilePrint(static_cast<const PrintStmt*>(s));
|
||||
|
||||
case STMT_EXPR:
|
||||
return CompileExpr(static_cast<const ExprStmt*>(s));
|
||||
|
||||
case STMT_IF:
|
||||
return CompileIf(static_cast<const IfStmt*>(s));
|
||||
|
||||
case STMT_SWITCH:
|
||||
return CompileSwitch(static_cast<const SwitchStmt*>(s));
|
||||
|
||||
case STMT_ADD:
|
||||
return CompileAdd(static_cast<const AddStmt*>(s));
|
||||
|
||||
case STMT_DELETE:
|
||||
return CompileDel(static_cast<const DelStmt*>(s));
|
||||
|
||||
case STMT_EVENT:
|
||||
{
|
||||
auto es = static_cast<const EventStmt*>(s);
|
||||
auto e = static_cast<const EventExpr*>(es->StmtExpr());
|
||||
return CompileExpr(e);
|
||||
}
|
||||
|
||||
case STMT_WHILE:
|
||||
return CompileWhile(static_cast<const WhileStmt*>(s));
|
||||
|
||||
case STMT_FOR:
|
||||
return CompileFor(static_cast<const ForStmt*>(s));
|
||||
|
||||
case STMT_RETURN:
|
||||
return CompileReturn(static_cast<const ReturnStmt*>(s));
|
||||
|
||||
case STMT_CATCH_RETURN:
|
||||
return CompileCatchReturn(static_cast<const CatchReturnStmt*>(s));
|
||||
|
||||
case STMT_LIST:
|
||||
return CompileStmts(static_cast<const StmtList*>(s));
|
||||
|
||||
case STMT_INIT:
|
||||
return CompileInit(static_cast<const InitStmt*>(s));
|
||||
|
||||
case STMT_NULL:
|
||||
return EmptyStmt();
|
||||
|
||||
case STMT_WHEN:
|
||||
return CompileWhen(static_cast<const WhenStmt*>(s));
|
||||
|
||||
case STMT_CHECK_ANY_LEN:
|
||||
{
|
||||
auto cs = static_cast<const CheckAnyLenStmt*>(s);
|
||||
auto n = cs->StmtExpr()->AsNameExpr();
|
||||
auto expected_len = cs->ExpectedLen();
|
||||
return CheckAnyLenVi(n, expected_len);
|
||||
}
|
||||
|
||||
case STMT_NEXT:
|
||||
return CompileNext();
|
||||
|
||||
case STMT_BREAK:
|
||||
return CompileBreak();
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
return CompileFallThrough();
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad statement type in ZAMCompile::CompileStmt");
|
||||
}
|
||||
|
||||
case STMT_WHILE:
|
||||
return CompileWhile(static_cast<const WhileStmt*>(s));
|
||||
|
||||
case STMT_FOR:
|
||||
return CompileFor(static_cast<const ForStmt*>(s));
|
||||
|
||||
case STMT_RETURN:
|
||||
return CompileReturn(static_cast<const ReturnStmt*>(s));
|
||||
|
||||
case STMT_CATCH_RETURN:
|
||||
return CompileCatchReturn(static_cast<const CatchReturnStmt*>(s));
|
||||
|
||||
case STMT_LIST:
|
||||
return CompileStmts(static_cast<const StmtList*>(s));
|
||||
|
||||
case STMT_INIT:
|
||||
return CompileInit(static_cast<const InitStmt*>(s));
|
||||
|
||||
case STMT_NULL:
|
||||
return EmptyStmt();
|
||||
|
||||
case STMT_WHEN:
|
||||
return CompileWhen(static_cast<const WhenStmt*>(s));
|
||||
|
||||
case STMT_CHECK_ANY_LEN:
|
||||
{
|
||||
auto cs = static_cast<const CheckAnyLenStmt*>(s);
|
||||
auto n = cs->StmtExpr()->AsNameExpr();
|
||||
auto expected_len = cs->ExpectedLen();
|
||||
return CheckAnyLenVi(n, expected_len);
|
||||
}
|
||||
|
||||
case STMT_NEXT:
|
||||
return CompileNext();
|
||||
|
||||
case STMT_BREAK:
|
||||
return CompileBreak();
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
return CompileFallThrough();
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad statement type in ZAMCompile::CompileStmt");
|
||||
}
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::CompilePrint(const PrintStmt* ps)
|
||||
|
@ -159,8 +161,7 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
|||
{
|
||||
auto n = e->AsNameExpr();
|
||||
|
||||
ZOp op = (s1 && s2) ? OP_IF_ELSE_VV :
|
||||
(s1 ? OP_IF_VV : OP_IF_NOT_VV);
|
||||
ZOp op = (s1 && s2) ? OP_IF_ELSE_VV : (s1 ? OP_IF_VV : OP_IF_NOT_VV);
|
||||
|
||||
ZInstI cond(op, FrameSlot(n), 0);
|
||||
cond_stmt = AddInst(cond);
|
||||
|
@ -176,8 +177,7 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
|||
{
|
||||
auto branch_after_s1 = GoToStub();
|
||||
auto s2_end = CompileStmt(s2);
|
||||
SetV(cond_stmt, GoToTargetBeyond(branch_after_s1),
|
||||
branch_v);
|
||||
SetV(cond_stmt, GoToTargetBeyond(branch_after_s1), branch_v);
|
||||
SetGoTo(branch_after_s1, GoToTargetBeyond(s2_end));
|
||||
|
||||
return s2_end;
|
||||
|
@ -197,59 +197,60 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
|
|||
// we're switching to "if ( ! cond ) s2".
|
||||
auto z = insts1[cond_stmt.stmt_num];
|
||||
|
||||
switch ( z->op ) {
|
||||
case OP_IF_ELSE_VV:
|
||||
case OP_IF_VV:
|
||||
case OP_IF_NOT_VV:
|
||||
// These are generated correctly above, no need
|
||||
// to fix up.
|
||||
break;
|
||||
switch ( z->op )
|
||||
{
|
||||
case OP_IF_ELSE_VV:
|
||||
case OP_IF_VV:
|
||||
case OP_IF_NOT_VV:
|
||||
// These are generated correctly above, no need
|
||||
// to fix up.
|
||||
break;
|
||||
|
||||
case OP_HAS_FIELD_COND_VVV:
|
||||
z->op = OP_NOT_HAS_FIELD_COND_VVV;
|
||||
break;
|
||||
case OP_NOT_HAS_FIELD_COND_VVV:
|
||||
z->op = OP_HAS_FIELD_COND_VVV;
|
||||
break;
|
||||
case OP_HAS_FIELD_COND_VVV:
|
||||
z->op = OP_NOT_HAS_FIELD_COND_VVV;
|
||||
break;
|
||||
case OP_NOT_HAS_FIELD_COND_VVV:
|
||||
z->op = OP_HAS_FIELD_COND_VVV;
|
||||
break;
|
||||
|
||||
case OP_VAL_IS_IN_TABLE_COND_VVV:
|
||||
z->op = OP_VAL_IS_NOT_IN_TABLE_COND_VVV;
|
||||
break;
|
||||
case OP_VAL_IS_NOT_IN_TABLE_COND_VVV:
|
||||
z->op = OP_VAL_IS_IN_TABLE_COND_VVV;
|
||||
break;
|
||||
case OP_VAL_IS_IN_TABLE_COND_VVV:
|
||||
z->op = OP_VAL_IS_NOT_IN_TABLE_COND_VVV;
|
||||
break;
|
||||
case OP_VAL_IS_NOT_IN_TABLE_COND_VVV:
|
||||
z->op = OP_VAL_IS_IN_TABLE_COND_VVV;
|
||||
break;
|
||||
|
||||
case OP_CONST_IS_IN_TABLE_COND_VVC:
|
||||
z->op = OP_CONST_IS_NOT_IN_TABLE_COND_VVC;
|
||||
break;
|
||||
case OP_CONST_IS_NOT_IN_TABLE_COND_VVC:
|
||||
z->op = OP_CONST_IS_IN_TABLE_COND_VVC;
|
||||
break;
|
||||
case OP_CONST_IS_IN_TABLE_COND_VVC:
|
||||
z->op = OP_CONST_IS_NOT_IN_TABLE_COND_VVC;
|
||||
break;
|
||||
case OP_CONST_IS_NOT_IN_TABLE_COND_VVC:
|
||||
z->op = OP_CONST_IS_IN_TABLE_COND_VVC;
|
||||
break;
|
||||
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVVV:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVVV;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVVV:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVVV;
|
||||
break;
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVVV:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVVV;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVVV:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVVV;
|
||||
break;
|
||||
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVVC:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVVC;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVVC:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVVC;
|
||||
break;
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVVC:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVVC;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVVC:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVVC;
|
||||
break;
|
||||
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVCV:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVCV;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVCV:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVCV;
|
||||
break;
|
||||
case OP_VAL2_IS_IN_TABLE_COND_VVCV:
|
||||
z->op = OP_VAL2_IS_NOT_IN_TABLE_COND_VVCV;
|
||||
break;
|
||||
case OP_VAL2_IS_NOT_IN_TABLE_COND_VVCV:
|
||||
z->op = OP_VAL2_IS_IN_TABLE_COND_VVCV;
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("inconsistency in ZAMCompiler::IfElse");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("inconsistency in ZAMCompiler::IfElse");
|
||||
}
|
||||
|
||||
SetV(cond_stmt, GoToTargetBeyond(s2_end), branch_v);
|
||||
return s2_end;
|
||||
|
@ -267,8 +268,7 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
if ( e->Tag() == EXPR_HAS_FIELD )
|
||||
{
|
||||
auto hf = e->AsHasFieldExpr();
|
||||
auto z = GenInst(OP_HAS_FIELD_COND_VVV, op1->AsNameExpr(),
|
||||
hf->Field());
|
||||
auto z = GenInst(OP_HAS_FIELD_COND_VVV, op1->AsNameExpr(), hf->Field());
|
||||
z.op_type = OP_VVV_I2_I3;
|
||||
branch_v = 3;
|
||||
return AddInst(z);
|
||||
|
@ -289,8 +289,7 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
|
||||
if ( op1->Tag() == EXPR_NAME )
|
||||
{
|
||||
auto z = GenInst(OP_VAL_IS_IN_TABLE_COND_VVV,
|
||||
op1->AsNameExpr(), op2, 0);
|
||||
auto z = GenInst(OP_VAL_IS_IN_TABLE_COND_VVV, op1->AsNameExpr(), op2, 0);
|
||||
z.t = op1->GetType();
|
||||
branch_v = 3;
|
||||
return AddInst(z);
|
||||
|
@ -298,8 +297,7 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
|
||||
if ( op1->Tag() == EXPR_CONST )
|
||||
{
|
||||
auto z = GenInst(OP_CONST_IS_IN_TABLE_COND_VVC,
|
||||
op2, op1->AsConstExpr(), 0);
|
||||
auto z = GenInst(OP_CONST_IS_IN_TABLE_COND_VVC, op2, op1->AsConstExpr(), 0);
|
||||
z.t = op1->GetType();
|
||||
branch_v = 2;
|
||||
return AddInst(z);
|
||||
|
@ -328,24 +326,21 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
|
||||
if ( name0 && name1 )
|
||||
{
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVVV,
|
||||
n0, n1, op2, 0);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVVV, n0, n1, op2, 0);
|
||||
branch_v = 4;
|
||||
z.t2 = n0->GetType();
|
||||
}
|
||||
|
||||
else if ( name0 )
|
||||
{
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVVC,
|
||||
n0, op2, c1, 0);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVVC, n0, op2, c1, 0);
|
||||
branch_v = 3;
|
||||
z.t2 = n0->GetType();
|
||||
}
|
||||
|
||||
else if ( name1 )
|
||||
{
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVCV,
|
||||
n1, op2, c0, 0);
|
||||
z = GenInst(OP_VAL2_IS_IN_TABLE_COND_VVCV, n1, op2, c0, 0);
|
||||
branch_v = 3;
|
||||
z.t2 = n1->GetType();
|
||||
}
|
||||
|
@ -354,8 +349,7 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
{ // Both are constants, assign first to temporary.
|
||||
auto slot = TempForConst(c0);
|
||||
|
||||
z = ZInstI(OP_VAL2_IS_IN_TABLE_COND_VVVC,
|
||||
slot, FrameSlot(op2), 0, c1);
|
||||
z = ZInstI(OP_VAL2_IS_IN_TABLE_COND_VVVC, slot, FrameSlot(op2), 0, c1);
|
||||
z.op_type = OP_VVVC_I3;
|
||||
branch_v = 3;
|
||||
z.t2 = c0->GetType();
|
||||
|
@ -385,12 +379,13 @@ const ZAMStmt ZAMCompiler::GenCond(const Expr* e, int& branch_v)
|
|||
else
|
||||
branch_v = 2;
|
||||
|
||||
switch ( e->Tag() ) {
|
||||
switch ( e->Tag() )
|
||||
{
|
||||
#include "ZAM-Conds.h"
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad expression type in ZAMCompiler::GenCond");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad expression type in ZAMCompiler::GenCond");
|
||||
}
|
||||
|
||||
// Not reached.
|
||||
}
|
||||
|
@ -415,8 +410,7 @@ const ZAMStmt ZAMCompiler::CompileSwitch(const SwitchStmt* sw)
|
|||
return ValueSwitch(sw, n, c);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::ValueSwitch(const SwitchStmt* sw, const NameExpr* v,
|
||||
const ConstExpr* c)
|
||||
const ZAMStmt ZAMCompiler::ValueSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c)
|
||||
{
|
||||
int slot = v ? FrameSlot(v) : -1;
|
||||
|
||||
|
@ -432,40 +426,41 @@ const ZAMStmt ZAMCompiler::ValueSwitch(const SwitchStmt* sw, const NameExpr* v,
|
|||
int tbl = 0;
|
||||
ZOp op;
|
||||
|
||||
switch ( t->InternalType() ) {
|
||||
case TYPE_INTERNAL_INT:
|
||||
op = OP_SWITCHI_VVV;
|
||||
tbl = int_casesI.size();
|
||||
break;
|
||||
switch ( t->InternalType() )
|
||||
{
|
||||
case TYPE_INTERNAL_INT:
|
||||
op = OP_SWITCHI_VVV;
|
||||
tbl = int_casesI.size();
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
op = OP_SWITCHU_VVV;
|
||||
tbl = uint_casesI.size();
|
||||
break;
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
op = OP_SWITCHU_VVV;
|
||||
tbl = uint_casesI.size();
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
op = OP_SWITCHD_VVV;
|
||||
tbl = double_casesI.size();
|
||||
break;
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
op = OP_SWITCHD_VVV;
|
||||
tbl = double_casesI.size();
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_STRING:
|
||||
op = OP_SWITCHS_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
case TYPE_INTERNAL_STRING:
|
||||
op = OP_SWITCHS_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
op = OP_SWITCHA_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
op = OP_SWITCHA_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
op = OP_SWITCHN_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
op = OP_SWITCHN_VVV;
|
||||
tbl = str_casesI.size();
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad switch type");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad switch type");
|
||||
}
|
||||
|
||||
// Add the "head", i.e., the execution of the jump table.
|
||||
auto sw_head_op = ZInstI(op, slot, tbl, 0);
|
||||
|
@ -510,87 +505,88 @@ const ZAMStmt ZAMCompiler::ValueSwitch(const SwitchStmt* sw, const NameExpr* v,
|
|||
{
|
||||
auto case_body_start = case_start[index];
|
||||
|
||||
switch ( cv->GetType()->InternalType() ) {
|
||||
case TYPE_INTERNAL_INT:
|
||||
new_int_cases[cv->InternalInt()] = case_body_start;
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
new_uint_cases[cv->InternalUnsigned()] = case_body_start;
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
new_double_cases[cv->InternalDouble()] = case_body_start;
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_STRING:
|
||||
switch ( cv->GetType()->InternalType() )
|
||||
{
|
||||
// This leaks, but only statically so not worth
|
||||
// tracking the value for ultimate deletion.
|
||||
auto sv = cv->AsString()->Render();
|
||||
std::string s(sv);
|
||||
new_str_cases[s] = case_body_start;
|
||||
delete[] sv;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_INT:
|
||||
new_int_cases[cv->InternalInt()] = case_body_start;
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
{
|
||||
auto a = cv->AsAddr().AsString();
|
||||
new_str_cases[a] = case_body_start;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
new_uint_cases[cv->InternalUnsigned()] = case_body_start;
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
{
|
||||
auto n = cv->AsSubNet().AsString();
|
||||
new_str_cases[n] = case_body_start;
|
||||
break;
|
||||
}
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
new_double_cases[cv->InternalDouble()] = case_body_start;
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad recovered type when compiling switch");
|
||||
}
|
||||
case TYPE_INTERNAL_STRING:
|
||||
{
|
||||
// This leaks, but only statically so not worth
|
||||
// tracking the value for ultimate deletion.
|
||||
auto sv = cv->AsString()->Render();
|
||||
std::string s(sv);
|
||||
new_str_cases[s] = case_body_start;
|
||||
delete[] sv;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
{
|
||||
auto a = cv->AsAddr().AsString();
|
||||
new_str_cases[a] = case_body_start;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
{
|
||||
auto n = cv->AsSubNet().AsString();
|
||||
new_str_cases[n] = case_body_start;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad recovered type when compiling switch");
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the jump table to the set we're keeping for the
|
||||
// corresponding type.
|
||||
|
||||
switch ( t->InternalType() ) {
|
||||
case TYPE_INTERNAL_INT:
|
||||
int_casesI.push_back(new_int_cases);
|
||||
break;
|
||||
switch ( t->InternalType() )
|
||||
{
|
||||
case TYPE_INTERNAL_INT:
|
||||
int_casesI.push_back(new_int_cases);
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
uint_casesI.push_back(new_uint_cases);
|
||||
break;
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
uint_casesI.push_back(new_uint_cases);
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
double_casesI.push_back(new_double_cases);
|
||||
break;
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
double_casesI.push_back(new_double_cases);
|
||||
break;
|
||||
|
||||
case TYPE_INTERNAL_STRING:
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
str_casesI.push_back(new_str_cases);
|
||||
break;
|
||||
case TYPE_INTERNAL_STRING:
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
str_casesI.push_back(new_str_cases);
|
||||
break;
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad switch type");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad switch type");
|
||||
}
|
||||
|
||||
return body_end;
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::TypeSwitch(const SwitchStmt* sw, const NameExpr* v,
|
||||
const ConstExpr* c)
|
||||
const ZAMStmt ZAMCompiler::TypeSwitch(const SwitchStmt* sw, const NameExpr* v, const ConstExpr* c)
|
||||
{
|
||||
auto cases = sw->Cases();
|
||||
auto type_map = sw->TypeMap();
|
||||
|
||||
auto body_end = EmptyStmt();
|
||||
|
||||
auto tmp = NewSlot(true); // true since we know "any" is managed
|
||||
auto tmp = NewSlot(true); // true since we know "any" is managed
|
||||
|
||||
int slot = v ? FrameSlot(v) : 0;
|
||||
|
||||
|
@ -609,8 +605,8 @@ const ZAMStmt ZAMCompiler::TypeSwitch(const SwitchStmt* sw, const NameExpr* v,
|
|||
}
|
||||
|
||||
int def_ind = sw->DefaultCaseIndex();
|
||||
ZAMStmt def_succ(0); // successor to default, if any
|
||||
bool saw_def_succ = false; // whether def_succ is meaningful
|
||||
ZAMStmt def_succ(0); // successor to default, if any
|
||||
bool saw_def_succ = false; // whether def_succ is meaningful
|
||||
|
||||
PushFallThroughs();
|
||||
for ( auto& i : *type_map )
|
||||
|
@ -731,13 +727,12 @@ const ZAMStmt ZAMCompiler::CompileWhile(const WhileStmt* ws)
|
|||
return While(cond_pred.get(), loop_condition.get(), ws->Body().get());
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::While(const Stmt* cond_stmt, const Expr* cond,
|
||||
const Stmt* body)
|
||||
const ZAMStmt ZAMCompiler::While(const Stmt* cond_stmt, const Expr* cond, const Stmt* body)
|
||||
{
|
||||
auto head = StartingBlock();
|
||||
|
||||
if ( cond_stmt )
|
||||
(void) CompileStmt(cond_stmt);
|
||||
(void)CompileStmt(cond_stmt);
|
||||
|
||||
ZAMStmt cond_IF = EmptyStmt();
|
||||
int branch_v;
|
||||
|
@ -755,7 +750,7 @@ const ZAMStmt ZAMCompiler::While(const Stmt* cond_stmt, const Expr* cond,
|
|||
PushBreaks();
|
||||
|
||||
if ( body && body->Tag() != STMT_NULL )
|
||||
(void) CompileStmt(body);
|
||||
(void)CompileStmt(body);
|
||||
|
||||
auto tail = GoTo(GoToTarget(head));
|
||||
|
||||
|
@ -842,21 +837,20 @@ const ZAMStmt ZAMCompiler::LoopOverTable(const ForStmt* f, const NameExpr* val)
|
|||
|
||||
if ( value_var )
|
||||
{
|
||||
ZOp op = no_loop_vars ? OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV :
|
||||
OP_NEXT_TABLE_ITER_VAL_VAR_VVV;
|
||||
ZOp op =
|
||||
no_loop_vars ? OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV : OP_NEXT_TABLE_ITER_VAL_VAR_VVV;
|
||||
z = ZInstI(op, FrameSlot(value_var), iter_slot, 0);
|
||||
z.CheckIfManaged(value_var->GetType());
|
||||
z.op_type = OP_VVV_I2_I3;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZOp op = no_loop_vars ? OP_NEXT_TABLE_ITER_NO_VARS_VV :
|
||||
OP_NEXT_TABLE_ITER_VV;
|
||||
ZOp op = no_loop_vars ? OP_NEXT_TABLE_ITER_NO_VARS_VV : OP_NEXT_TABLE_ITER_VV;
|
||||
z = ZInstI(op, iter_slot, 0);
|
||||
z.op_type = OP_VV_I1_I2;
|
||||
}
|
||||
|
||||
z.aux = aux; // so ZOpt.cc can get to it
|
||||
z.aux = aux; // so ZOpt.cc can get to it
|
||||
|
||||
return FinishLoop(iter_head, z, body, iter_slot, true);
|
||||
}
|
||||
|
@ -919,7 +913,7 @@ const ZAMStmt ZAMCompiler::Loop(const Stmt* body)
|
|||
PushBreaks();
|
||||
|
||||
auto head = StartingBlock();
|
||||
(void) CompileStmt(body);
|
||||
(void)CompileStmt(body);
|
||||
auto tail = GoTo(GoToTarget(head));
|
||||
|
||||
ResolveNexts(GoToTarget(head));
|
||||
|
@ -928,8 +922,7 @@ const ZAMStmt ZAMCompiler::Loop(const Stmt* body)
|
|||
return tail;
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::FinishLoop(const ZAMStmt iter_head,
|
||||
ZInstI& iter_stmt, const Stmt* body,
|
||||
const ZAMStmt ZAMCompiler::FinishLoop(const ZAMStmt iter_head, ZInstI& iter_stmt, const Stmt* body,
|
||||
int iter_slot, bool is_table)
|
||||
{
|
||||
auto loop_iter = AddInst(iter_stmt);
|
||||
|
@ -946,7 +939,7 @@ const ZAMStmt ZAMCompiler::FinishLoop(const ZAMStmt iter_head,
|
|||
auto final_stmt = AddInst(z);
|
||||
|
||||
auto ot = iter_stmt.op_type;
|
||||
if ( ot == OP_VVV_I3 || ot == OP_VVV_I2_I3)
|
||||
if ( ot == OP_VVV_I3 || ot == OP_VVV_I2_I3 )
|
||||
SetV3(loop_iter, GoToTarget(final_stmt));
|
||||
else
|
||||
SetV2(loop_iter, GoToTarget(final_stmt));
|
||||
|
@ -984,9 +977,9 @@ const ZAMStmt ZAMCompiler::CompileReturn(const ReturnStmt* r)
|
|||
if ( e )
|
||||
{
|
||||
if ( e->Tag() == EXPR_NAME )
|
||||
(void) AssignVV(rv, e->AsNameExpr());
|
||||
(void)AssignVV(rv, e->AsNameExpr());
|
||||
else
|
||||
(void) AssignVC(rv, e->AsConstExpr());
|
||||
(void)AssignVC(rv, e->AsConstExpr());
|
||||
}
|
||||
|
||||
return CompileCatchReturn();
|
||||
|
@ -1035,23 +1028,23 @@ const ZAMStmt ZAMCompiler::CompileInit(const InitStmt* is)
|
|||
|
||||
auto& t = aggr->GetType();
|
||||
|
||||
switch ( t->Tag() ) {
|
||||
case TYPE_RECORD:
|
||||
last = InitRecord(aggr, t->AsRecordType());
|
||||
break;
|
||||
switch ( t->Tag() )
|
||||
{
|
||||
case TYPE_RECORD:
|
||||
last = InitRecord(aggr, t->AsRecordType());
|
||||
break;
|
||||
|
||||
case TYPE_VECTOR:
|
||||
last = InitVector(aggr, t->AsVectorType());
|
||||
break;
|
||||
case TYPE_VECTOR:
|
||||
last = InitVector(aggr, t->AsVectorType());
|
||||
break;
|
||||
|
||||
case TYPE_TABLE:
|
||||
last = InitTable(aggr, t->AsTableType(),
|
||||
aggr->GetAttrs().get());
|
||||
break;
|
||||
case TYPE_TABLE:
|
||||
last = InitTable(aggr, t->AsTableType(), aggr->GetAttrs().get());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
|
@ -1153,4 +1146,4 @@ const ZAMStmt ZAMCompiler::CompileWhen(const WhenStmt* ws)
|
|||
}
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
// Low-level support utilities/globals for ZAM compilation.
|
||||
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/ZAM/Support.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/ZeekString.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
const Stmt* curr_stmt;
|
||||
TypePtr log_ID_enum_type;
|
||||
|
@ -39,7 +41,6 @@ bool IsAny(const Type* t)
|
|||
return t->Tag() == TYPE_ANY;
|
||||
}
|
||||
|
||||
|
||||
StringVal* ZAM_to_lower(const StringVal* sv)
|
||||
{
|
||||
auto bs = sv->AsString();
|
||||
|
@ -57,14 +58,14 @@ StringVal* ZAM_to_lower(const StringVal* sv)
|
|||
}
|
||||
|
||||
*ls++ = '\0';
|
||||
|
||||
|
||||
return new StringVal(new String(1, lower_s, n));
|
||||
}
|
||||
|
||||
StringVal* ZAM_sub_bytes(const StringVal* s, bro_uint_t start, bro_int_t n)
|
||||
{
|
||||
if ( start > 0 )
|
||||
--start; // make it 0-based
|
||||
--start; // make it 0-based
|
||||
|
||||
auto ss = s->AsString()->GetSubstring(start, n);
|
||||
|
||||
|
@ -103,4 +104,4 @@ void ZAM_run_time_warning(const Location* loc, const char* msg)
|
|||
reporter->Warning("%s: %s", d.Description(), msg);
|
||||
}
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "zeek/Expr.h"
|
||||
#include "zeek/Stmt.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
using ValVec = std::vector<ValPtr>;
|
||||
|
||||
|
@ -18,16 +19,20 @@ extern const Stmt* curr_stmt;
|
|||
// True if a function with the given profile can be compiled to ZAM.
|
||||
// If not, returns the reason in *reason, if non-nil.
|
||||
class ProfileFunc;
|
||||
extern bool is_ZAM_compilable(const ProfileFunc* pf,
|
||||
const char** reason = nullptr);
|
||||
extern bool is_ZAM_compilable(const ProfileFunc* pf, const char** reason = nullptr);
|
||||
|
||||
// True if a given type is one that we treat internally as an "any" type.
|
||||
extern bool IsAny(const Type* t);
|
||||
|
||||
// Convenience functions for getting to these.
|
||||
inline bool IsAny(const TypePtr& t) { return IsAny(t.get()); }
|
||||
inline bool IsAny(const Expr* e) { return IsAny(e->GetType()); }
|
||||
|
||||
inline bool IsAny(const TypePtr& t)
|
||||
{
|
||||
return IsAny(t.get());
|
||||
}
|
||||
inline bool IsAny(const Expr* e)
|
||||
{
|
||||
return IsAny(e->GetType());
|
||||
}
|
||||
|
||||
// Needed for the logging built-in. Exported so that ZAM can make sure it's
|
||||
// defined when compiling.
|
||||
|
@ -38,8 +43,7 @@ extern TypePtr any_base_type;
|
|||
|
||||
extern void ZAM_run_time_error(const char* msg);
|
||||
extern void ZAM_run_time_error(const Location* loc, const char* msg);
|
||||
extern void ZAM_run_time_error(const Location* loc, const char* msg,
|
||||
const Obj* o);
|
||||
extern void ZAM_run_time_error(const Location* loc, const char* msg, const Obj* o);
|
||||
extern void ZAM_run_time_error(const Stmt* stmt, const char* msg);
|
||||
extern void ZAM_run_time_error(const char* msg, const Obj* o);
|
||||
|
||||
|
@ -50,4 +54,4 @@ extern void ZAM_run_time_warning(const Location* loc, const char* msg);
|
|||
extern StringVal* ZAM_to_lower(const StringVal* sv);
|
||||
extern StringVal* ZAM_sub_bytes(const StringVal* s, bro_uint_t start, bro_int_t n);
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
// Methods for dealing with variables (both ZAM and script-level).
|
||||
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/script_opt/ProfileFunc.h"
|
||||
#include "zeek/script_opt/Reduce.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
bool ZAMCompiler::IsUnused(const IDPtr& id, const Stmt* where) const
|
||||
{
|
||||
|
@ -27,7 +27,8 @@ bool ZAMCompiler::IsUnused(const IDPtr& id, const Stmt* where) const
|
|||
void ZAMCompiler::LoadParam(ID* id)
|
||||
{
|
||||
if ( id->IsType() )
|
||||
reporter->InternalError("don't know how to compile local variable that's a type not a value");
|
||||
reporter->InternalError(
|
||||
"don't know how to compile local variable that's a type not a value");
|
||||
|
||||
bool is_any = IsAny(id->GetType());
|
||||
|
||||
|
@ -41,7 +42,7 @@ void ZAMCompiler::LoadParam(ID* id)
|
|||
z.SetType(id->GetType());
|
||||
z.op_type = OP_VV_FRAME;
|
||||
|
||||
(void) AddInst(z);
|
||||
(void)AddInst(z);
|
||||
}
|
||||
|
||||
const ZAMStmt ZAMCompiler::LoadGlobal(ID* id)
|
||||
|
@ -80,7 +81,7 @@ int ZAMCompiler::FrameSlot(const ID* id)
|
|||
auto slot = RawSlot(id);
|
||||
|
||||
if ( id->IsGlobal() )
|
||||
(void) LoadGlobal(frame_denizens[slot]);
|
||||
(void)LoadGlobal(frame_denizens[slot]);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
@ -89,28 +90,29 @@ int ZAMCompiler::Frame1Slot(const ID* id, ZAMOp1Flavor fl)
|
|||
{
|
||||
auto slot = RawSlot(id);
|
||||
|
||||
switch ( fl ) {
|
||||
case OP1_READ:
|
||||
if ( id->IsGlobal() )
|
||||
(void) LoadGlobal(frame_denizens[slot]);
|
||||
break;
|
||||
switch ( fl )
|
||||
{
|
||||
case OP1_READ:
|
||||
if ( id->IsGlobal() )
|
||||
(void)LoadGlobal(frame_denizens[slot]);
|
||||
break;
|
||||
|
||||
case OP1_WRITE:
|
||||
if ( id->IsGlobal() )
|
||||
pending_global_store = global_id_to_info[id];
|
||||
break;
|
||||
case OP1_WRITE:
|
||||
if ( id->IsGlobal() )
|
||||
pending_global_store = global_id_to_info[id];
|
||||
break;
|
||||
|
||||
case OP1_READ_WRITE:
|
||||
if ( id->IsGlobal() )
|
||||
{
|
||||
(void) LoadGlobal(frame_denizens[slot]);
|
||||
pending_global_store = global_id_to_info[id];
|
||||
}
|
||||
break;
|
||||
case OP1_READ_WRITE:
|
||||
if ( id->IsGlobal() )
|
||||
{
|
||||
(void)LoadGlobal(frame_denizens[slot]);
|
||||
pending_global_store = global_id_to_info[id];
|
||||
}
|
||||
break;
|
||||
|
||||
case OP1_INTERNAL:
|
||||
break;
|
||||
}
|
||||
case OP1_INTERNAL:
|
||||
break;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
@ -152,9 +154,9 @@ int ZAMCompiler::TempForConst(const ConstExpr* c)
|
|||
|
||||
auto z = ZInstI(OP_ASSIGN_CONST_VC, slot, c);
|
||||
z.CheckIfManaged(c->GetType());
|
||||
(void) AddInst(z);
|
||||
(void)AddInst(z);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/RE.h"
|
||||
#include "zeek/Frame.h"
|
||||
#include "zeek/EventHandler.h"
|
||||
#include "zeek/Trigger.h"
|
||||
#include "zeek/Traverse.h"
|
||||
#include "zeek/Frame.h"
|
||||
#include "zeek/Overflow.h"
|
||||
#include "zeek/RE.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Traverse.h"
|
||||
#include "zeek/Trigger.h"
|
||||
#include "zeek/script_opt/ScriptOpt.h"
|
||||
#include "zeek/script_opt/ZAM/Compile.h"
|
||||
|
||||
|
@ -22,8 +22,8 @@
|
|||
#include "zeek/file_analysis/Manager.h"
|
||||
#include "zeek/logging/Manager.h"
|
||||
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
using std::vector;
|
||||
|
||||
|
@ -31,26 +31,22 @@ static bool did_init = false;
|
|||
|
||||
// Count of how often each type of ZOP executed, and how much CPU it
|
||||
// cumulatively took.
|
||||
int ZOP_count[OP_NOP+1];
|
||||
double ZOP_CPU[OP_NOP+1];
|
||||
|
||||
int ZOP_count[OP_NOP + 1];
|
||||
double ZOP_CPU[OP_NOP + 1];
|
||||
|
||||
void report_ZOP_profile()
|
||||
{
|
||||
for ( int i = 1; i <= OP_NOP; ++i )
|
||||
if ( ZOP_count[i] > 0 )
|
||||
printf("%s\t%d\t%.06f\n", ZOP_name(ZOp(i)),
|
||||
ZOP_count[i], ZOP_CPU[i]);
|
||||
printf("%s\t%d\t%.06f\n", ZOP_name(ZOp(i)), ZOP_count[i], ZOP_CPU[i]);
|
||||
}
|
||||
|
||||
|
||||
// Sets the given element to a copy of an existing (not newly constructed)
|
||||
// ZVal, including underlying memory management. Returns false if the
|
||||
// assigned value was missing (which we can only tell for managed types),
|
||||
// true otherwise.
|
||||
|
||||
static bool copy_vec_elem(VectorVal* vv, bro_uint_t ind, ZVal zv,
|
||||
const TypePtr& t)
|
||||
static bool copy_vec_elem(VectorVal* vv, bro_uint_t ind, ZVal zv, const TypePtr& t)
|
||||
{
|
||||
if ( vv->Size() <= ind )
|
||||
vv->Resize(ind + 1);
|
||||
|
@ -82,40 +78,39 @@ static bool copy_vec_elem(VectorVal* vv, bro_uint_t ind, ZVal zv,
|
|||
// Unary and binary element-by-element vector operations, yielding a new
|
||||
// VectorVal with a yield type of 't'. 'z' is passed in only for localizing
|
||||
// errors.
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2, const ZInst& z);
|
||||
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2, const VectorVal* v3,
|
||||
const ZInst& z);
|
||||
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||
const VectorVal* v3, const ZInst& z);
|
||||
|
||||
// Vector coercion.
|
||||
#define VEC_COERCE(tag, lhs_type, cast, rhs_accessor, ov_check, ov_err) \
|
||||
static VectorVal* vec_coerce_##tag(VectorVal* vec, const ZInst& z) \
|
||||
{ \
|
||||
auto& v = *vec->RawVec(); \
|
||||
auto yt = make_intrusive<VectorType>(base_type(lhs_type)); \
|
||||
auto res_zv = new VectorVal(yt); \
|
||||
auto n = v.size(); \
|
||||
res_zv->Resize(n); \
|
||||
auto& res = *res_zv->RawVec(); \
|
||||
for ( auto i = 0U; i < n; ++i ) \
|
||||
if ( v[i] ) \
|
||||
{ \
|
||||
auto vi = (*v[i]).rhs_accessor; \
|
||||
if ( ov_check(vi) ) \
|
||||
{ \
|
||||
std::string err = "overflow promoting from "; \
|
||||
err += ov_err; \
|
||||
err += " arithmetic value"; \
|
||||
ZAM_run_time_error(z.loc, err.c_str()); \
|
||||
res[i] = std::nullopt; \
|
||||
} \
|
||||
else \
|
||||
res[i] = ZVal(cast(vi)); \
|
||||
} \
|
||||
else \
|
||||
res[i] = std::nullopt; \
|
||||
return res_zv; \
|
||||
#define VEC_COERCE(tag, lhs_type, cast, rhs_accessor, ov_check, ov_err) \
|
||||
static VectorVal* vec_coerce_##tag(VectorVal* vec, const ZInst& z) \
|
||||
{ \
|
||||
auto& v = *vec->RawVec(); \
|
||||
auto yt = make_intrusive<VectorType>(base_type(lhs_type)); \
|
||||
auto res_zv = new VectorVal(yt); \
|
||||
auto n = v.size(); \
|
||||
res_zv->Resize(n); \
|
||||
auto& res = *res_zv->RawVec(); \
|
||||
for ( auto i = 0U; i < n; ++i ) \
|
||||
if ( v[i] ) \
|
||||
{ \
|
||||
auto vi = (*v[i]).rhs_accessor; \
|
||||
if ( ov_check(vi) ) \
|
||||
{ \
|
||||
std::string err = "overflow promoting from "; \
|
||||
err += ov_err; \
|
||||
err += " arithmetic value"; \
|
||||
ZAM_run_time_error(z.loc, err.c_str()); \
|
||||
res[i] = std::nullopt; \
|
||||
} \
|
||||
else \
|
||||
res[i] = ZVal(cast(vi)); \
|
||||
} \
|
||||
else \
|
||||
res[i] = std::nullopt; \
|
||||
return res_zv; \
|
||||
}
|
||||
|
||||
#define false_func(x) false
|
||||
|
@ -124,7 +119,8 @@ VEC_COERCE(DI, TYPE_DOUBLE, double, AsInt(), false_func, "")
|
|||
VEC_COERCE(DU, TYPE_DOUBLE, double, AsCount(), false_func, "")
|
||||
VEC_COERCE(ID, TYPE_INT, bro_int_t, AsDouble(), double_to_int_would_overflow, "double to signed")
|
||||
VEC_COERCE(IU, TYPE_INT, bro_int_t, AsCount(), count_to_int_would_overflow, "unsigned to signed")
|
||||
VEC_COERCE(UD, TYPE_COUNT, bro_uint_t, AsDouble(), double_to_count_would_overflow, "double to unsigned")
|
||||
VEC_COERCE(UD, TYPE_COUNT, bro_uint_t, AsDouble(), double_to_count_would_overflow,
|
||||
"double to unsigned")
|
||||
VEC_COERCE(UI, TYPE_COUNT, bro_int_t, AsInt(), int_to_count_would_overflow, "signed to unsigned")
|
||||
|
||||
double curr_CPU_time()
|
||||
|
@ -134,9 +130,7 @@ double curr_CPU_time()
|
|||
return double(ts.tv_sec) + double(ts.tv_nsec) / 1e9;
|
||||
}
|
||||
|
||||
|
||||
ZBody::ZBody(const char* _func_name, const ZAMCompiler* zc)
|
||||
: Stmt(STMT_ZAM)
|
||||
ZBody::ZBody(const char* _func_name, const ZAMCompiler* zc) : Stmt(STMT_ZAM)
|
||||
{
|
||||
func_name = _func_name;
|
||||
|
||||
|
@ -288,14 +282,13 @@ ValPtr ZBody::DoExec(Frame* f, int start_pc, StmtFlowType& flow)
|
|||
|
||||
if ( ! table_iters.empty() )
|
||||
{
|
||||
local_table_iters =
|
||||
std::make_unique<TableIterVec>(table_iters.size());
|
||||
local_table_iters = std::make_unique<TableIterVec>(table_iters.size());
|
||||
*local_table_iters = table_iters;
|
||||
tiv_ptr = &(*local_table_iters);
|
||||
}
|
||||
}
|
||||
|
||||
flow = FLOW_RETURN; // can be over-written by a Hook-Break
|
||||
flow = FLOW_RETURN; // can be over-written by a Hook-Break
|
||||
|
||||
while ( pc < end_pc && ! ZAM_error )
|
||||
{
|
||||
|
@ -315,16 +308,17 @@ ValPtr ZBody::DoExec(Frame* f, int start_pc, StmtFlowType& flow)
|
|||
}
|
||||
#endif
|
||||
|
||||
switch ( z.op ) {
|
||||
case OP_NOP:
|
||||
break;
|
||||
switch ( z.op )
|
||||
{
|
||||
case OP_NOP:
|
||||
break;
|
||||
|
||||
#include "ZAM-EvalMacros.h"
|
||||
#include "ZAM-EvalDefs.h"
|
||||
#include "ZAM-EvalMacros.h"
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad ZAM opcode");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad ZAM opcode");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( do_profile )
|
||||
|
@ -366,7 +360,7 @@ ValPtr ZBody::DoExec(Frame* f, int start_pc, StmtFlowType& flow)
|
|||
ZVal::DeleteManagedType(v);
|
||||
}
|
||||
|
||||
delete [] frame;
|
||||
delete[] frame;
|
||||
}
|
||||
|
||||
// Clear any error state.
|
||||
|
@ -393,8 +387,7 @@ void ZBody::ProfileExecution() const
|
|||
|
||||
for ( auto i = 0U; i < inst_count->size(); ++i )
|
||||
{
|
||||
printf("%s %d %d %.06f ", func_name, i,
|
||||
(*inst_count)[i], (*inst_CPU)[i]);
|
||||
printf("%s %d %d %.06f ", func_name, i, (*inst_count)[i], (*inst_CPU)[i]);
|
||||
insts[i].Dump(i, &frame_denizens);
|
||||
}
|
||||
}
|
||||
|
@ -420,8 +413,7 @@ bool ZBody::CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type,
|
|||
}
|
||||
|
||||
char buf[8192];
|
||||
snprintf(buf, sizeof buf, "run-time type clash (%s/%s)",
|
||||
type_name(at), type_name(et));
|
||||
snprintf(buf, sizeof buf, "run-time type clash (%s/%s)", type_name(at), type_name(et));
|
||||
|
||||
reporter->RuntimeError(loc, "%s", buf);
|
||||
return false;
|
||||
|
@ -474,7 +466,6 @@ TraversalCode ZBody::Traverse(TraversalCallback* cb) const
|
|||
HANDLE_TC_STMT_POST(tc);
|
||||
}
|
||||
|
||||
|
||||
ValPtr ZAMResumption::Exec(Frame* f, StmtFlowType& flow)
|
||||
{
|
||||
return am->DoExec(f, xfer_pc, flow);
|
||||
|
@ -494,10 +485,8 @@ TraversalCode ZAMResumption::Traverse(TraversalCallback* cb) const
|
|||
HANDLE_TC_STMT_POST(tc);
|
||||
}
|
||||
|
||||
|
||||
// Unary vector operation of v1 <vec-op> v2.
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
||||
const ZInst& z)
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2, const ZInst& z)
|
||||
{
|
||||
// We could speed this up further still by gen'ing up an instance
|
||||
// of the loop inside each switch case (in which case we might as
|
||||
|
@ -512,13 +501,14 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
|||
for ( auto i = 0U; i < n; ++i )
|
||||
{
|
||||
if ( vec2[i] )
|
||||
switch ( op ) {
|
||||
switch ( op )
|
||||
{
|
||||
|
||||
#include "ZAM-Vec1EvalDefs.h"
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad invocation of VecExec");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad invocation of VecExec");
|
||||
}
|
||||
else
|
||||
vec1[i] = std::nullopt;
|
||||
}
|
||||
|
@ -530,8 +520,8 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2,
|
|||
}
|
||||
|
||||
// Binary vector operation of v1 = v2 <vec-op> v3.
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
||||
const VectorVal* v2, const VectorVal* v3, const ZInst& z)
|
||||
static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, const VectorVal* v2, const VectorVal* v3,
|
||||
const ZInst& z)
|
||||
{
|
||||
// See comment above re further speed-up.
|
||||
|
||||
|
@ -544,13 +534,14 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
|||
for ( auto i = 0U; i < vec2.size(); ++i )
|
||||
{
|
||||
if ( vec2[i] && vec3[i] )
|
||||
switch ( op ) {
|
||||
switch ( op )
|
||||
{
|
||||
|
||||
#include "ZAM-Vec2EvalDefs.h"
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad invocation of VecExec");
|
||||
}
|
||||
default:
|
||||
reporter->InternalError("bad invocation of VecExec");
|
||||
}
|
||||
else
|
||||
vec1[i] = std::nullopt;
|
||||
}
|
||||
|
@ -561,4 +552,4 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1,
|
|||
Unref(old_v1);
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -7,25 +7,27 @@
|
|||
#include "zeek/script_opt/ZAM/IterInfo.h"
|
||||
#include "zeek/script_opt/ZAM/Support.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
// Static information about globals used in a function.
|
||||
class GlobalInfo {
|
||||
class GlobalInfo
|
||||
{
|
||||
public:
|
||||
IDPtr id;
|
||||
int slot;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// These are the counterparts to CaseMapI and CaseMapsI in ZAM.h,
|
||||
// but concretized to use instruction numbers rather than pointers
|
||||
// to instructions.
|
||||
template<typename T> using CaseMap = std::map<T, int>;
|
||||
template<typename T> using CaseMaps = std::vector<CaseMap<T>>;
|
||||
template <typename T> using CaseMap = std::map<T, int>;
|
||||
template <typename T> using CaseMaps = std::vector<CaseMap<T>>;
|
||||
|
||||
using TableIterVec = std::vector<TableIterInfo>;
|
||||
|
||||
class ZBody : public Stmt {
|
||||
class ZBody : public Stmt
|
||||
{
|
||||
public:
|
||||
ZBody(const char* _func_name, const ZAMCompiler* zc);
|
||||
|
||||
|
@ -62,7 +64,7 @@ protected:
|
|||
bool CheckAnyType(const TypePtr& any_type, const TypePtr& expected_type,
|
||||
const Location* loc) const;
|
||||
|
||||
StmtPtr Duplicate() override { return {NewRef{}, this}; }
|
||||
StmtPtr Duplicate() override { return {NewRef{}, this}; }
|
||||
|
||||
void StmtDescribe(ODesc* d) const override;
|
||||
TraversalCode Traverse(TraversalCallback* cb) const override;
|
||||
|
@ -105,28 +107,29 @@ private:
|
|||
//
|
||||
// These need to be pointers so we can manipulate them in a
|
||||
// const method.
|
||||
std::vector<int>* inst_count = nullptr; // for profiling
|
||||
double* CPU_time = nullptr; // cumulative CPU time for the program
|
||||
std::vector<double>* inst_CPU; // per-instruction CPU time.
|
||||
std::vector<int>* inst_count = nullptr; // for profiling
|
||||
double* CPU_time = nullptr; // cumulative CPU time for the program
|
||||
std::vector<double>* inst_CPU; // per-instruction CPU time.
|
||||
|
||||
CaseMaps<bro_int_t> int_cases;
|
||||
CaseMaps<bro_uint_t> uint_cases;
|
||||
CaseMaps<double> double_cases;
|
||||
CaseMaps<std::string> str_cases;
|
||||
};
|
||||
};
|
||||
|
||||
// This is a statement that resumes execution into a code block in a
|
||||
// ZBody. Used for deferred execution for "when" statements.
|
||||
|
||||
class ZAMResumption : public Stmt {
|
||||
class ZAMResumption : public Stmt
|
||||
{
|
||||
public:
|
||||
ZAMResumption(ZBody* _am, int _xfer_pc)
|
||||
: Stmt(STMT_ZAM_RESUMPTION), am(_am), xfer_pc(_xfer_pc)
|
||||
{ }
|
||||
ZAMResumption(ZBody* _am, int _xfer_pc) : Stmt(STMT_ZAM_RESUMPTION), am(_am), xfer_pc(_xfer_pc)
|
||||
{
|
||||
}
|
||||
|
||||
ValPtr Exec(Frame* f, StmtFlowType& flow) override;
|
||||
|
||||
StmtPtr Duplicate() override { return {NewRef{}, this}; }
|
||||
StmtPtr Duplicate() override { return {NewRef{}, this}; }
|
||||
|
||||
void StmtDescribe(ODesc* d) const override;
|
||||
|
||||
|
@ -135,10 +138,9 @@ protected:
|
|||
|
||||
ZBody* am;
|
||||
int xfer_pc = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Prints the execution profile.
|
||||
extern void report_ZOP_profile();
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Reporter.h"
|
||||
#include "zeek/Func.h"
|
||||
#include "zeek/script_opt/ZAM/ZInst.h"
|
||||
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Func.h"
|
||||
#include "zeek/Reporter.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
void ZInst::Dump(bro_uint_t inst_num, const FrameReMap* mappings) const
|
||||
{
|
||||
|
@ -21,112 +23,106 @@ void ZInst::Dump(bro_uint_t inst_num, const FrameReMap* mappings) const
|
|||
Dump(id1, id2, id3, id4);
|
||||
}
|
||||
|
||||
void ZInst::Dump(const string& id1, const string& id2, const string& id3,
|
||||
const string& id4) const
|
||||
void ZInst::Dump(const string& id1, const string& id2, const string& id3, const string& id4) const
|
||||
{
|
||||
printf("%s ", ZOP_name(op));
|
||||
// printf("(%s) ", op_type_name(op_type));
|
||||
if ( t && 0 )
|
||||
printf("(%s) ", type_name(t->Tag()));
|
||||
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
break;
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
break;
|
||||
|
||||
case OP_V:
|
||||
printf("%s", id1.c_str());
|
||||
break;
|
||||
case OP_V:
|
||||
printf("%s", id1.c_str());
|
||||
break;
|
||||
|
||||
case OP_VV:
|
||||
printf("%s, %s", id1.c_str(), id2.c_str());
|
||||
break;
|
||||
case OP_VV:
|
||||
printf("%s, %s", id1.c_str(), id2.c_str());
|
||||
break;
|
||||
|
||||
case OP_VVV:
|
||||
printf("%s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str());
|
||||
break;
|
||||
case OP_VVV:
|
||||
printf("%s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str());
|
||||
break;
|
||||
|
||||
case OP_VVVV:
|
||||
printf("%s, %s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str(),
|
||||
id4.c_str());
|
||||
break;
|
||||
case OP_VVVV:
|
||||
printf("%s, %s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str(), id4.c_str());
|
||||
break;
|
||||
|
||||
case OP_VVVC:
|
||||
printf("%s, %s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str(),
|
||||
ConstDump().c_str());
|
||||
break;
|
||||
case OP_VVVC:
|
||||
printf("%s, %s, %s, %s", id1.c_str(), id2.c_str(), id3.c_str(), ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_C:
|
||||
printf("%s", ConstDump().c_str());
|
||||
break;
|
||||
case OP_C:
|
||||
printf("%s", ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VC:
|
||||
printf("%s, %s", id1.c_str(), ConstDump().c_str());
|
||||
break;
|
||||
case OP_VC:
|
||||
printf("%s, %s", id1.c_str(), ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VVC:
|
||||
printf("%s, %s, %s", id1.c_str(), id2.c_str(),
|
||||
ConstDump().c_str());
|
||||
break;
|
||||
case OP_VVC:
|
||||
printf("%s, %s, %s", id1.c_str(), id2.c_str(), ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_V_I1:
|
||||
printf("%d", v1);
|
||||
break;
|
||||
case OP_V_I1:
|
||||
printf("%d", v1);
|
||||
break;
|
||||
|
||||
case OP_VC_I1:
|
||||
printf("%d %s", v1, ConstDump().c_str());
|
||||
break;
|
||||
case OP_VC_I1:
|
||||
printf("%d %s", v1, ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VV_FRAME:
|
||||
printf("%s, interpreter frame[%d]", id1.c_str(), v2);
|
||||
break;
|
||||
case OP_VV_FRAME:
|
||||
printf("%s, interpreter frame[%d]", id1.c_str(), v2);
|
||||
break;
|
||||
|
||||
case OP_VV_I2:
|
||||
printf("%s, %d", id1.c_str(), v2);
|
||||
break;
|
||||
case OP_VV_I2:
|
||||
printf("%s, %d", id1.c_str(), v2);
|
||||
break;
|
||||
|
||||
case OP_VV_I1_I2:
|
||||
printf("%d, %d", v1, v2);
|
||||
break;
|
||||
case OP_VV_I1_I2:
|
||||
printf("%d, %d", v1, v2);
|
||||
break;
|
||||
|
||||
case OP_VVC_I2:
|
||||
printf("%s, %d, %s", id1.c_str(), v2, ConstDump().c_str());
|
||||
break;
|
||||
case OP_VVC_I2:
|
||||
printf("%s, %d, %s", id1.c_str(), v2, ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VVV_I3:
|
||||
printf("%s, %s, %d", id1.c_str(), id2.c_str(), v3);
|
||||
break;
|
||||
case OP_VVV_I3:
|
||||
printf("%s, %s, %d", id1.c_str(), id2.c_str(), v3);
|
||||
break;
|
||||
|
||||
case OP_VVV_I2_I3:
|
||||
printf("%s, %d, %d", id1.c_str(), v2, v3);
|
||||
break;
|
||||
case OP_VVV_I2_I3:
|
||||
printf("%s, %d, %d", id1.c_str(), v2, v3);
|
||||
break;
|
||||
|
||||
case OP_VVVV_I4:
|
||||
printf("%s, %s, %s, %d", id1.c_str(), id2.c_str(), id3.c_str(),
|
||||
v4);
|
||||
break;
|
||||
case OP_VVVV_I4:
|
||||
printf("%s, %s, %s, %d", id1.c_str(), id2.c_str(), id3.c_str(), v4);
|
||||
break;
|
||||
|
||||
case OP_VVVV_I3_I4:
|
||||
printf("%s, %s, %d, %d", id1.c_str(), id2.c_str(), v3, v4);
|
||||
break;
|
||||
case OP_VVVV_I3_I4:
|
||||
printf("%s, %s, %d, %d", id1.c_str(), id2.c_str(), v3, v4);
|
||||
break;
|
||||
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
printf("%s, %d, %d, %d", id1.c_str(), v2, v3, v4);
|
||||
break;
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
printf("%s, %d, %d, %d", id1.c_str(), v2, v3, v4);
|
||||
break;
|
||||
|
||||
case OP_VVVC_I3:
|
||||
printf("%s, %s, %d, %s", id1.c_str(), id2.c_str(), v3,
|
||||
ConstDump().c_str());
|
||||
break;
|
||||
case OP_VVVC_I3:
|
||||
printf("%s, %s, %d, %s", id1.c_str(), id2.c_str(), v3, ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VVVC_I2_I3:
|
||||
printf("%s, %d, %d, %s", id1.c_str(), v2, v3,
|
||||
ConstDump().c_str());
|
||||
break;
|
||||
case OP_VVVC_I2_I3:
|
||||
printf("%s, %d, %d, %s", id1.c_str(), v2, v3, ConstDump().c_str());
|
||||
break;
|
||||
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
printf("%d, %d, %d, %s", v1, v2, v3, ConstDump().c_str());
|
||||
break;
|
||||
}
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
printf("%d, %d, %d, %s", v1, v2, v3, ConstDump().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
if ( func )
|
||||
printf(" (func %s)", func->Name());
|
||||
|
@ -136,80 +132,82 @@ void ZInst::Dump(const string& id1, const string& id2, const string& id3,
|
|||
|
||||
int ZInst::NumFrameSlots() const
|
||||
{
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return 0;
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return 0;
|
||||
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return 1;
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return 1;
|
||||
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
return 2;
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
return 2;
|
||||
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
return 3;
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
return 3;
|
||||
|
||||
case OP_VVVV:
|
||||
return 4;
|
||||
}
|
||||
case OP_VVVV:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ZInst::NumSlots() const
|
||||
{
|
||||
switch ( op_type ) {
|
||||
case OP_C:
|
||||
case OP_X:
|
||||
return 0;
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_C:
|
||||
case OP_X:
|
||||
return 0;
|
||||
|
||||
case OP_V:
|
||||
case OP_V_I1:
|
||||
case OP_VC:
|
||||
case OP_VC_I1:
|
||||
return 1;
|
||||
case OP_V:
|
||||
case OP_V_I1:
|
||||
case OP_VC:
|
||||
case OP_VC_I1:
|
||||
return 1;
|
||||
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VV_I1_I2:
|
||||
return 2;
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VV_I1_I2:
|
||||
return 2;
|
||||
|
||||
case OP_VVV:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return 3;
|
||||
case OP_VVV:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return 3;
|
||||
|
||||
case OP_VVVV:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return 4;
|
||||
}
|
||||
case OP_VVVV:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -236,8 +234,7 @@ string ZInst::VName(int n, bro_uint_t inst_num, const FrameReMap* mappings) cons
|
|||
// identifiers, then it matters whether this is slot 1
|
||||
// (starts right here) vs. slot > 1 (ignore change right
|
||||
// at the boundary and stick with older value).
|
||||
if ( (n == 1 && map.id_start[i] > inst_num) ||
|
||||
(n > 1 && map.id_start[i] >= inst_num) )
|
||||
if ( (n == 1 && map.id_start[i] > inst_num) || (n > 1 && map.id_start[i] >= inst_num) )
|
||||
// Went too far.
|
||||
break;
|
||||
}
|
||||
|
@ -247,41 +244,42 @@ string ZInst::VName(int n, bro_uint_t inst_num, const FrameReMap* mappings) cons
|
|||
ASSERT(i > 0);
|
||||
}
|
||||
|
||||
auto id = map.names.empty() ? map.ids[i-1]->Name() : map.names[i-1];
|
||||
auto id = map.names.empty() ? map.ids[i - 1]->Name() : map.names[i - 1];
|
||||
|
||||
return util::fmt("%d (%s)", slot, id);
|
||||
}
|
||||
|
||||
ValPtr ZInst::ConstVal() const
|
||||
{
|
||||
switch ( op_type ) {
|
||||
case OP_C:
|
||||
case OP_VC:
|
||||
case OP_VC_I1:
|
||||
case OP_VVC:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVVC:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return c.ToVal(t);
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_C:
|
||||
case OP_VC:
|
||||
case OP_VC_I1:
|
||||
case OP_VVC:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVVC:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return c.ToVal(t);
|
||||
|
||||
case OP_X:
|
||||
case OP_V:
|
||||
case OP_VV:
|
||||
case OP_VVV:
|
||||
case OP_VVVV:
|
||||
case OP_V_I1:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return nullptr;
|
||||
}
|
||||
case OP_X:
|
||||
case OP_V:
|
||||
case OP_VV:
|
||||
case OP_VVV:
|
||||
case OP_VVVV:
|
||||
case OP_V_I1:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -298,7 +296,6 @@ string ZInst::ConstDump() const
|
|||
return d.Description();
|
||||
}
|
||||
|
||||
|
||||
void ZInstI::Dump(const FrameMap* frame_ids, const FrameReMap* remappings) const
|
||||
{
|
||||
int n = NumFrameSlots();
|
||||
|
@ -312,8 +309,7 @@ void ZInstI::Dump(const FrameMap* frame_ids, const FrameReMap* remappings) const
|
|||
ZInst::Dump(id1, id2, id3, id4);
|
||||
}
|
||||
|
||||
string ZInstI::VName(int n, const FrameMap* frame_ids,
|
||||
const FrameReMap* remappings) const
|
||||
string ZInstI::VName(int n, const FrameMap* frame_ids, const FrameReMap* remappings) const
|
||||
{
|
||||
if ( n > NumFrameSlots() )
|
||||
return "";
|
||||
|
@ -327,8 +323,7 @@ string ZInstI::VName(int n, const FrameMap* frame_ids,
|
|||
|
||||
if ( remappings && live )
|
||||
{ // Find which identifier manifests at this instruction.
|
||||
ASSERT(slot >= 0 &&
|
||||
static_cast<bro_uint_t>(slot) < remappings->size());
|
||||
ASSERT(slot >= 0 && static_cast<bro_uint_t>(slot) < remappings->size());
|
||||
|
||||
auto& map = (*remappings)[slot];
|
||||
|
||||
|
@ -349,7 +344,7 @@ string ZInstI::VName(int n, const FrameMap* frame_ids,
|
|||
}
|
||||
|
||||
// For ZInstI's, map.ids is always populated.
|
||||
id = map.ids[i-1];
|
||||
id = map.ids[i - 1];
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -360,17 +355,18 @@ string ZInstI::VName(int n, const FrameMap* frame_ids,
|
|||
|
||||
bool ZInstI::DoesNotContinue() const
|
||||
{
|
||||
switch ( op ) {
|
||||
case OP_GOTO_V:
|
||||
case OP_HOOK_BREAK_X:
|
||||
case OP_RETURN_C:
|
||||
case OP_RETURN_V:
|
||||
case OP_RETURN_X:
|
||||
return true;
|
||||
switch ( op )
|
||||
{
|
||||
case OP_GOTO_V:
|
||||
case OP_HOOK_BREAK_X:
|
||||
case OP_RETURN_C:
|
||||
case OP_RETURN_V:
|
||||
case OP_RETURN_X:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZInstI::IsDirectAssignment() const
|
||||
|
@ -378,25 +374,26 @@ bool ZInstI::IsDirectAssignment() const
|
|||
if ( op_type != OP_VV )
|
||||
return false;
|
||||
|
||||
switch ( op ) {
|
||||
case OP_ASSIGN_VV_N:
|
||||
case OP_ASSIGN_VV_A:
|
||||
case OP_ASSIGN_VV_O:
|
||||
case OP_ASSIGN_VV_P:
|
||||
case OP_ASSIGN_VV_R:
|
||||
case OP_ASSIGN_VV_S:
|
||||
case OP_ASSIGN_VV_F:
|
||||
case OP_ASSIGN_VV_T:
|
||||
case OP_ASSIGN_VV_V:
|
||||
case OP_ASSIGN_VV_L:
|
||||
case OP_ASSIGN_VV_f:
|
||||
case OP_ASSIGN_VV_t:
|
||||
case OP_ASSIGN_VV:
|
||||
return true;
|
||||
switch ( op )
|
||||
{
|
||||
case OP_ASSIGN_VV_N:
|
||||
case OP_ASSIGN_VV_A:
|
||||
case OP_ASSIGN_VV_O:
|
||||
case OP_ASSIGN_VV_P:
|
||||
case OP_ASSIGN_VV_R:
|
||||
case OP_ASSIGN_VV_S:
|
||||
case OP_ASSIGN_VV_F:
|
||||
case OP_ASSIGN_VV_T:
|
||||
case OP_ASSIGN_VV_V:
|
||||
case OP_ASSIGN_VV_L:
|
||||
case OP_ASSIGN_VV_f:
|
||||
case OP_ASSIGN_VV_t:
|
||||
case OP_ASSIGN_VV:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZInstI::HasSideEffects() const
|
||||
|
@ -406,39 +403,40 @@ bool ZInstI::HasSideEffects() const
|
|||
|
||||
bool ZInstI::AssignsToSlot1() const
|
||||
{
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
|
||||
// We use this ginormous set of cases rather than "default" so
|
||||
// that when we add a new operand type, we have to consider
|
||||
// its behavior here. (Same for many of the other switch's
|
||||
// used for ZInst/ZinstI.)
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV:
|
||||
auto fl = op1_flavor[op];
|
||||
return fl == OP1_WRITE || fl == OP1_READ_WRITE;
|
||||
}
|
||||
// We use this ginormous set of cases rather than "default" so
|
||||
// that when we add a new operand type, we have to consider
|
||||
// its behavior here. (Same for many of the other switch's
|
||||
// used for ZInst/ZinstI.)
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
case OP_VVVV:
|
||||
auto fl = op1_flavor[op];
|
||||
return fl == OP1_WRITE || fl == OP1_READ_WRITE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -449,40 +447,41 @@ bool ZInstI::UsesSlot(int slot) const
|
|||
auto v1_relevant = fl == OP1_READ || fl == OP1_READ_WRITE;
|
||||
auto v1_match = v1_relevant && v1 == slot;
|
||||
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return v1_match;
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return v1_match;
|
||||
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
return v1_match || v2 == slot;
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
return v1_match || v2 == slot;
|
||||
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
return v1_match || v2 == slot || v3 == slot;
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
return v1_match || v2 == slot || v3 == slot;
|
||||
|
||||
case OP_VVVV:
|
||||
return v1_match || v2 == slot || v3 == slot || v4 == slot;
|
||||
}
|
||||
case OP_VVVV:
|
||||
return v1_match || v2 == slot || v3 == slot || v4 == slot;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -494,108 +493,110 @@ bool ZInstI::UsesSlots(int& s1, int& s2, int& s3, int& s4) const
|
|||
auto fl = op1_flavor[op];
|
||||
auto v1_relevant = fl == OP1_READ || fl == OP1_READ_WRITE;
|
||||
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
if ( ! v1_relevant )
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return false;
|
||||
|
||||
s1 = v1;
|
||||
return true;
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
if ( ! v1_relevant )
|
||||
return false;
|
||||
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
s1 = v2;
|
||||
s1 = v1;
|
||||
return true;
|
||||
|
||||
if ( v1_relevant )
|
||||
s2 = v1;
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
s1 = v2;
|
||||
|
||||
return true;
|
||||
if ( v1_relevant )
|
||||
s2 = v1;
|
||||
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
s1 = v2;
|
||||
s2 = v3;
|
||||
return true;
|
||||
|
||||
if ( v1_relevant )
|
||||
s3 = v1;
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
s1 = v2;
|
||||
s2 = v3;
|
||||
|
||||
return true;
|
||||
if ( v1_relevant )
|
||||
s3 = v1;
|
||||
|
||||
case OP_VVVV:
|
||||
s1 = v2;
|
||||
s2 = v3;
|
||||
s3 = v4;
|
||||
return true;
|
||||
|
||||
if ( v1_relevant )
|
||||
s4 = v1;
|
||||
case OP_VVVV:
|
||||
s1 = v2;
|
||||
s2 = v3;
|
||||
s3 = v4;
|
||||
|
||||
return true;
|
||||
}
|
||||
if ( v1_relevant )
|
||||
s4 = v1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ZInstI::UpdateSlots(std::vector<int>& slot_mapping)
|
||||
{
|
||||
switch ( op_type ) {
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return; // so we don't do any v1 remapping.
|
||||
switch ( op_type )
|
||||
{
|
||||
case OP_X:
|
||||
case OP_C:
|
||||
case OP_V_I1:
|
||||
case OP_VC_I1:
|
||||
case OP_VV_I1_I2:
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return; // so we don't do any v1 remapping.
|
||||
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
break;
|
||||
case OP_V:
|
||||
case OP_VC:
|
||||
case OP_VV_FRAME:
|
||||
case OP_VV_I2:
|
||||
case OP_VVC_I2:
|
||||
case OP_VVV_I2_I3:
|
||||
case OP_VVVC_I2_I3:
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
break;
|
||||
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
v2 = slot_mapping[v2];
|
||||
break;
|
||||
case OP_VV:
|
||||
case OP_VVC:
|
||||
case OP_VVV_I3:
|
||||
case OP_VVVV_I3_I4:
|
||||
case OP_VVVC_I3:
|
||||
v2 = slot_mapping[v2];
|
||||
break;
|
||||
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
v2 = slot_mapping[v2];
|
||||
v3 = slot_mapping[v3];
|
||||
break;
|
||||
case OP_VVV:
|
||||
case OP_VVVC:
|
||||
case OP_VVVV_I4:
|
||||
v2 = slot_mapping[v2];
|
||||
v3 = slot_mapping[v3];
|
||||
break;
|
||||
|
||||
case OP_VVVV:
|
||||
v2 = slot_mapping[v2];
|
||||
v3 = slot_mapping[v3];
|
||||
v4 = slot_mapping[v4];
|
||||
break;
|
||||
}
|
||||
case OP_VVVV:
|
||||
v2 = slot_mapping[v2];
|
||||
v3 = slot_mapping[v3];
|
||||
v4 = slot_mapping[v4];
|
||||
break;
|
||||
}
|
||||
|
||||
// Note, unlike for UsesSlots() we do *not* include OP1_READ_WRITE
|
||||
// here, because such instructions will already have v1 remapped
|
||||
|
@ -617,8 +618,7 @@ bool ZInstI::IsGlobalLoad() const
|
|||
for ( int t = 0; t < NUM_TYPES; ++t )
|
||||
{
|
||||
TypeTag tag = TypeTag(t);
|
||||
ZOp global_op_flavor =
|
||||
AssignmentFlavor(OP_LOAD_GLOBAL_VV, tag, false);
|
||||
ZOp global_op_flavor = AssignmentFlavor(OP_LOAD_GLOBAL_VV, tag, false);
|
||||
|
||||
if ( global_op_flavor != OP_NOP )
|
||||
global_ops.insert(global_op_flavor);
|
||||
|
@ -638,4 +638,4 @@ void ZInstI::InitConst(const ConstExpr* ce)
|
|||
reporter->InternalError("bad value compiling code");
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#include "zeek/script_opt/ZAM/Support.h"
|
||||
#include "zeek/script_opt/ZAM/ZOp.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
class Expr;
|
||||
class ConstExpr;
|
||||
|
@ -16,12 +17,13 @@ class Stmt;
|
|||
|
||||
using AttributesPtr = IntrusivePtr<Attributes>;
|
||||
|
||||
// Maps ZAM frame slots to associated identifiers.
|
||||
// Maps ZAM frame slots to associated identifiers.
|
||||
using FrameMap = std::vector<ID*>;
|
||||
|
||||
// Maps ZAM frame slots to information for sharing the slot across
|
||||
// multiple script variables.
|
||||
class FrameSharingInfo {
|
||||
class FrameSharingInfo
|
||||
{
|
||||
public:
|
||||
// The variables sharing the slot. ID's need to be non-const so we
|
||||
// can manipulate them, for example by changing their interpreter
|
||||
|
@ -43,7 +45,7 @@ public:
|
|||
|
||||
// Whether this is a managed slot.
|
||||
bool is_managed = false;
|
||||
};
|
||||
};
|
||||
|
||||
using FrameReMap = std::vector<FrameSharingInfo>;
|
||||
|
||||
|
@ -52,7 +54,8 @@ class ZInstAux;
|
|||
// A ZAM instruction. This base class has all the information for
|
||||
// execution, but omits information and methods only necessary for
|
||||
// compiling.
|
||||
class ZInst {
|
||||
class ZInst
|
||||
{
|
||||
public:
|
||||
ZInst(ZOp _op, ZAMOpType _op_type)
|
||||
{
|
||||
|
@ -61,22 +64,21 @@ public:
|
|||
}
|
||||
|
||||
// Create a stub instruction that will be populated later.
|
||||
ZInst() { }
|
||||
ZInst() { }
|
||||
|
||||
virtual ~ZInst() { }
|
||||
virtual ~ZInst() { }
|
||||
|
||||
// Methods for printing out the instruction for debugging/maintenance.
|
||||
void Dump(bro_uint_t inst_num, const FrameReMap* mappings) const;
|
||||
void Dump(const std::string& id1, const std::string& id2,
|
||||
const std::string& id3, const std::string& id4) const;
|
||||
void Dump(const std::string& id1, const std::string& id2, const std::string& id3,
|
||||
const std::string& id4) const;
|
||||
|
||||
// Returns the name to use in identifying one of the slots/integer
|
||||
// values (designated by "n"). "inst_num" identifes the instruction
|
||||
// by its number within a larger set. "mappings" provides the
|
||||
// mappings used to translate raw slots to the corresponding
|
||||
// script variable(s).
|
||||
std::string VName(int n, bro_uint_t inst_num,
|
||||
const FrameReMap* mappings) const;
|
||||
std::string VName(int n, bro_uint_t inst_num, const FrameReMap* mappings) const;
|
||||
|
||||
// Number of slots that refer to a frame element. These always
|
||||
// come first, if we use additional slots.
|
||||
|
@ -102,17 +104,17 @@ public:
|
|||
// Initialized here to keep Coverity happy.
|
||||
int v1 = -1, v2 = -1, v3 = -1, v4 = -1;
|
||||
|
||||
ZVal c; // constant associated with instruction, if any
|
||||
ZVal c; // constant associated with instruction, if any
|
||||
|
||||
// Meta-data associated with the execution.
|
||||
|
||||
// Type, usually for interpreting the constant.
|
||||
TypePtr t = nullptr;
|
||||
TypePtr t2 = nullptr; // just a few ops need two types
|
||||
const Expr* e = nullptr; // only needed for "when" expressions
|
||||
Func* func = nullptr; // used for calls
|
||||
EventHandler* event_handler = nullptr; // used for referring to events
|
||||
AttributesPtr attrs = nullptr; // used for things like constructors
|
||||
TypePtr t2 = nullptr; // just a few ops need two types
|
||||
const Expr* e = nullptr; // only needed for "when" expressions
|
||||
Func* func = nullptr; // used for calls
|
||||
EventHandler* event_handler = nullptr; // used for referring to events
|
||||
AttributesPtr attrs = nullptr; // used for things like constructors
|
||||
|
||||
// Auxiliary information. We could in principle use this to
|
||||
// consolidate a bunch of the above, though at the cost of
|
||||
|
@ -126,13 +128,14 @@ public:
|
|||
// Whether v1 represents a frame slot type for which we
|
||||
// explicitly manage the memory.
|
||||
bool is_managed = false;
|
||||
};
|
||||
};
|
||||
|
||||
// A intermediary ZAM instruction, one that includes information/methods
|
||||
// needed for compiling. Intermediate instructions use pointers to other
|
||||
// such instructions for branches, rather than concrete instruction
|
||||
// numbers. This allows the AM optimizer to easily prune instructions.
|
||||
class ZInstI : public ZInst {
|
||||
class ZInstI : public ZInst
|
||||
{
|
||||
public:
|
||||
// These constructors can be used directly, but often instead
|
||||
// they'll be generated via the use of Inst-Gen methods.
|
||||
|
@ -142,10 +145,7 @@ public:
|
|||
op_type = OP_X;
|
||||
}
|
||||
|
||||
ZInstI(ZOp _op, int _v1) : ZInst(_op, OP_V)
|
||||
{
|
||||
v1 = _v1;
|
||||
}
|
||||
ZInstI(ZOp _op, int _v1) : ZInst(_op, OP_V) { v1 = _v1; }
|
||||
|
||||
ZInstI(ZOp _op, int _v1, int _v2) : ZInst(_op, OP_VV)
|
||||
{
|
||||
|
@ -160,8 +160,7 @@ public:
|
|||
v3 = _v3;
|
||||
}
|
||||
|
||||
ZInstI(ZOp _op, int _v1, int _v2, int _v3, int _v4)
|
||||
: ZInst(_op, OP_VVVV)
|
||||
ZInstI(ZOp _op, int _v1, int _v2, int _v3, int _v4) : ZInst(_op, OP_VVVV)
|
||||
{
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
|
@ -169,10 +168,7 @@ public:
|
|||
v4 = _v4;
|
||||
}
|
||||
|
||||
ZInstI(ZOp _op, const ConstExpr* ce) : ZInst(_op, OP_C)
|
||||
{
|
||||
InitConst(ce);
|
||||
}
|
||||
ZInstI(ZOp _op, const ConstExpr* ce) : ZInst(_op, OP_C) { InitConst(ce); }
|
||||
|
||||
ZInstI(ZOp _op, int _v1, const ConstExpr* ce) : ZInst(_op, OP_VC)
|
||||
{
|
||||
|
@ -180,16 +176,14 @@ public:
|
|||
InitConst(ce);
|
||||
}
|
||||
|
||||
ZInstI(ZOp _op, int _v1, int _v2, const ConstExpr* ce)
|
||||
: ZInst(_op, OP_VVC)
|
||||
ZInstI(ZOp _op, int _v1, int _v2, const ConstExpr* ce) : ZInst(_op, OP_VVC)
|
||||
{
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
InitConst(ce);
|
||||
}
|
||||
|
||||
ZInstI(ZOp _op, int _v1, int _v2, int _v3, const ConstExpr* ce)
|
||||
: ZInst(_op, OP_VVVC)
|
||||
ZInstI(ZOp _op, int _v1, int _v2, int _v3, const ConstExpr* ce) : ZInst(_op, OP_VVVC)
|
||||
{
|
||||
v1 = _v1;
|
||||
v2 = _v2;
|
||||
|
@ -206,8 +200,7 @@ public:
|
|||
// Note that this is *not* an override of the base class's VName
|
||||
// but instead a method with similar functionality but somewhat
|
||||
// different behavior (namely, being cognizant of frame_ids).
|
||||
std::string VName(int n, const FrameMap* frame_ids,
|
||||
const FrameReMap* remappings) const;
|
||||
std::string VName(int n, const FrameMap* frame_ids, const FrameReMap* remappings) const;
|
||||
|
||||
// True if this instruction definitely won't proceed to the one
|
||||
// after it.
|
||||
|
@ -216,7 +209,7 @@ public:
|
|||
// True if this instruction always branches elsewhere. Different
|
||||
// from DoesNotContinue() in that returns & hook breaks do not
|
||||
// continue, but they are not branches.
|
||||
bool IsUnconditionalBranch() const { return op == OP_GOTO_V; }
|
||||
bool IsUnconditionalBranch() const { return op == OP_GOTO_V; }
|
||||
|
||||
// True if this instruction is of the form "v1 = v2".
|
||||
bool IsDirectAssignment() const;
|
||||
|
@ -246,19 +239,16 @@ public:
|
|||
|
||||
// True if the instruction corresponds to some sort of load,
|
||||
// either from the interpreter frame or of a global.
|
||||
bool IsLoad() const
|
||||
{
|
||||
return op_type == OP_VV_FRAME || IsGlobalLoad();
|
||||
}
|
||||
bool IsLoad() const { return op_type == OP_VV_FRAME || IsGlobalLoad(); }
|
||||
|
||||
// True if the instruction corresponds to storing a global.
|
||||
bool IsGlobalStore() const
|
||||
{
|
||||
return op == OP_STORE_GLOBAL_V;
|
||||
}
|
||||
bool IsGlobalStore() const { return op == OP_STORE_GLOBAL_V; }
|
||||
|
||||
void CheckIfManaged(const TypePtr& t)
|
||||
{ if ( ZVal::IsManagedType(t) ) is_managed = true; }
|
||||
{
|
||||
if ( ZVal::IsManagedType(t) )
|
||||
is_managed = true;
|
||||
}
|
||||
|
||||
void SetType(TypePtr _t)
|
||||
{
|
||||
|
@ -283,7 +273,7 @@ public:
|
|||
|
||||
// Branch target, prior to concretizing into PC target.
|
||||
ZInstI* target = nullptr;
|
||||
int target_slot = 0; // which of v1/v2/v3 should hold the target
|
||||
int target_slot = 0; // which of v1/v2/v3 should hold the target
|
||||
|
||||
// The final PC location of the statement. -1 indicates not
|
||||
// yet assigned.
|
||||
|
@ -299,12 +289,13 @@ public:
|
|||
private:
|
||||
// Initialize 'c' from the given ConstExpr.
|
||||
void InitConst(const ConstExpr* ce);
|
||||
};
|
||||
};
|
||||
|
||||
// Auxiliary information, used when the fixed ZInst layout lacks
|
||||
// sufficient expressiveness to represent all of the elements that
|
||||
// an instruction needs.
|
||||
class ZInstAux {
|
||||
class ZInstAux
|
||||
{
|
||||
public:
|
||||
// if n is positive then it gives the size of parallel arrays
|
||||
// tracking slots, constants, and types.
|
||||
|
@ -321,9 +312,9 @@ public:
|
|||
|
||||
~ZInstAux()
|
||||
{
|
||||
delete [] ints;
|
||||
delete [] constants;
|
||||
delete [] types;
|
||||
delete[] ints;
|
||||
delete[] constants;
|
||||
delete[] types;
|
||||
}
|
||||
|
||||
// Returns the i'th element of the parallel arrays as a ValPtr.
|
||||
|
@ -392,7 +383,6 @@ public:
|
|||
types[i] = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Member variables. We could add accessors for manipulating
|
||||
// these (and make the variables private), but for convenience we
|
||||
// make them directly available.
|
||||
|
@ -405,8 +395,8 @@ public:
|
|||
// We track associated types, too, enabling us to use
|
||||
// ZVal::ToVal to convert frame slots or constants to ValPtr's.
|
||||
|
||||
int n; // size of arrays
|
||||
int* slots = nullptr; // either nil or points to ints
|
||||
int n; // size of arrays
|
||||
int* slots = nullptr; // either nil or points to ints
|
||||
int* ints = nullptr;
|
||||
ValPtr* constants = nullptr;
|
||||
TypePtr* types = nullptr;
|
||||
|
@ -435,14 +425,13 @@ public:
|
|||
// iteration.
|
||||
TypePtr value_var_type;
|
||||
|
||||
|
||||
// This is only used to return values stored elsewhere in this
|
||||
// object - it's not set directly.
|
||||
//
|
||||
// If we cared about memory penny-pinching, we could make this
|
||||
// a pointer and only instantiate as needed.
|
||||
ValVec vv;
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a human-readable version of the given ZAM op-code.
|
||||
extern const char* ZOP_name(ZOp op);
|
||||
|
@ -451,14 +440,13 @@ extern const char* ZOP_name(ZOp op);
|
|||
// The third argument governs what to do if the given type has no assignment
|
||||
// flavor. If true, this leads to an assertion failure. If false, and
|
||||
// if there's no flavor for the type, then OP_NOP is returned.
|
||||
extern ZOp AssignmentFlavor(ZOp orig, TypeTag tag, bool strict=true);
|
||||
|
||||
extern ZOp AssignmentFlavor(ZOp orig, TypeTag tag, bool strict = true);
|
||||
|
||||
// The following all use initializations produced by Gen-ZAM.
|
||||
|
||||
// Maps first operands, and then type tags, to operands.
|
||||
extern std::unordered_map<ZOp, std::unordered_map<TypeTag, ZOp>> assignment_flavor;
|
||||
|
||||
|
||||
// Maps flavorful assignments to their non-assignment counterpart.
|
||||
// Used for optimization when we determine that the assigned-to
|
||||
// value is superfluous.
|
||||
|
@ -468,4 +456,4 @@ extern std::unordered_map<ZOp, ZOp> assignmentless_op;
|
|||
// counterpart uses.
|
||||
extern std::unordered_map<ZOp, ZAMOpType> assignmentless_op_type;
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -1,64 +1,89 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/script_opt/ZAM/Support.h"
|
||||
#include "zeek/script_opt/ZAM/ZOp.h"
|
||||
|
||||
#include "zeek/script_opt/ZAM/Support.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
const char* ZOP_name(ZOp op)
|
||||
{
|
||||
switch ( op ) {
|
||||
switch ( op )
|
||||
{
|
||||
#include "zeek/ZAM-OpsNamesDefs.h"
|
||||
case OP_NOP: return "nop";
|
||||
}
|
||||
case OP_NOP:
|
||||
return "nop";
|
||||
}
|
||||
|
||||
return "<error>";
|
||||
}
|
||||
|
||||
static const char* op_type_name(ZAMOpType ot)
|
||||
{
|
||||
switch ( ot ) {
|
||||
case OP_X: return "X";
|
||||
case OP_C: return "C";
|
||||
case OP_V: return "V";
|
||||
case OP_V_I1: return "V_I1";
|
||||
case OP_VC_I1: return "VC_I1";
|
||||
case OP_VC: return "VC";
|
||||
case OP_VV: return "VV";
|
||||
case OP_VV_I2: return "VV_I2";
|
||||
case OP_VV_I1_I2: return "VV_I1_I2";
|
||||
case OP_VV_FRAME: return "VV_FRAME";
|
||||
case OP_VVC: return "VVC";
|
||||
case OP_VVC_I2: return "VVC_I2";
|
||||
case OP_VVV: return "VVV";
|
||||
case OP_VVV_I3: return "VVV_I3";
|
||||
case OP_VVV_I2_I3: return "VVV_I2_I3";
|
||||
case OP_VVVC: return "VVVC";
|
||||
case OP_VVVC_I3: return "VVVC_I3";
|
||||
case OP_VVVC_I2_I3: return "VVVC_I2_I3";
|
||||
case OP_VVVC_I1_I2_I3: return "VVVC_I1_I2_I3";
|
||||
case OP_VVVV: return "VVVV";
|
||||
case OP_VVVV_I4: return "VVVV_I4";
|
||||
case OP_VVVV_I3_I4: return "VVVV_I3_I4";
|
||||
case OP_VVVV_I2_I3_I4: return "VVVV_I2_I3_I4";
|
||||
}
|
||||
switch ( ot )
|
||||
{
|
||||
case OP_X:
|
||||
return "X";
|
||||
case OP_C:
|
||||
return "C";
|
||||
case OP_V:
|
||||
return "V";
|
||||
case OP_V_I1:
|
||||
return "V_I1";
|
||||
case OP_VC_I1:
|
||||
return "VC_I1";
|
||||
case OP_VC:
|
||||
return "VC";
|
||||
case OP_VV:
|
||||
return "VV";
|
||||
case OP_VV_I2:
|
||||
return "VV_I2";
|
||||
case OP_VV_I1_I2:
|
||||
return "VV_I1_I2";
|
||||
case OP_VV_FRAME:
|
||||
return "VV_FRAME";
|
||||
case OP_VVC:
|
||||
return "VVC";
|
||||
case OP_VVC_I2:
|
||||
return "VVC_I2";
|
||||
case OP_VVV:
|
||||
return "VVV";
|
||||
case OP_VVV_I3:
|
||||
return "VVV_I3";
|
||||
case OP_VVV_I2_I3:
|
||||
return "VVV_I2_I3";
|
||||
case OP_VVVC:
|
||||
return "VVVC";
|
||||
case OP_VVVC_I3:
|
||||
return "VVVC_I3";
|
||||
case OP_VVVC_I2_I3:
|
||||
return "VVVC_I2_I3";
|
||||
case OP_VVVC_I1_I2_I3:
|
||||
return "VVVC_I1_I2_I3";
|
||||
case OP_VVVV:
|
||||
return "VVVV";
|
||||
case OP_VVVV_I4:
|
||||
return "VVVV_I4";
|
||||
case OP_VVVV_I3_I4:
|
||||
return "VVVV_I3_I4";
|
||||
case OP_VVVV_I2_I3_I4:
|
||||
return "VVVV_I2_I3_I4";
|
||||
}
|
||||
|
||||
return "<error>";
|
||||
}
|
||||
|
||||
|
||||
ZAMOp1Flavor op1_flavor[] = {
|
||||
#include "zeek/ZAM-Op1FlavorsDefs.h"
|
||||
OP1_INTERNAL, // OP_NOP
|
||||
OP1_INTERNAL, // OP_NOP
|
||||
};
|
||||
|
||||
bool op_side_effects[] = {
|
||||
#include "zeek/ZAM-OpSideEffects.h"
|
||||
false, // OP_NOP
|
||||
false, // OP_NOP
|
||||
};
|
||||
|
||||
|
||||
std::unordered_map<ZOp, std::unordered_map<TypeTag, ZOp>> assignment_flavor;
|
||||
std::unordered_map<ZOp, ZOp> assignmentless_op;
|
||||
std::unordered_map<ZOp, ZAMOpType> assignmentless_op_type;
|
||||
|
@ -77,24 +102,25 @@ ZOp AssignmentFlavor(ZOp orig, TypeTag tag, bool strict)
|
|||
}
|
||||
|
||||
// Map type tag to equivalent, as needed.
|
||||
switch ( tag ) {
|
||||
case TYPE_BOOL:
|
||||
case TYPE_ENUM:
|
||||
tag = TYPE_INT;
|
||||
break;
|
||||
switch ( tag )
|
||||
{
|
||||
case TYPE_BOOL:
|
||||
case TYPE_ENUM:
|
||||
tag = TYPE_INT;
|
||||
break;
|
||||
|
||||
case TYPE_PORT:
|
||||
tag = TYPE_COUNT;
|
||||
break;
|
||||
case TYPE_PORT:
|
||||
tag = TYPE_COUNT;
|
||||
break;
|
||||
|
||||
case TYPE_TIME:
|
||||
case TYPE_INTERVAL:
|
||||
tag = TYPE_DOUBLE;
|
||||
break;
|
||||
case TYPE_TIME:
|
||||
case TYPE_INTERVAL:
|
||||
tag = TYPE_DOUBLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( assignment_flavor.count(orig) == 0 )
|
||||
{
|
||||
|
@ -117,4 +143,4 @@ ZOp AssignmentFlavor(ZOp orig, TypeTag tag, bool strict)
|
|||
return orig_map[tag];
|
||||
}
|
||||
|
||||
} // zeek::detail
|
||||
} // zeek::detail
|
||||
|
|
|
@ -4,14 +4,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace zeek::detail {
|
||||
namespace zeek::detail
|
||||
{
|
||||
|
||||
// Opcodes associated with ZAM instructions.
|
||||
enum ZOp {
|
||||
enum ZOp
|
||||
{
|
||||
#include "zeek/ZAM-OpsDefs.h"
|
||||
OP_NOP,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Possible types of instruction operands in terms of which fields they use.
|
||||
// Used for low-level optimization (so important that they're correct),
|
||||
|
@ -22,8 +23,13 @@ enum ZOp {
|
|||
// I1/I2/I3/I4: the instruction's integer value, used directly (not as a slot)
|
||||
// FRAME: a slot in the (intrepreter) Frame object
|
||||
// X: no operands
|
||||
enum ZAMOpType {
|
||||
OP_X, OP_C, OP_V, OP_V_I1, OP_VC_I1,
|
||||
enum ZAMOpType
|
||||
{
|
||||
OP_X,
|
||||
OP_C,
|
||||
OP_V,
|
||||
OP_V_I1,
|
||||
OP_VC_I1,
|
||||
|
||||
OP_VC,
|
||||
OP_VV,
|
||||
|
@ -46,15 +52,16 @@ enum ZAMOpType {
|
|||
OP_VVVV_I3_I4,
|
||||
OP_VVVV_I2_I3_I4,
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// Possible "flavors" for an operator's first slot.
|
||||
enum ZAMOp1Flavor {
|
||||
OP1_READ, // the slot is read, not modified
|
||||
OP1_WRITE, // the slot is modified, not read - the most common
|
||||
OP1_READ_WRITE, // the slot is both read and then modified, e.g. "++"
|
||||
OP1_INTERNAL, // we're doing some internal manipulation of the slot
|
||||
};
|
||||
enum ZAMOp1Flavor
|
||||
{
|
||||
OP1_READ, // the slot is read, not modified
|
||||
OP1_WRITE, // the slot is modified, not read - the most common
|
||||
OP1_READ_WRITE, // the slot is both read and then modified, e.g. "++"
|
||||
OP1_INTERNAL, // we're doing some internal manipulation of the slot
|
||||
};
|
||||
|
||||
// Maps an operand to its flavor.
|
||||
extern ZAMOp1Flavor op1_flavor[];
|
||||
|
@ -62,4 +69,4 @@ extern ZAMOp1Flavor op1_flavor[];
|
|||
// Maps an operand to whether it has side effects.
|
||||
extern bool op_side_effects[];
|
||||
|
||||
} // namespace zeek::detail
|
||||
} // namespace zeek::detail
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue