zeek/src/script_opt/ZAM/Vars.cc

174 lines
4.5 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/Desc.h"
#include "zeek/Reporter.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());
}
bool ZAMCompiler::IsCapture(const ID* id) const {
const auto& c = pf->CapturesOffsets();
return c.find(id) != c.end();
}
int ZAMCompiler::CaptureOffset(const ID* id) const {
auto id_offset = pf->CapturesOffsets().find(id);
ASSERT(id_offset != pf->CapturesOffsets().end());
return id_offset->second;
}
void ZAMCompiler::LoadParam(const 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_Vi, 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(const 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_Vg;
else
op = AssignmentFlavor(OP_LOAD_GLOBAL_Vg, 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 = {NewRef{}, const_cast<ID*>(id)};
return AddInst(z, true);
}
const ZAMStmt ZAMCompiler::LoadCapture(const ID* id) {
ZOp op;
if ( ZVal::IsManagedType(id->GetType()) )
op = OP_LOAD_MANAGED_CAPTURE_Vi;
else
op = OP_LOAD_CAPTURE_Vi;
auto slot = RawSlot(id);
ZInstI z(op, slot, CaptureOffset(id));
z.SetType(id->GetType());
z.op_type = OP_VV_I2;
return AddInst(z, true);
}
int ZAMCompiler::AddToFrame(const 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(id);
else if ( IsCapture(id) )
(void)LoadCapture(id);
return slot;
}
int ZAMCompiler::Frame1Slot(const ID* id, ZAMOp1Flavor fl) {
if ( fl == OP1_READ )
return FrameSlot(id);
if ( fl == OP1_INTERNAL )
return RawSlot(id);
ASSERT(fl == OP1_WRITE || fl == OP1_READ_WRITE);
// Important: get the slot *before* tracking non-locals, so we don't
// prematurely generate a Store for the read/write case.
auto slot = fl == OP1_READ_WRITE ? FrameSlot(id) : RawSlot(id);
if ( id->IsGlobal() )
pending_global_store = global_id_to_info[id];
else if ( IsCapture(id) )
pending_capture_store = CaptureOffset(id);
// Make sure we don't think we're storing to both a global and
// a capture.
ASSERT(pending_global_store == -1 || pending_capture_store == -1);
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;
}
} // namespace zeek::detail