// 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)}; 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