P4C
The P4 Compiler
Loading...
Searching...
No Matches
interpreter.h
1/*
2Copyright 2016 VMware, Inc.
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14*/
15
16#ifndef MIDEND_INTERPRETER_H_
17#define MIDEND_INTERPRETER_H_
18
19#include "frontends/common/resolveReferences/referenceMap.h"
20#include "frontends/p4/coreLibrary.h"
21#include "frontends/p4/typeMap.h"
22#include "ir/ir.h"
23
24// Symbolic P4 program evaluation.
25
26namespace P4 {
27
28class SymbolicValueFactory;
29
30// Base class for all abstract values
31class SymbolicValue : public IHasDbPrint, public ICastable {
32 static unsigned crtid;
33
34 protected:
35 explicit SymbolicValue(const IR::Type *type) : id(crtid++), type(type) {}
36
37 public:
38 const unsigned id;
39 const IR::Type *type;
40 virtual bool isScalar() const = 0;
41 virtual SymbolicValue *clone() const = 0;
42 virtual void setAllUnknown() = 0;
43 virtual void assign(const SymbolicValue *other) = 0;
44 // Merging two symbolic values; values should form a lattice.
45 // Returns 'true' if merging changed the current value.
46 virtual bool merge(const SymbolicValue *other) = 0;
47 virtual bool equals(const SymbolicValue *other) const = 0;
48 // True if some parts of this value are definitely uninitialized
49 virtual bool hasUninitializedParts() const = 0;
50
51 DECLARE_TYPEINFO(SymbolicValue);
52};
53
54// Creates values from type declarations
56 const TypeMap *typeMap;
57
58 public:
59 explicit SymbolicValueFactory(const TypeMap *typeMap) : typeMap(typeMap) {
60 CHECK_NULL(typeMap);
61 }
62 SymbolicValue *create(const IR::Type *type, bool uninitialized) const;
63 // True if type has a fixed width, i.e., it does not contain a Varbit.
64 bool isFixedWidth(const IR::Type *type) const;
65 // If type has a fixed width return width in bits.
66 // varbit types are assumed to have width 0 when counting.
67 // Does not count the size for the "valid" bit for headers.
68 unsigned getWidth(const IR::Type *type) const;
69};
70
71class ValueMap final : public IHasDbPrint {
72 public:
73 std::map<const IR::IDeclaration *, SymbolicValue *> map;
74 ValueMap *clone() const {
75 auto result = new ValueMap();
76 for (auto v : map) result->map.emplace(v.first, v.second->clone());
77 return result;
78 }
79 ValueMap *filter(std::function<bool(const IR::IDeclaration *, const SymbolicValue *)> filter) {
80 auto result = new ValueMap();
81 for (auto v : map)
82 if (filter(v.first, v.second)) result->map.emplace(v.first, v.second);
83 return result;
84 }
85 void set(const IR::IDeclaration *left, SymbolicValue *right) {
86 CHECK_NULL(left);
87 CHECK_NULL(right);
88 map[left] = right;
89 }
90 SymbolicValue *get(const IR::IDeclaration *left) const {
91 CHECK_NULL(left);
92 return ::P4::get(map, left);
93 }
94
95 void dbprint(std::ostream &out) const {
96 bool first = true;
97 for (auto f : map) {
98 if (!first) out << std::endl;
99 out << f.first << "=>" << f.second;
100 first = false;
101 }
102 }
103 bool merge(const ValueMap *other) {
104 bool change = false;
105 BUG_CHECK(map.size() == other->map.size(), "Merging incompatible maps?");
106 for (auto d : map) {
107 auto v = other->get(d.first);
108 CHECK_NULL(v);
109 change = change || d.second->merge(v);
110 }
111 return change;
112 }
113 bool equals(const ValueMap *other) const {
114 BUG_CHECK(map.size() == other->map.size(), "Incompatible maps compared");
115 for (auto v : map) {
116 auto ov = other->get(v.first);
117 CHECK_NULL(ov);
118 if (!v.second->equals(ov)) return false;
119 }
120 return true;
121 }
122};
123
125 ReferenceMap *refMap;
126 TypeMap *typeMap; // updated if constant folding happens
127 ValueMap *valueMap;
128 const SymbolicValueFactory *factory;
129 bool evaluatingLeftValue = false;
130
131 std::map<const IR::Expression *, SymbolicValue *> value;
132
133 SymbolicValue *set(const IR::Expression *expression, SymbolicValue *v) {
134 LOG2("Symbolic evaluation of " << expression << " is " << v);
135 value.emplace(expression, v);
136 return v;
137 }
138
139 void postorder(const IR::Constant *expression) override;
140 void postorder(const IR::BoolLiteral *expression) override;
141 void postorder(const IR::StringLiteral *expression) override;
142 void postorder(const IR::Operation_Ternary *expression) override;
143 void postorder(const IR::Operation_Binary *expression) override;
144 void postorder(const IR::Operation_Relation *expression) override;
145 void postorder(const IR::Operation_Unary *expression) override;
146 void postorder(const IR::PathExpression *expression) override;
147 void postorder(const IR::Member *expression) override;
148 bool preorder(const IR::ArrayIndex *expression) override;
149 void postorder(const IR::ArrayIndex *expression) override;
150 void postorder(const IR::ListExpression *expression) override;
151 void postorder(const IR::StructExpression *expression) override;
152 void postorder(const IR::MethodCallExpression *expression) override;
153 void checkResult(const IR::Expression *expression, const IR::Expression *result);
154 void setNonConstant(const IR::Expression *expression);
155
156 public:
157 ExpressionEvaluator(ReferenceMap *refMap, TypeMap *typeMap, ValueMap *valueMap)
158 : refMap(refMap), typeMap(typeMap), valueMap(valueMap) {
159 CHECK_NULL(refMap);
160 CHECK_NULL(typeMap);
161 CHECK_NULL(valueMap);
162 factory = new SymbolicValueFactory(typeMap);
163 }
164
165 // May mutate the valueMap, when evaluating expression with side-effects.
166 // If leftValue is true we are returning a leftValue.
167 SymbolicValue *evaluate(const IR::Expression *expression, bool leftValue);
168
169 SymbolicValue *get(const IR::Expression *expression) const {
170 auto r = ::P4::get(value, expression);
171 BUG_CHECK(r != nullptr, "no evaluation for %1%", expression);
172 return r;
173 }
174};
175
177
178// produced when evaluation gives a static error
180 public:
181 const IR::Node *errorPosition;
182 explicit SymbolicError(const IR::Node *errorPosition)
183 : SymbolicValue(nullptr), errorPosition(errorPosition) {}
184 void setAllUnknown() override {}
185 void assign(const SymbolicValue *) override {}
186 bool isScalar() const override { return true; }
187 bool merge(const SymbolicValue *) override {
188 BUG("%1%: cannot merge errors", this);
189 return false;
190 }
191 virtual cstring message() const = 0;
192 bool hasUninitializedParts() const override { return false; }
193
194 DECLARE_TYPEINFO(SymbolicError, SymbolicValue);
195};
196
198 public:
199 const P4::StandardExceptions exc;
200 SymbolicException(const IR::Node *errorPosition, P4::StandardExceptions exc)
201 : SymbolicError(errorPosition), exc(exc) {}
202 SymbolicValue *clone() const override { return new SymbolicException(errorPosition, exc); }
203 void dbprint(std::ostream &out) const override { out << "Exception: " << exc; }
204 cstring message() const override {
205 std::stringstream str;
206 str << exc;
207 return str.str();
208 }
209 bool equals(const SymbolicValue *other) const override;
210
211 DECLARE_TYPEINFO(SymbolicException, SymbolicError);
212};
213
215 public:
216 const std::string msg;
217 SymbolicStaticError(const IR::Node *errorPosition, std::string_view message)
218 : SymbolicError(errorPosition), msg(message) {}
219 SymbolicValue *clone() const override { return new SymbolicStaticError(errorPosition, msg); }
220 void dbprint(std::ostream &out) const override { out << "Error: " << msg; }
221 cstring message() const override { return msg; }
222 bool equals(const SymbolicValue *other) const override;
223
224 DECLARE_TYPEINFO(SymbolicStaticError, SymbolicError);
225};
226
228 public:
229 enum class ValueState {
230 Uninitialized,
231 NotConstant, // we cannot tell statically
232 Constant // compile-time constant
233 };
234
235 protected:
236 ScalarValue(ScalarValue::ValueState state, const IR::Type *type)
237 : SymbolicValue(type), state(state) {}
238
239 public:
240 ValueState state;
241 bool isUninitialized() const { return state == ValueState::Uninitialized; }
242 bool isUnknown() const { return state == ValueState::NotConstant; }
243 bool isKnown() const { return state == ValueState::Constant; }
244 bool isScalar() const override { return true; }
245 void dbprint(std::ostream &out) const override {
246 if (isUninitialized())
247 out << "uninitialized";
248 else if (isUnknown())
249 out << "unknown";
250 }
251 static ValueState init(bool uninit) {
252 return uninit ? ValueState::Uninitialized : ValueState::NotConstant;
253 }
254 void setAllUnknown() override { state = ScalarValue::ValueState::NotConstant; }
255 ValueState mergeState(ValueState other) const {
256 if (state == ValueState::Uninitialized && other == ValueState::Uninitialized)
257 return ValueState::Uninitialized;
258 if (state == ValueState::Constant && other == ValueState::Constant)
259 // This may be wrong.
260 return ValueState::Constant;
261 return ValueState::NotConstant;
262 }
263 bool hasUninitializedParts() const override { return state == ValueState::Uninitialized; }
264
265 DECLARE_TYPEINFO(ScalarValue, SymbolicValue);
266};
267
269 SymbolicVoid() : SymbolicValue(IR::Type_Void::get()) {}
270 static SymbolicVoid *instance;
271
272 public:
273 void dbprint(std::ostream &out) const override { out << "void"; }
274 void setAllUnknown() override {}
275 bool isScalar() const override { return false; }
276 void assign(const SymbolicValue *) override { BUG("assign to void"); }
277 static SymbolicVoid *get() { return instance; }
278 SymbolicValue *clone() const override { return instance; }
279 bool merge(const SymbolicValue *other) override {
280 BUG_CHECK(other->is<SymbolicVoid>(), "%1%: expected void", other);
281 return false;
282 }
283 bool equals(const SymbolicValue *other) const override { return other == instance; }
284 bool hasUninitializedParts() const override { return false; }
285
286 DECLARE_TYPEINFO(SymbolicVoid, SymbolicValue);
287};
288
289class SymbolicBool final : public ScalarValue {
290 public:
291 bool value;
292 explicit SymbolicBool(ScalarValue::ValueState state)
293 : ScalarValue(state, IR::Type_Boolean::get()), value(false) {}
295 : ScalarValue(ScalarValue::ValueState::Uninitialized, IR::Type_Boolean::get()),
296 value(false) {}
297 explicit SymbolicBool(const IR::BoolLiteral *constant)
298 : ScalarValue(ScalarValue::ValueState::Constant, IR::Type_Boolean::get()),
299 value(constant->value) {}
300 SymbolicBool(const SymbolicBool &other) = default;
301 explicit SymbolicBool(bool value)
302 : ScalarValue(ScalarValue::ValueState::Constant, IR::Type_Boolean::get()), value(value) {}
303 void dbprint(std::ostream &out) const override {
304 ScalarValue::dbprint(out);
305 if (!isKnown()) return;
306 out << (value ? "true" : "false");
307 }
308 SymbolicValue *clone() const override {
309 auto result = new SymbolicBool();
310 result->state = state;
311 result->value = value;
312 return result;
313 }
314 void assign(const SymbolicValue *other) override;
315 bool merge(const SymbolicValue *other) override;
316 bool equals(const SymbolicValue *other) const override;
317
318 DECLARE_TYPEINFO(SymbolicBool, ScalarValue);
319};
320
321class SymbolicInteger final : public ScalarValue {
322 public:
323 const IR::Constant *constant;
324 explicit SymbolicInteger(const IR::Type_Bits *type)
325 : ScalarValue(ScalarValue::ValueState::Uninitialized, type), constant(nullptr) {}
326 SymbolicInteger(ScalarValue::ValueState state, const IR::Type_Bits *type)
327 : ScalarValue(state, type), constant(nullptr) {}
328 explicit SymbolicInteger(const IR::Constant *constant)
329 : ScalarValue(ScalarValue::ValueState::Constant, constant->type), constant(constant) {
330 CHECK_NULL(constant);
331 }
332 SymbolicInteger(const SymbolicInteger &other) = default;
333 void dbprint(std::ostream &out) const override {
334 ScalarValue::dbprint(out);
335 if (isKnown()) out << constant->value;
336 }
337 SymbolicValue *clone() const override {
338 auto result = new SymbolicInteger(type->to<IR::Type_Bits>());
339 result->state = state;
340 result->constant = constant;
341 return result;
342 }
343 void assign(const SymbolicValue *other) override;
344 bool merge(const SymbolicValue *other) override;
345 bool equals(const SymbolicValue *other) const override;
346
347 DECLARE_TYPEINFO(SymbolicInteger, ScalarValue);
348};
349
350class SymbolicString final : public ScalarValue {
351 public:
352 const IR::StringLiteral *string;
353 explicit SymbolicString(const IR::Type_String *type)
354 : ScalarValue(ScalarValue::ValueState::Uninitialized, type), string(nullptr) {}
355 SymbolicString(ScalarValue::ValueState state, const IR::Type_String *type)
356 : ScalarValue(state, type), string(nullptr) {}
357 explicit SymbolicString(const IR::StringLiteral *string)
358 : ScalarValue(ScalarValue::ValueState::Constant, string->type), string(string) {
359 CHECK_NULL(string);
360 }
361 SymbolicString(const SymbolicString &other) = default;
362 void dbprint(std::ostream &out) const override {
363 ScalarValue::dbprint(out);
364 if (isKnown()) out << string->value;
365 }
366 SymbolicValue *clone() const override {
367 auto result = new SymbolicString(type->to<IR::Type_String>());
368 result->state = state;
369 result->string = string;
370 return result;
371 }
372 void assign(const SymbolicValue *other) override;
373 bool merge(const SymbolicValue *other) override;
374 bool equals(const SymbolicValue *other) const override;
375
376 DECLARE_TYPEINFO(SymbolicString, ScalarValue);
377};
378
379class SymbolicVarbit final : public ScalarValue {
380 public:
381 explicit SymbolicVarbit(const IR::Type_Varbits *type)
382 : ScalarValue(ScalarValue::ValueState::Uninitialized, type) {}
383 SymbolicVarbit(ScalarValue::ValueState state, const IR::Type_Varbits *type)
384 : ScalarValue(state, type) {}
385 SymbolicVarbit(const SymbolicVarbit &other) = default;
386 void dbprint(std::ostream &out) const override { ScalarValue::dbprint(out); }
387 SymbolicValue *clone() const override {
388 return new SymbolicVarbit(state, type->to<IR::Type_Varbits>());
389 }
390 void assign(const SymbolicValue *other) override;
391 bool merge(const SymbolicValue *other) override;
392 bool equals(const SymbolicValue *other) const override;
393
394 DECLARE_TYPEINFO(SymbolicVarbit, ScalarValue);
395};
396
397// represents enum, error, and match_kind
398class SymbolicEnum final : public ScalarValue {
399 IR::ID value;
400
401 public:
402 explicit SymbolicEnum(const IR::Type *type)
403 : ScalarValue(ScalarValue::ValueState::Uninitialized, type) {}
404 SymbolicEnum(ScalarValue::ValueState state, const IR::Type *type, const IR::ID value)
405 : ScalarValue(state, type), value(value) {}
406 SymbolicEnum(const IR::Type *type, const IR::ID value)
407 : ScalarValue(ScalarValue::ValueState::Constant, type), value(value) {}
408 SymbolicEnum(const SymbolicEnum &other) = default;
409 void dbprint(std::ostream &out) const override {
410 ScalarValue::dbprint(out);
411 if (isKnown()) out << value;
412 }
413 SymbolicValue *clone() const override { return new SymbolicEnum(state, type, value); }
414 void assign(const SymbolicValue *other) override;
415 bool merge(const SymbolicValue *other) override;
416 bool equals(const SymbolicValue *other) const override;
417
418 DECLARE_TYPEINFO(SymbolicEnum, ScalarValue);
419};
420
422 public:
423 explicit SymbolicStruct(const IR::Type_StructLike *type) : SymbolicValue(type) {
424 CHECK_NULL(type);
425 }
426 std::map<cstring, SymbolicValue *> fieldValue;
427 SymbolicStruct(const IR::Type_StructLike *type, bool uninitialized,
428 const SymbolicValueFactory *factory);
429 virtual SymbolicValue *get(const IR::Node *, cstring field) const {
430 auto r = ::P4::get(fieldValue, field);
431 CHECK_NULL(r);
432 return r;
433 }
434 void set(cstring field, SymbolicValue *value) {
435 CHECK_NULL(value);
436 fieldValue[field] = value;
437 }
438 void dbprint(std::ostream &out) const override;
439 bool isScalar() const override { return false; }
440 SymbolicValue *clone() const override;
441 void setAllUnknown() override;
442 void assign(const SymbolicValue *other) override;
443 bool merge(const SymbolicValue *other) override;
444 bool equals(const SymbolicValue *other) const override;
445 bool hasUninitializedParts() const override;
446
447 DECLARE_TYPEINFO(SymbolicStruct, SymbolicValue);
448};
449
451 public:
452 explicit SymbolicHeader(const IR::Type_Header *type) : SymbolicStruct(type) {}
453 SymbolicBool *valid = nullptr;
454 SymbolicHeader(const IR::Type_Header *type, bool uninitialized,
455 const SymbolicValueFactory *factory);
456 virtual void setValid(bool v);
457 SymbolicValue *clone() const override;
458 SymbolicValue *get(const IR::Node *node, cstring field) const override;
459 void setAllUnknown() override;
460 void assign(const SymbolicValue *other) override;
461 void dbprint(std::ostream &out) const override;
462 bool merge(const SymbolicValue *other) override;
463 bool equals(const SymbolicValue *other) const override;
464
465 DECLARE_TYPEINFO(SymbolicHeader, SymbolicStruct);
466};
467
469 public:
470 explicit SymbolicHeaderUnion(const IR::Type_HeaderUnion *type) : SymbolicStruct(type) {}
471 SymbolicHeaderUnion(const IR::Type_HeaderUnion *type, bool uninitialized,
472 const SymbolicValueFactory *factory);
473 SymbolicBool *isValid() const;
474 SymbolicValue *clone() const override;
475 SymbolicValue *get(const IR::Node *node, cstring field) const override;
476 void setAllUnknown() override;
477 void assign(const SymbolicValue *other) override;
478 void dbprint(std::ostream &out) const override;
479 bool merge(const SymbolicValue *other) override;
480 bool equals(const SymbolicValue *other) const override;
481
482 DECLARE_TYPEINFO(SymbolicHeaderUnion, SymbolicStruct);
483};
484
485class SymbolicArray final : public SymbolicValue {
486 std::vector<SymbolicStruct *> values;
487 friend class AnyElement;
488 explicit SymbolicArray(const IR::Type_Stack *type)
489 : SymbolicValue(type),
490 size(type->getSize()),
491 elemType(type->elementType->to<IR::Type_Header>()) {}
492
493 public:
494 const size_t size;
495 const IR::Type_Header *elemType;
496 SymbolicArray(const IR::Type_Stack *stack, bool uninitialized,
497 const SymbolicValueFactory *factory);
498 SymbolicValue *get(const IR::Node *node, size_t index) const {
499 if (index >= values.size())
500 return new SymbolicException(node, P4::StandardExceptions::StackOutOfBounds);
501 return values.at(index);
502 }
503 void shift(int amount); // negative = shift left
504 void set(size_t index, SymbolicHeader *value) {
505 CHECK_NULL(value);
506 values[index] = value;
507 }
508 void dbprint(std::ostream &out) const override;
509 SymbolicValue *clone() const override;
510 SymbolicValue *next(const IR::Node *node);
511 SymbolicValue *last(const IR::Node *node);
512 SymbolicValue *lastIndex(const IR::Node *node);
513 bool isScalar() const override { return false; }
514 void setAllUnknown() override;
515 void assign(const SymbolicValue *other) override;
516 bool merge(const SymbolicValue *other) override;
517 bool equals(const SymbolicValue *other) const override;
518 bool hasUninitializedParts() const override;
519
520 DECLARE_TYPEINFO(SymbolicArray, SymbolicValue);
521};
522
523// Represents any element from a stack
524class AnyElement final : public SymbolicHeader {
525 SymbolicArray *parent;
526
527 public:
528 explicit AnyElement(SymbolicArray *parent) : SymbolicHeader(parent->elemType), parent(parent) {
529 CHECK_NULL(parent);
530 valid = new SymbolicBool();
531 }
532 SymbolicValue *clone() const override {
533 auto result = new AnyElement(parent);
534 return result;
535 }
536 void setAllUnknown() override { parent->setAllUnknown(); }
537 void assign(const SymbolicValue *) override { parent->setAllUnknown(); }
538 void dbprint(std::ostream &out) const override { out << "Any element of " << parent; }
539 void setValid(bool) override { parent->setAllUnknown(); }
540 bool merge(const SymbolicValue *other) override;
541 bool equals(const SymbolicValue *other) const override;
542 SymbolicValue *collapse() const;
543 bool hasUninitializedParts() const override { BUG("Should not be called"); }
544
545 DECLARE_TYPEINFO(AnyElement, SymbolicHeader);
546};
547
548class SymbolicTuple final : public SymbolicValue {
549 std::vector<SymbolicValue *> values;
550
551 public:
552 explicit SymbolicTuple(const IR::Type_Tuple *type) : SymbolicValue(type) {}
553 SymbolicTuple(const IR::Type_Tuple *type, bool uninitialized,
554 const SymbolicValueFactory *factory);
555 SymbolicValue *get(size_t index) const { return values.at(index); }
556 void dbprint(std::ostream &out) const override {
557 bool first = true;
558 for (auto f : values) {
559 if (!first) out << ", ";
560 out << f;
561 first = false;
562 }
563 }
564 SymbolicValue *clone() const override;
565 bool isScalar() const override { return false; }
566 void setAllUnknown() override;
567 void assign(const SymbolicValue *) override { BUG("%1%: tuples are read-only", this); }
568 void add(SymbolicValue *value) { values.push_back(value); }
569 bool merge(const SymbolicValue *other) override;
570 bool equals(const SymbolicValue *other) const override;
571 bool hasUninitializedParts() const override;
572
573 DECLARE_TYPEINFO(SymbolicTuple, SymbolicValue);
574};
575
576// Some extern value of an unknown type
578 public:
579 explicit SymbolicExtern(const IR::Type_Extern *type) : SymbolicValue(type) { CHECK_NULL(type); }
580 void dbprint(std::ostream &out) const override { out << "instance of " << type; }
581 SymbolicValue *clone() const override {
582 return new SymbolicExtern(type->to<IR::Type_Extern>());
583 }
584 bool isScalar() const override { return false; }
585 void setAllUnknown() override { BUG("%1%: extern is read-only", this); }
586 void assign(const SymbolicValue *) override { BUG("%1%: extern is read-only", this); }
587 bool merge(const SymbolicValue *) override { return false; }
588 bool equals(const SymbolicValue *other) const override;
589 bool hasUninitializedParts() const override { return false; }
590
591 DECLARE_TYPEINFO(SymbolicExtern, SymbolicValue);
592};
593
594// Models an extern of type packet_in
595class SymbolicPacketIn final : public SymbolicExtern {
596 // Minimum offset in the stream.
597 // Extracting to a varbit may advance the stream offset
598 // by an unknown quantity. Varbits are counted as 0
599 // (as per SymbolicValueFactory::getWidth).
600 unsigned minimumStreamOffset;
601 // If true the minimumStreamOffset is a conservative
602 // approximation.
603 bool conservative;
604
605 public:
606 explicit SymbolicPacketIn(const IR::Type_Extern *type)
607 : SymbolicExtern(type), minimumStreamOffset(0), conservative(false) {}
608 void dbprint(std::ostream &out) const override {
609 out << "packet_in; offset =" << minimumStreamOffset
610 << (conservative ? " (conservative)" : "");
611 }
612 SymbolicValue *clone() const override {
613 auto result = new SymbolicPacketIn(type->to<IR::Type_Extern>());
614 result->minimumStreamOffset = minimumStreamOffset;
615 result->conservative = conservative;
616 return result;
617 }
618 void setConservative() { conservative = true; }
619 bool isConservative() const { return conservative; }
620 void advance(unsigned width) { minimumStreamOffset += width; }
621 bool merge(const SymbolicValue *other) override;
622 bool equals(const SymbolicValue *other) const override;
623
624 DECLARE_TYPEINFO(SymbolicPacketIn, SymbolicExtern);
625};
626
627} // namespace P4
628
629#endif /* MIDEND_INTERPRETER_H_ */
Definition interpreter.h:524
Definition interpreter.h:124
Definition castable.h:36
Definition stringify.h:33
The Declaration interface, representing objects with names.
Definition declaration.h:26
Definition node.h:94
Definition visitor.h:400
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition interpreter.h:227
Definition interpreter.h:485
Definition interpreter.h:289
Definition interpreter.h:398
Definition interpreter.h:179
Definition interpreter.h:197
Definition interpreter.h:577
Definition interpreter.h:450
Definition interpreter.h:468
Definition interpreter.h:321
Definition interpreter.h:595
Definition interpreter.h:214
Definition interpreter.h:350
Definition interpreter.h:421
Definition interpreter.h:548
Definition interpreter.h:55
Definition interpreter.h:31
Definition interpreter.h:379
Definition interpreter.h:268
Definition typeMap.h:41
Definition interpreter.h:71
Definition cstring.h:85
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition id.h:28
bool is() const noexcept
Definition rtti.h:216