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 SymbolicInteger(const SymbolicInteger &other) = default;
323 void dbprint(std::ostream &out) const override {
324 ScalarValue::dbprint(out);
325 if (isKnown()) out << constant->value;
326 }
327 SymbolicValue *clone() const override {
328 auto result = new SymbolicInteger(type->to<IR::Type_Bits>());
329 result->state = state;
330 result->constant = constant;
331 return result;
332 }
333 void assign(const SymbolicValue *other) override;
334 bool merge(const SymbolicValue *other) override;
335 bool equals(const SymbolicValue *other) const override;
336
337 DECLARE_TYPEINFO(SymbolicInteger, ScalarValue);
338};
339
340class SymbolicString final : public ScalarValue {
341 public:
342 const IR::StringLiteral *string;
343 explicit SymbolicString(const IR::Type_String *type)
344 : ScalarValue(ScalarValue::ValueState::Uninitialized, type), string(nullptr) {}
345 SymbolicString(ScalarValue::ValueState state, const IR::Type_String *type)
346 : ScalarValue(state, type), string(nullptr) {}
347 explicit SymbolicString(const IR::StringLiteral *string)
348 : ScalarValue(ScalarValue::ValueState::Constant, string->type), string(string) {}
349 SymbolicString(const SymbolicString &other) = default;
350 void dbprint(std::ostream &out) const override {
351 ScalarValue::dbprint(out);
352 if (isKnown()) out << string->value;
353 }
354 SymbolicValue *clone() const override {
355 auto result = new SymbolicString(type->to<IR::Type_String>());
356 result->state = state;
357 result->string = string;
358 return result;
359 }
360 void assign(const SymbolicValue *other) override;
361 bool merge(const SymbolicValue *other) override;
362 bool equals(const SymbolicValue *other) const override;
363
364 DECLARE_TYPEINFO(SymbolicString, ScalarValue);
365};
366
367class SymbolicVarbit final : public ScalarValue {
368 public:
369 explicit SymbolicVarbit(const IR::Type_Varbits *type)
370 : ScalarValue(ScalarValue::ValueState::Uninitialized, type) {}
371 SymbolicVarbit(ScalarValue::ValueState state, const IR::Type_Varbits *type)
372 : ScalarValue(state, type) {}
373 SymbolicVarbit(const SymbolicVarbit &other) = default;
374 void dbprint(std::ostream &out) const override { ScalarValue::dbprint(out); }
375 SymbolicValue *clone() const override {
376 return new SymbolicVarbit(state, type->to<IR::Type_Varbits>());
377 }
378 void assign(const SymbolicValue *other) override;
379 bool merge(const SymbolicValue *other) override;
380 bool equals(const SymbolicValue *other) const override;
381
382 DECLARE_TYPEINFO(SymbolicVarbit, ScalarValue);
383};
384
385// represents enum, error, and match_kind
386class SymbolicEnum final : public ScalarValue {
387 IR::ID value;
388
389 public:
390 explicit SymbolicEnum(const IR::Type *type)
391 : ScalarValue(ScalarValue::ValueState::Uninitialized, type) {}
392 SymbolicEnum(ScalarValue::ValueState state, const IR::Type *type, const IR::ID value)
393 : ScalarValue(state, type), value(value) {}
394 SymbolicEnum(const IR::Type *type, const IR::ID value)
395 : ScalarValue(ScalarValue::ValueState::Constant, type), value(value) {}
396 SymbolicEnum(const SymbolicEnum &other) = default;
397 void dbprint(std::ostream &out) const override {
398 ScalarValue::dbprint(out);
399 if (isKnown()) out << value;
400 }
401 SymbolicValue *clone() const override { return new SymbolicEnum(state, type, value); }
402 void assign(const SymbolicValue *other) override;
403 bool merge(const SymbolicValue *other) override;
404 bool equals(const SymbolicValue *other) const override;
405
406 DECLARE_TYPEINFO(SymbolicEnum, ScalarValue);
407};
408
409class SymbolicStruct : public SymbolicValue {
410 public:
411 explicit SymbolicStruct(const IR::Type_StructLike *type) : SymbolicValue(type) {
412 CHECK_NULL(type);
413 }
414 std::map<cstring, SymbolicValue *> fieldValue;
415 SymbolicStruct(const IR::Type_StructLike *type, bool uninitialized,
416 const SymbolicValueFactory *factory);
417 virtual SymbolicValue *get(const IR::Node *, cstring field) const {
418 auto r = ::P4::get(fieldValue, field);
419 CHECK_NULL(r);
420 return r;
421 }
422 void set(cstring field, SymbolicValue *value) {
423 CHECK_NULL(value);
424 fieldValue[field] = value;
425 }
426 void dbprint(std::ostream &out) const override;
427 bool isScalar() const override { return false; }
428 SymbolicValue *clone() const override;
429 void setAllUnknown() override;
430 void assign(const SymbolicValue *other) override;
431 bool merge(const SymbolicValue *other) override;
432 bool equals(const SymbolicValue *other) const override;
433 bool hasUninitializedParts() const override;
434
435 DECLARE_TYPEINFO(SymbolicStruct, SymbolicValue);
436};
437
438class SymbolicHeader : public SymbolicStruct {
439 public:
440 explicit SymbolicHeader(const IR::Type_Header *type) : SymbolicStruct(type) {}
441 SymbolicBool *valid = nullptr;
442 SymbolicHeader(const IR::Type_Header *type, bool uninitialized,
443 const SymbolicValueFactory *factory);
444 virtual void setValid(bool v);
445 SymbolicValue *clone() const override;
446 SymbolicValue *get(const IR::Node *node, cstring field) const override;
447 void setAllUnknown() override;
448 void assign(const SymbolicValue *other) override;
449 void dbprint(std::ostream &out) const override;
450 bool merge(const SymbolicValue *other) override;
451 bool equals(const SymbolicValue *other) const override;
452
453 DECLARE_TYPEINFO(SymbolicHeader, SymbolicStruct);
454};
455
456class SymbolicHeaderUnion : public SymbolicStruct {
457 public:
458 explicit SymbolicHeaderUnion(const IR::Type_HeaderUnion *type) : SymbolicStruct(type) {}
459 SymbolicHeaderUnion(const IR::Type_HeaderUnion *type, bool uninitialized,
460 const SymbolicValueFactory *factory);
461 SymbolicBool *isValid() const;
462 SymbolicValue *clone() const override;
463 SymbolicValue *get(const IR::Node *node, cstring field) const override;
464 void setAllUnknown() override;
465 void assign(const SymbolicValue *other) override;
466 void dbprint(std::ostream &out) const override;
467 bool merge(const SymbolicValue *other) override;
468 bool equals(const SymbolicValue *other) const override;
469
470 DECLARE_TYPEINFO(SymbolicHeaderUnion, SymbolicStruct);
471};
472
473class SymbolicArray final : public SymbolicValue {
474 std::vector<SymbolicValue *> values;
475 friend class AnyElement;
476 explicit SymbolicArray(const IR::Type_Array *type)
477 : SymbolicValue(type),
478 size(type->getSize()),
479 elemType(type->elementType->to<IR::Type_Header>()) {}
480
481 public:
482 const size_t size;
483 const IR::Type_Header *elemType;
484 SymbolicArray(const IR::Type_Array *stack, bool uninitialized,
485 const SymbolicValueFactory *factory);
486 SymbolicValue *get(const IR::Node *node, size_t index) const {
487 if (index >= values.size())
488 return new SymbolicException(node, P4::StandardExceptions::StackOutOfBounds);
489 return values.at(index);
490 }
491 void shift(int amount); // negative = shift left
492 void set(size_t index, SymbolicHeader *value) {
493 CHECK_NULL(value);
494 values[index] = value;
495 }
496 void dbprint(std::ostream &out) const override;
497 SymbolicValue *clone() const override;
498 SymbolicValue *next(const IR::Node *node);
499 SymbolicValue *last(const IR::Node *node);
500 SymbolicValue *lastIndex(const IR::Node *node);
501 bool isScalar() const override { return false; }
502 void setAllUnknown() override;
503 void assign(const SymbolicValue *other) override;
504 bool merge(const SymbolicValue *other) override;
505 bool equals(const SymbolicValue *other) const override;
506 bool hasUninitializedParts() const override;
507
508 DECLARE_TYPEINFO(SymbolicArray, SymbolicValue);
509};
510
511// Represents any element from a stack
512class AnyElement final : public SymbolicHeader {
513 SymbolicArray *parent;
514
515 public:
516 explicit AnyElement(SymbolicArray *parent) : SymbolicHeader(parent->elemType), parent(parent) {
517 valid = new SymbolicBool();
518 }
519 SymbolicValue *clone() const override {
520 auto result = new AnyElement(parent);
521 return result;
522 }
523 void setAllUnknown() override { parent->setAllUnknown(); }
524 void assign(const SymbolicValue *) override { parent->setAllUnknown(); }
525 void dbprint(std::ostream &out) const override { out << "Any element of " << parent; }
526 void setValid(bool) override { parent->setAllUnknown(); }
527 bool merge(const SymbolicValue *other) override;
528 bool equals(const SymbolicValue *other) const override;
529 SymbolicValue *collapse() const;
530 bool hasUninitializedParts() const override { BUG("Should not be called"); }
531
532 DECLARE_TYPEINFO(AnyElement, SymbolicHeader);
533};
534
535class SymbolicTuple final : public SymbolicValue {
536 std::vector<SymbolicValue *> values;
537
538 public:
539 explicit SymbolicTuple(const IR::Type_Tuple *type) : SymbolicValue(type) {}
540 SymbolicTuple(const IR::Type_Tuple *type, bool uninitialized,
541 const SymbolicValueFactory *factory);
542 SymbolicValue *get(size_t index) const { return values.at(index); }
543 void dbprint(std::ostream &out) const override {
544 bool first = true;
545 for (auto f : values) {
546 if (!first) out << ", ";
547 out << f;
548 first = false;
549 }
550 }
551 SymbolicValue *clone() const override;
552 bool isScalar() const override { return false; }
553 void setAllUnknown() override;
554 void assign(const SymbolicValue *) override { BUG("%1%: tuples are read-only", this); }
555 void add(SymbolicValue *value) { values.push_back(value); }
556 bool merge(const SymbolicValue *other) override;
557 bool equals(const SymbolicValue *other) const override;
558 bool hasUninitializedParts() const override;
559
560 DECLARE_TYPEINFO(SymbolicTuple, SymbolicValue);
561};
562
563// Some extern value of an unknown type
564class SymbolicExtern : public SymbolicValue {
565 public:
566 explicit SymbolicExtern(const IR::Type_Extern *type) : SymbolicValue(type) { CHECK_NULL(type); }
567 void dbprint(std::ostream &out) const override { out << "instance of " << type; }
568 SymbolicValue *clone() const override {
569 return new SymbolicExtern(type->to<IR::Type_Extern>());
570 }
571 bool isScalar() const override { return false; }
572 void setAllUnknown() override { BUG("%1%: extern is read-only", this); }
573 void assign(const SymbolicValue *) override { BUG("%1%: extern is read-only", this); }
574 bool merge(const SymbolicValue *) override { return false; }
575 bool equals(const SymbolicValue *other) const override;
576 bool hasUninitializedParts() const override { return false; }
577
578 DECLARE_TYPEINFO(SymbolicExtern, SymbolicValue);
579};
580
581// Models an extern of type packet_in
582class SymbolicPacketIn final : public SymbolicExtern {
583 // Minimum offset in the stream.
584 // Extracting to a varbit may advance the stream offset
585 // by an unknown quantity. Varbits are counted as 0
586 // (as per SymbolicValueFactory::getWidth).
587 unsigned minimumStreamOffset;
588 // If true the minimumStreamOffset is a conservative
589 // approximation.
590 bool conservative;
591
592 public:
593 explicit SymbolicPacketIn(const IR::Type_Extern *type)
594 : SymbolicExtern(type), minimumStreamOffset(0), conservative(false) {}
595 void dbprint(std::ostream &out) const override {
596 out << "packet_in; offset =" << minimumStreamOffset
597 << (conservative ? " (conservative)" : "");
598 }
599 SymbolicValue *clone() const override {
600 auto result = new SymbolicPacketIn(type->to<IR::Type_Extern>());
601 result->minimumStreamOffset = minimumStreamOffset;
602 result->conservative = conservative;
603 return result;
604 }
605 void setConservative() { conservative = true; }
606 bool isConservative() const { return conservative; }
607 void advance(unsigned width) { minimumStreamOffset += width; }
608 bool merge(const SymbolicValue *other) override;
609 bool equals(const SymbolicValue *other) const override;
610
611 DECLARE_TYPEINFO(SymbolicPacketIn, SymbolicExtern);
612};
613
614} // namespace P4
615
616#endif /* MIDEND_INTERPRETER_H_ */
Definition castable.h:27
Definition stringify.h:24
The Declaration interface, representing objects with names.
Definition declaration.h:17
Definition node.h:44
Definition visitor.h:409
Class used to encode maps from paths to declarations.
Definition referenceMap.h:58
Definition interpreter.h:473
Definition interpreter.h:281
Definition interpreter.h:189
Definition interpreter.h:438
Definition interpreter.h:47
Definition interpreter.h:23
Definition typeMap.h:32
Definition interpreter.h:63
Definition cstring.h:76
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
Definition id.h:19
bool is() const noexcept
Definition rtti.h:216