Coverage Report

Created: 2025-08-01 06:58

/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