zeek/src/script_opt/ZAM/Vars.cc
2021-09-08 10:23:38 -07:00

160 lines
3.3 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
// Methods for dealing with variables (both ZAM and script-level).
#include "zeek/Reporter.h"
#include "zeek/Desc.h"
#include "zeek/script_opt/ProfileFunc.h"
#include "zeek/script_opt/Reduce.h"
#include "zeek/script_opt/ZAM/Compile.h"
namespace zeek::detail {
bool ZAMCompiler::IsUnused(const IDPtr& id, const Stmt* where) const
{
if ( ! ud->HasUsage(where) )
return true;
auto usage = ud->GetUsage(where);
// "usage" can be nil if due to constant propagation we've prune
// all of the uses of the given identifier.
return ! usage || ! usage->HasID(id.get());
}
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");
bool is_any = IsAny(id->GetType());
ZOp op;
op = AssignmentFlavor(OP_LOAD_VAL_VV, id->GetType()->Tag());
int slot = AddToFrame(id);
ZInstI z(op, slot, id->Offset());
z.SetType(id->GetType());
z.op_type = OP_VV_FRAME;
(void) AddInst(z);
}
const ZAMStmt ZAMCompiler::LoadGlobal(ID* id)
{
ZOp op;
if ( id->IsType() )
// Need a special load for these, as they don't fit
// with the usual template.
op = OP_LOAD_GLOBAL_TYPE_VV;
else
op = AssignmentFlavor(OP_LOAD_GLOBAL_VV, id->GetType()->Tag());
auto slot = RawSlot(id);
ZInstI z(op, slot, global_id_to_info[id]);
z.SetType(id->GetType());
z.op_type = OP_VV_I2;
// We use the id_val for reporting used-but-not-set errors.
z.aux = new ZInstAux(0);
z.aux->id_val = id;
return AddInst(z);
}
int ZAMCompiler::AddToFrame(ID* id)
{
frame_layout1[id] = frame_sizeI;
frame_denizens.push_back(id);
return frame_sizeI++;
}
int ZAMCompiler::FrameSlot(const ID* id)
{
auto slot = RawSlot(id);
if ( id->IsGlobal() )
(void) LoadGlobal(frame_denizens[slot]);
return slot;
}
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;
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_INTERNAL:
break;
}
return slot;
}
int ZAMCompiler::RawSlot(const ID* id)
{
auto id_slot = frame_layout1.find(id);
if ( id_slot == frame_layout1.end() )
reporter->InternalError("ID %s missing from frame layout", id->Name());
return id_slot->second;
}
bool ZAMCompiler::HasFrameSlot(const ID* id) const
{
return frame_layout1.find(id) != frame_layout1.end();
}
int ZAMCompiler::NewSlot(bool is_managed)
{
char buf[8192];
snprintf(buf, sizeof buf, "#internal-%d#", frame_sizeI);
// In the following, all that matters is that for managed types
// we pick a tag that will be viewed as managed, and vice versa.
auto tag = is_managed ? TYPE_TABLE : TYPE_VOID;
auto internal_reg = new ID(buf, SCOPE_FUNCTION, false);
internal_reg->SetType(base_type(tag));
return AddToFrame(internal_reg);
}
int ZAMCompiler::TempForConst(const ConstExpr* c)
{
auto slot = NewSlot(c->GetType());
auto z = ZInstI(OP_ASSIGN_CONST_VC, slot, c);
z.CheckIfManaged(c->GetType());
(void) AddInst(z);
return slot;
}
} // zeek::detail