mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
174 lines
4.5 KiB
C++
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
|