P4C
The P4 Compiler
Loading...
Searching...
No Matches
sharedActionSelectorCheck.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
18#define BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_
19
20#include <algorithm>
21
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "frontends/p4/coreLibrary.h"
24#include "frontends/p4/frontend.h"
25#include "frontends/p4/typeChecking/typeChecker.h"
26#include "frontends/p4/typeMap.h"
27#include "helpers.h"
28#include "ir/ir.h"
29#include "lib/error.h"
30#include "lib/json.h"
31
32namespace BMV2 {
33
34using SelectorInput = std::vector<const IR::Expression *>;
35
40template <Standard::Arch arch>
43 P4::ReferenceMap *refMap;
44 P4::TypeMap *typeMap;
45
46 static bool checkSameKeyExpr(const IR::Expression *expr0, const IR::Expression *expr1) {
47 if (expr0->node_type_name() != expr1->node_type_name()) return false;
48 if (auto pe0 = expr0->to<IR::PathExpression>()) {
49 auto pe1 = expr1->to<IR::PathExpression>();
50 return pe0->path->name == pe1->path->name && pe0->path->absolute == pe1->path->absolute;
51 } else if (auto mem0 = expr0->to<IR::Member>()) {
52 auto mem1 = expr1->to<IR::Member>();
53 return checkSameKeyExpr(mem0->expr, mem1->expr) && mem0->member == mem1->member;
54 } else if (auto l0 = expr0->to<IR::Literal>()) {
55 auto l1 = expr1->to<IR::Literal>();
56 return *l0 == *l1;
57 } else if (auto ai0 = expr0->to<IR::ArrayIndex>()) {
58 auto ai1 = expr1->to<IR::ArrayIndex>();
59 return checkSameKeyExpr(ai0->left, ai1->left) &&
60 checkSameKeyExpr(ai0->right, ai1->right);
61 }
62 return false;
63 }
64
65 public:
66 explicit SharedActionSelectorCheck(BMV2::ConversionContext *ctxt) : ctxt(ctxt) {
67 refMap = ctxt->refMap;
68 typeMap = ctxt->typeMap;
69 }
70
71 bool preorder(const IR::P4Table *table) override {
72 auto implementation = table->properties->getProperty("implementation");
73 if (implementation == nullptr) return false;
74 if (!implementation->value->is<IR::ExpressionValue>()) {
75 ::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property",
76 implementation);
77 return false;
78 }
79 auto propv = implementation->value->to<IR::ExpressionValue>();
80 if (!propv->expression->is<IR::PathExpression>()) return false;
81 auto pathe = propv->expression->to<IR::PathExpression>();
82 auto decl = refMap->getDeclaration(pathe->path, true);
83 if (!decl->is<IR::Declaration_Instance>()) {
84 ::error(ErrorType::ERR_EXPECTED, "%1%: expected a reference to an instance", pathe);
85 return false;
86 }
87 auto dcltype = typeMap->getType(pathe, true);
88 if (!dcltype->is<IR::Type_Extern>()) {
89 ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation", dcltype);
90 return false;
91 }
92 auto type_extern_name = dcltype->to<IR::Type_Extern>()->name;
93 auto actionSelectorName = Standard::ActionSelectorTraits<arch>::typeName();
94 if (type_extern_name != actionSelectorName) return false;
95
96 auto key = table->getKey();
97 SelectorInput input;
98 for (auto ke : key->keyElements) {
99 auto mt = refMap->getDeclaration(ke->matchType->path, true)->to<IR::Declaration_ID>();
100 BUG_CHECK(mt != nullptr, "%1%: could not find declaration", ke->matchType);
101 if (mt->name.name != BMV2::MatchImplementation::selectorMatchTypeName) continue;
102 input.push_back(ke->expression);
103 }
104 auto decl_instance = decl->to<IR::Declaration_Instance>();
105 auto it = ctxt->selector_input_map.find(decl_instance);
106 if (it == ctxt->selector_input_map.end()) {
107 ctxt->selector_input_map[decl_instance] = input;
108 return false;
109 }
110 // returns true if inputs are the same, false otherwise
111 auto cmp_inputs = [](const SelectorInput &i1, const SelectorInput &i2) {
112 if (i1.size() != i2.size()) return false;
113 return std::equal(i1.begin(), i1.end(), i2.begin(), checkSameKeyExpr);
114 };
115
116 if (!cmp_inputs(it->second, input)) {
117 ::error(ErrorType::ERR_INVALID,
118 "Action selector %1% is used by multiple tables with different selector inputs",
119 decl);
120 }
121
122 return false;
123 }
124};
125
126} // namespace BMV2
127
128#endif /* BACKENDS_BMV2_COMMON_SHAREDACTIONSELECTORCHECK_H_ */
static const cstring selectorMatchTypeName
constant definition for bmv2
Definition helpers.h:41
Definition sharedActionSelectorCheck.h:41
Definition visitor.h:396
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
const IR::IDeclaration * getDeclaration(const IR::Path *path, bool notNull=false) const override
Definition referenceMap.cpp:78
Definition typeMap.h:41
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition action.cpp:21
std::vector< const IR::Expression * > SelectorInput
Definition helpers.h:295
Definition helpers.h:297
P4::ReferenceMap * refMap
context
Definition helpers.h:299
Definition helpers.h:116
T * to() noexcept
Definition rtti.h:226