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