P4C
The P4 Compiler
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
specializeGenericTypes.h
1/*
2Copyright 2020 VMware, 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 FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_
18#define FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_
19
20#include "frontends/p4/typeChecking/typeChecker.h"
21#include "ir/ir.h"
22
23namespace P4 {
24
26using InsertionSet = absl::flat_hash_set<P4::cstring>;
27
28struct TypeSpecialization : public IHasDbPrint {
32 const IR::Type_Specialized *specialized;
34 const IR::Type_Declaration *declaration;
36 const IR::Type_StructLike *replacement;
44 bool inserted = false;
45
46 TypeSpecialization(cstring name, const IR::Type_Specialized *specialized,
47 const IR::Type_Declaration *decl, const InsertionSet &insertion,
48 const IR::Vector<IR::Type> *argTypes)
49 : name(name),
51 declaration(decl),
52 replacement(nullptr),
54 argumentTypes(argTypes) {
55 CHECK_NULL(specialized);
56 CHECK_NULL(decl);
57 CHECK_NULL(argTypes);
58 }
59 void dbprint(std::ostream &out) const override {
60 out << "Specializing:" << dbp(specialized) << " from " << dbp(declaration) << " as "
61 << dbp(replacement) << " inserted at ";
62 format_container(out, insertion, '(', ')');
63 }
64};
65
75
77 std::string name() const;
78
84 bool operator<(const SpecSignature &other) const {
85 // Using pointer comparison to speed up baseType comparation as we don't care about what
86 // that order is. Note that for pointers we have to use `std::less` to make the comparison
87 // defined for pointers into different objects.
88 return std::less<>()(std::forward_as_tuple(baseType.c_str(), arguments),
89 std::forward_as_tuple(other.baseType.c_str(), other.arguments));
90 }
91
94 static std::optional<SpecSignature> get(const IR::Type_Specialized *spec);
95};
96
97std::string toString(const SpecSignature &);
98
100 TypeMap *typeMap;
102
103 void add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl,
104 NameGenerator *nameGen);
105 const TypeSpecialization *get(const IR::Type_Specialized *t) const;
106 TypeSpecialization *get(const IR::Type_Specialized *t);
107 void dbprint(std::ostream &out) const override {
108 for (auto it : map) {
109 out << toString(it.first) << " => " << it.second << std::endl;
110 }
111 }
112
115 [[nodiscard]] const IR::Type_Declaration *nextAvailable();
118 void markDefined(const IR::Type_Declaration *tdec);
119
120 private:
121 friend class CreateSpecializedTypes;
122 void fillInsertionSet(const IR::Type_StructLike *decl, InsertionSet &insertion);
123};
124
128class FindTypeSpecializations : public Inspector, ResolutionContext {
129 TypeSpecializationMap *specMap;
130 MinimalNameGenerator nameGen;
131
132 public:
133 explicit FindTypeSpecializations(TypeSpecializationMap *specMap) : specMap(specMap) {
134 CHECK_NULL(specMap);
135 setName("FindTypeSpecializations");
136 }
137
138 void postorder(const IR::Type_Specialized *type) override;
139 profile_t init_apply(const IR::Node *node) override;
140};
141
146class CreateSpecializedTypes : public Modifier, public ResolutionContext {
147 TypeSpecializationMap *specMap;
148
149 public:
150 explicit CreateSpecializedTypes(TypeSpecializationMap *specMap) : specMap(specMap) {
151 CHECK_NULL(specMap);
152 setName("CreateSpecializedTypes");
153 }
154
155 void postorder(IR::Type_Specialized *type) override;
156 void postorder(IR::P4Program *prog) override;
157};
158
163class ReplaceTypeUses : public Transform {
164 TypeSpecializationMap *specMap;
165
166 public:
167 explicit ReplaceTypeUses(TypeSpecializationMap *specMap) : specMap(specMap) {
168 setName("ReplaceTypeUses");
169 CHECK_NULL(specMap);
170 }
171 const IR::Node *postorder(IR::Type_Specialized *type) override;
172 const IR::Node *postorder(IR::StructExpression *expresison) override;
173};
174
192class SpecializeGenericTypes : public PassRepeated {
193 TypeSpecializationMap specMap;
194
195 public:
196 explicit SpecializeGenericTypes(TypeMap *typeMap) {
197 passes.emplace_back(new PassRepeated({
198 new TypeChecking(nullptr, typeMap),
199 new FindTypeSpecializations(&specMap),
200 new CreateSpecializedTypes(&specMap),
201 // The previous pass has mutated some struct types
202 new ClearTypeMap(typeMap, true),
203 }));
204 passes.emplace_back(new TypeChecking(nullptr, typeMap));
205 passes.emplace_back(new ReplaceTypeUses(&specMap));
206 // The previous pass has invalidated the types of struct expressions
207 passes.emplace_back(new ClearTypeMap(typeMap, true));
208 specMap.typeMap = typeMap;
209 setName("SpecializeGenericTypes");
210 setStopOnError(true);
211 }
212};
213
215// Note: this pass is currently not used, but some
216// back-ends may find it useful.
218 public:
219 const IR::Node *postorder(IR::Type_StructLike *type) override {
220 if (!type->typeParameters->empty()) return nullptr;
221 return type;
222 }
223 const IR::Node *postorder(IR::Type_Stack *type) override {
224 if (type->elementType->is<IR::Type_Specialized>()) return nullptr;
225 return type;
226 }
227};
228
229} // namespace P4
230
231#endif /* FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_ */
Definition typeChecker.h:32
Definition specializeGenericTypes.h:146
Definition specializeGenericTypes.h:128
Definition stringify.h:33
Definition node.h:94
Definition ir/vector.h:59
Definition visitor.h:413
Definition referenceMap.h:36
Definition visitor.h:385
Definition referenceMap.h:29
Removes all structs or stacks that are generic.
Definition specializeGenericTypes.h:217
Definition specializeGenericTypes.h:163
Definition visitor.h:437
Definition typeChecker.h:55
Definition typeMap.h:41
Definition visitor.h:78
Definition cstring.h:85
Definition ordered_map.h:32
Definition safe_vector.h:27
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
absl::flat_hash_set< P4::cstring > InsertionSet
Set of type declaration names that must be defined before the type can be inserted.
Definition specializeGenericTypes.h:26
std::ostream & format_container(std::ostream &out, const Cont &container, char lbrace, char rbrace)
Definition log.h:164
A signature of a concrete specialization. None of the parameters can be type variables or generic typ...
Definition specializeGenericTypes.h:69
cstring baseType
Name of the type declaration of the base (unspecialized) type (i.e. the struct/header)
Definition specializeGenericTypes.h:72
static std::optional< SpecSignature > get(const IR::Type_Specialized *spec)
Get a specialization signature if it is valid (i.e. the type is specialized only by concrete non-gene...
Definition specializeGenericTypes.cpp:229
std::string name() const
Get a candidate name for the instantiation.
Definition specializeGenericTypes.cpp:215
bool operator<(const SpecSignature &other) const
Order for the sake of std::map only, the requirements are:
Definition specializeGenericTypes.h:84
safe_vector< cstring > arguments
String representation of the type argument names.
Definition specializeGenericTypes.h:74
Definition specializeGenericTypes.h:28
const IR::Vector< IR::Type > * argumentTypes
Definition specializeGenericTypes.h:42
const IR::Type_StructLike * replacement
New synthesized type (created later)
Definition specializeGenericTypes.h:36
bool inserted
was this specialization already inserted?
Definition specializeGenericTypes.h:44
InsertionSet insertion
Definition specializeGenericTypes.h:39
const IR::Type_Declaration * declaration
Declaration of specialized type, which will be replaced.
Definition specializeGenericTypes.h:34
const IR::Type_Specialized * specialized
Type that is being specialized.
Definition specializeGenericTypes.h:32
cstring name
Name to use for specialized type.
Definition specializeGenericTypes.h:30
Definition specializeGenericTypes.h:99
void markDefined(const IR::Type_Declaration *tdec)
Mark the tdec as already present and therefore remove it from required definitions for specialization...
Definition specializeGenericTypes.cpp:36
const IR::Type_Declaration * nextAvailable()
Get a single specialization that is already available (i.e. it does not require any additional defini...
Definition specializeGenericTypes.cpp:24