P4C
The P4 Compiler
Loading...
Searching...
No Matches
staticAssert.h
1/*
2 * Copyright 2022 VMware, Inc.
3 * SPDX-FileCopyrightText: 2022 VMware, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef FRONTENDS_P4_STATICASSERT_H_
9#define FRONTENDS_P4_STATICASSERT_H_
10
11#include "frontends/common/resolveReferences/resolveReferences.h"
12#include "frontends/p4/methodInstance.h"
13#include "frontends/p4/typeChecking/typeChecker.h"
14#include "ir/ir.h"
15
16namespace P4 {
17
18using namespace literals;
19
20const cstring staticAssertMethodName = "static_assert"_cs;
21
26class DoStaticAssert : public Transform, public ResolutionContext {
27 TypeMap *typeMap;
28 bool removeStatement = false;
29 bool isFinal = true;
30
31 public:
32 explicit DoStaticAssert(TypeMap *typeMap, bool isFinal) : typeMap(typeMap), isFinal(isFinal) {
33 CHECK_NULL(typeMap);
34 setName("DoStaticAssert");
35 }
36 const IR::Node *postorder(IR::MethodCallExpression *method) override {
37 MethodInstance *mi = MethodInstance::resolve(method, this, typeMap);
38 if (auto ef = mi->to<ExternFunction>()) {
39 if (ef->method->name == staticAssertMethodName) {
40 auto subst = ef->substitution;
41 auto params = subst.getParametersInOrder();
42 if (!params->moveNext()) {
43 ::P4::warning(ErrorType::WARN_INVALID, "static_assert with no arguments: %1%",
44 method);
45 return method;
46 }
47 auto param = params->getCurrent();
48 CHECK_NULL(param);
49 auto arg = subst.lookup(param);
50 CHECK_NULL(arg);
51 if (auto bl = arg->expression->to<IR::BoolLiteral>()) {
52 if (!bl->value) {
53 std::string_view message = "static_assert failed";
54 if (params->moveNext()) {
55 param = params->getCurrent();
56 CHECK_NULL(param);
57 auto msg = subst.lookup(param);
58 CHECK_NULL(msg);
59 if (const auto *sl = msg->expression->to<IR::StringLiteral>()) {
60 message = sl->value;
61 }
62 }
63 ::P4::error(ErrorType::ERR_EXPECTED, "%1%: %2%", method, message);
64 return method;
65 }
66 if (getContext()->node->is<IR::MethodCallStatement>()) {
67 removeStatement = true;
68 return method;
69 }
70 return new IR::BoolLiteral(method->srcInfo, true);
71 } else if (!isFinal) {
72 return method;
73 } else {
74 ::P4::error(ErrorType::ERR_UNEXPECTED,
75 "Could not evaluate static_assert to a constant: %1%", arg);
76 return method;
77 }
78 }
79 }
80 return method;
81 }
82
83 const IR::Node *postorder(IR::MethodCallStatement *statement) override {
84 if (removeStatement) {
85 removeStatement = false;
86 return nullptr;
87 }
88 return statement;
89 }
90};
91
92class StaticAssert : public PassManager {
93 public:
94 explicit StaticAssert(TypeMap *typeMap, bool isFinal = true) {
95 passes.push_back(new ReadOnlyTypeInference(typeMap));
96 passes.push_back(new DoStaticAssert(typeMap, isFinal));
97 setName("StaticAssert");
98 }
99};
100
101} // namespace P4
102
103#endif /* FRONTENDS_P4_STATICASSERT_H_ */
Definition staticAssert.h:26
Definition methodInstance.h:194
Definition node.h:53
Definition methodInstance.h:56
static MethodInstance * resolve(const IR::MethodCallExpression *mce, const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType=false, const Visitor::Context *ctxt=nullptr, bool incomplete=false)
Definition methodInstance.cpp:27
Definition typeChecker.h:363
Definition visitor.h:442
Definition typeMap.h:32
Definition cstring.h:85
Definition cstring.h:80
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
void warning(const char *format, Args &&...args)
Report a warning with the given message.
Definition lib/error.h:128
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
T * to() noexcept
Definition rtti.h:226