/src/zeek/src/script_opt/ZAM/Vars.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // See the file "COPYING" in the main distribution directory for copyright. |
2 | | |
3 | | // Methods for dealing with variables (both ZAM and script-level). |
4 | | |
5 | | #include "zeek/Desc.h" |
6 | | #include "zeek/Reporter.h" |
7 | | #include "zeek/script_opt/ZAM/Compile.h" |
8 | | |
9 | | namespace zeek::detail { |
10 | | |
11 | 0 | bool ZAMCompiler::IsUnused(const IDPtr& id, const Stmt* where) const { |
12 | 0 | if ( ! ud->HasUsage(where) ) |
13 | 0 | return true; |
14 | | |
15 | 0 | auto usage = ud->GetUsage(where); |
16 | | |
17 | | // "usage" can be nil if due to constant propagation we've prune |
18 | | // all of the uses of the given identifier. |
19 | |
|
20 | 0 | return ! usage || ! usage->HasID(id.get()); |
21 | 0 | } |
22 | | |
23 | 0 | bool ZAMCompiler::IsCapture(const ID* id) const { |
24 | 0 | const auto& c = pf->CapturesOffsets(); |
25 | 0 | return c.find(id) != c.end(); |
26 | 0 | } |
27 | | |
28 | 0 | int ZAMCompiler::CaptureOffset(const ID* id) const { |
29 | 0 | auto id_offset = pf->CapturesOffsets().find(id); |
30 | 0 | ASSERT(id_offset != pf->CapturesOffsets().end()); |
31 | 0 | return id_offset->second; |
32 | 0 | } |
33 | | |
34 | 0 | void ZAMCompiler::LoadParam(const ID* id) { |
35 | 0 | if ( id->IsType() ) |
36 | 0 | reporter->InternalError("don't know how to compile local variable that's a type not a value"); |
37 | |
|
38 | 0 | bool is_any = IsAny(id->GetType()); |
39 | |
|
40 | 0 | ZOp op; |
41 | |
|
42 | 0 | op = AssignmentFlavor(OP_LOAD_VAL_Vi, id->GetType()->Tag()); |
43 | |
|
44 | 0 | int slot = AddToFrame(id); |
45 | |
|
46 | 0 | ZInstI z(op, slot, id->Offset()); |
47 | 0 | z.SetType(id->GetType()); |
48 | 0 | z.op_type = OP_VV_FRAME; |
49 | |
|
50 | 0 | (void)AddInst(z); |
51 | 0 | } |
52 | | |
53 | 0 | const ZAMStmt ZAMCompiler::LoadGlobal(const ID* id) { |
54 | 0 | ZOp op; |
55 | |
|
56 | 0 | if ( id->IsType() ) |
57 | | // Need a special load for these, as they don't fit |
58 | | // with the usual template. |
59 | 0 | op = OP_LOAD_GLOBAL_TYPE_Vg; |
60 | 0 | else |
61 | 0 | op = AssignmentFlavor(OP_LOAD_GLOBAL_Vg, id->GetType()->Tag()); |
62 | |
|
63 | 0 | auto slot = RawSlot(id); |
64 | |
|
65 | 0 | ZInstI z(op, slot, global_id_to_info[id]); |
66 | 0 | z.SetType(id->GetType()); |
67 | 0 | z.op_type = OP_VV_I2; |
68 | | |
69 | | // We use the id_val for reporting used-but-not-set errors. |
70 | 0 | z.aux = new ZInstAux(0); |
71 | 0 | z.aux->id_val = {NewRef{}, const_cast<ID*>(id)}; |
72 | |
|
73 | 0 | return AddInst(z, true); |
74 | 0 | } |
75 | | |
76 | 0 | const ZAMStmt ZAMCompiler::LoadCapture(const ID* id) { |
77 | 0 | ZOp op; |
78 | |
|
79 | 0 | if ( ZVal::IsManagedType(id->GetType()) ) |
80 | 0 | op = OP_LOAD_MANAGED_CAPTURE_Vi; |
81 | 0 | else |
82 | 0 | op = OP_LOAD_CAPTURE_Vi; |
83 | |
|
84 | 0 | auto slot = RawSlot(id); |
85 | |
|
86 | 0 | ZInstI z(op, slot, CaptureOffset(id)); |
87 | 0 | z.SetType(id->GetType()); |
88 | 0 | z.op_type = OP_VV_I2; |
89 | |
|
90 | 0 | return AddInst(z, true); |
91 | 0 | } |
92 | | |
93 | 0 | int ZAMCompiler::AddToFrame(const ID* id) { |
94 | 0 | frame_layout1[id] = frame_sizeI; |
95 | 0 | frame_denizens.push_back(id); |
96 | 0 | return frame_sizeI++; |
97 | 0 | } |
98 | | |
99 | 0 | int ZAMCompiler::FrameSlot(const ID* id) { |
100 | 0 | auto slot = RawSlot(id); |
101 | |
|
102 | 0 | if ( id->IsGlobal() ) |
103 | 0 | (void)LoadGlobal(id); |
104 | | |
105 | 0 | else if ( IsCapture(id) ) |
106 | 0 | (void)LoadCapture(id); |
107 | |
|
108 | 0 | return slot; |
109 | 0 | } |
110 | | |
111 | 0 | int ZAMCompiler::Frame1Slot(const ID* id, ZAMOp1Flavor fl) { |
112 | 0 | if ( fl == OP1_READ ) |
113 | 0 | return FrameSlot(id); |
114 | | |
115 | 0 | if ( fl == OP1_INTERNAL ) |
116 | 0 | return RawSlot(id); |
117 | | |
118 | 0 | ASSERT(fl == OP1_WRITE || fl == OP1_READ_WRITE); |
119 | | |
120 | | // Important: get the slot *before* tracking non-locals, so we don't |
121 | | // prematurely generate a Store for the read/write case. |
122 | 0 | auto slot = fl == OP1_READ_WRITE ? FrameSlot(id) : RawSlot(id); |
123 | |
|
124 | 0 | if ( id->IsGlobal() ) |
125 | 0 | pending_global_store = global_id_to_info[id]; |
126 | | |
127 | 0 | else if ( IsCapture(id) ) |
128 | 0 | pending_capture_store = CaptureOffset(id); |
129 | | |
130 | | // Make sure we don't think we're storing to both a global and |
131 | | // a capture. |
132 | 0 | ASSERT(pending_global_store == -1 || pending_capture_store == -1); |
133 | | |
134 | 0 | return slot; |
135 | 0 | } |
136 | | |
137 | 0 | int ZAMCompiler::RawSlot(const ID* id) { |
138 | 0 | auto id_slot = frame_layout1.find(id); |
139 | |
|
140 | 0 | if ( id_slot == frame_layout1.end() ) |
141 | 0 | reporter->InternalError("ID %s missing from frame layout", id->Name()); |
142 | |
|
143 | 0 | return id_slot->second; |
144 | 0 | } |
145 | | |
146 | 0 | bool ZAMCompiler::HasFrameSlot(const ID* id) const { return frame_layout1.find(id) != frame_layout1.end(); } |
147 | | |
148 | 0 | int ZAMCompiler::NewSlot(bool is_managed) { |
149 | 0 | char buf[8192]; |
150 | 0 | snprintf(buf, sizeof buf, "#internal-%d#", frame_sizeI); |
151 | | |
152 | | // In the following, all that matters is that for managed types |
153 | | // we pick a tag that will be viewed as managed, and vice versa. |
154 | |
|
155 | 0 | auto tag = is_managed ? TYPE_TABLE : TYPE_VOID; |
156 | |
|
157 | 0 | auto internal_reg = new ID(buf, SCOPE_FUNCTION, false); |
158 | 0 | internal_reg->SetType(base_type(tag)); |
159 | |
|
160 | 0 | return AddToFrame(internal_reg); |
161 | 0 | } |
162 | | |
163 | 0 | int ZAMCompiler::TempForConst(const ConstExpr* c) { |
164 | 0 | auto slot = NewSlot(c->GetType()); |
165 | |
|
166 | 0 | auto z = ZInstI(OP_ASSIGN_CONST_VC, slot, c); |
167 | 0 | z.CheckIfManaged(c->GetType()); |
168 | 0 | (void)AddInst(z); |
169 | |
|
170 | 0 | return slot; |
171 | 0 | } |
172 | | |
173 | | } // namespace zeek::detail |