P4C
The P4 Compiler
Loading...
Searching...
No Matches
specializeGenericTypes.h
1/*
2 * Copyright 2020 VMware, Inc.
3 * SPDX-FileCopyrightText: 2020 VMware, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_
9#define FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_
10
11#include "frontends/p4/typeChecking/typeChecker.h"
12#include "ir/ir.h"
13
14namespace P4 {
15
17using InsertionSet = absl::flat_hash_set<P4::cstring>;
18
19struct TypeSpecialization : public IHasDbPrint {
23 const IR::Type_Specialized *specialized;
25 const IR::Type_Declaration *declaration;
27 const IR::Type_StructLike *replacement;
35 bool inserted = false;
36
37 TypeSpecialization(cstring name, const IR::Type_Specialized *specialized,
38 const IR::Type_Declaration *decl, const InsertionSet &insertion,
39 const IR::Vector<IR::Type> *argTypes)
40 : name(name),
42 declaration(decl),
43 replacement(nullptr),
45 argumentTypes(argTypes) {
46 CHECK_NULL(specialized);
47 CHECK_NULL(decl);
48 CHECK_NULL(argTypes);
49 }
50 void dbprint(std::ostream &out) const override {
51 out << "Specializing:" << dbp(specialized) << " from " << dbp(declaration) << " as "
52 << dbp(replacement) << " inserted at ";
53 format_container(out, insertion, '(', ')');
54 }
55};
56
66
68 std::string name() const;
69
75 bool operator<(const SpecSignature &other) const {
76 // Using pointer comparison to speed up baseType comparation as we don't care about what
77 // that order is. Note that for pointers we have to use `std::less` to make the comparison
78 // defined for pointers into different objects.
79 return std::less<>()(std::forward_as_tuple(baseType.c_str(), arguments),
80 std::forward_as_tuple(other.baseType.c_str(), other.arguments));
81 }
82
85 static std::optional<SpecSignature> get(const IR::Type_Specialized *spec);
86};
87
88std::string toString(const SpecSignature &);
89
91 TypeMap *typeMap;
93
94 void add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl,
95 NameGenerator *nameGen);
96 const TypeSpecialization *get(const IR::Type_Specialized *t) const;
97 TypeSpecialization *get(const IR::Type_Specialized *t);
98 void dbprint(std::ostream &out) const override {
99 for (auto it : map) {
100 out << toString(it.first) << " => " << it.second << std::endl;
101 }
102 }
103
106 [[nodiscard]] const IR::Type_Declaration *nextAvailable();
109 void markDefined(const IR::Type_Declaration *tdec);
110
111 private:
112 friend class CreateSpecializedTypes;
113 void fillInsertionSet(const IR::Type_StructLike *decl, InsertionSet &insertion);
114};
115
119class FindTypeSpecializations : public Inspector, ResolutionContext {
120 TypeSpecializationMap *specMap;
121 MinimalNameGenerator nameGen;
122
123 public:
124 explicit FindTypeSpecializations(TypeSpecializationMap *specMap) : specMap(specMap) {
125 CHECK_NULL(specMap);
126 setName("FindTypeSpecializations");
127 }
128
129 void postorder(const IR::Type_Specialized *type) override;
130 profile_t init_apply(const IR::Node *node) override;
131};
132
137class CreateSpecializedTypes : public Modifier, public ResolutionContext {
138 TypeSpecializationMap *specMap;
139
140 public:
141 explicit CreateSpecializedTypes(TypeSpecializationMap *specMap) : specMap(specMap) {
142 CHECK_NULL(specMap);
143 setName("CreateSpecializedTypes");
144 }
145
146 void postorder(IR::Type_Specialized *type) override;
147 void postorder(IR::P4Program *prog) override;
148};
149
154class ReplaceTypeUses : public Transform {
155 TypeSpecializationMap *specMap;
156
157 public:
158 explicit ReplaceTypeUses(TypeSpecializationMap *specMap) : specMap(specMap) {
159 setName("ReplaceTypeUses");
160 CHECK_NULL(specMap);
161 }
162 const IR::Node *postorder(IR::Type_Specialized *type) override;
163 const IR::Node *postorder(IR::StructExpression *expresison) override;
164};
165
183class SpecializeGenericTypes : public PassRepeated {
184 TypeSpecializationMap specMap;
185
186 public:
187 explicit SpecializeGenericTypes(TypeMap *typeMap) {
188 passes.emplace_back(new PassRepeated({
189 new TypeChecking(nullptr, typeMap),
190 new FindTypeSpecializations(&specMap),
191 new CreateSpecializedTypes(&specMap),
192 // The previous pass has mutated some struct types
193 new ClearTypeMap(typeMap, true),
194 }));
195 passes.emplace_back(new TypeChecking(nullptr, typeMap));
196 passes.emplace_back(new ReplaceTypeUses(&specMap));
197 // The previous pass has invalidated the types of struct expressions
198 passes.emplace_back(new ClearTypeMap(typeMap, true));
199 specMap.typeMap = typeMap;
200 setName("SpecializeGenericTypes");
201 setStopOnError(true);
202 }
203};
204
206// Note: this pass is currently not used, but some
207// back-ends may find it useful.
209 public:
210 const IR::Node *postorder(IR::Type_StructLike *type) override {
211 if (!type->typeParameters->empty()) return nullptr;
212 return type;
213 }
214 const IR::Node *postorder(IR::Type_Array *type) override {
215 if (type->elementType->is<IR::Type_Specialized>()) return nullptr;
216 return type;
217 }
218};
219
220} // namespace P4
221
222#endif /* FRONTENDS_P4_SPECIALIZEGENERICTYPES_H_ */
Definition typeChecker.h:32
Definition specializeGenericTypes.h:137
Definition specializeGenericTypes.h:119
Definition stringify.h:33
Definition node.h:53
Definition ir/vector.h:59
Definition visitor.h:418
Definition referenceMap.h:36
Definition visitor.h:385
Definition referenceMap.h:29
Removes all structs or stacks that are generic.
Definition specializeGenericTypes.h:208
Definition specializeGenericTypes.h:154
Definition visitor.h:442
Definition typeChecker.h:55
Definition typeMap.h:32
Definition visitor.h:78
Definition cstring.h:85
Definition ordered_map.h:32
Definition safe_vector.h:18
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
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:17
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:60
cstring baseType
Name of the type declaration of the base (unspecialized) type (i.e. the struct/header)
Definition specializeGenericTypes.h:63
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:218
std::string name() const
Get a candidate name for the instantiation.
Definition specializeGenericTypes.cpp:204
bool operator<(const SpecSignature &other) const
Order for the sake of std::map only, the requirements are:
Definition specializeGenericTypes.h:75
safe_vector< cstring > arguments
String representation of the type argument names.
Definition specializeGenericTypes.h:65
Definition specializeGenericTypes.h:19
const IR::Vector< IR::Type > * argumentTypes
Definition specializeGenericTypes.h:33
const IR::Type_StructLike * replacement
New synthesized type (created later)
Definition specializeGenericTypes.h:27
bool inserted
was this specialization already inserted?
Definition specializeGenericTypes.h:35
InsertionSet insertion
Definition specializeGenericTypes.h:30
const IR::Type_Declaration * declaration
Declaration of specialized type, which will be replaced.
Definition specializeGenericTypes.h:25
const IR::Type_Specialized * specialized
Type that is being specialized.
Definition specializeGenericTypes.h:23
cstring name
Name to use for specialized type.
Definition specializeGenericTypes.h:21
Definition specializeGenericTypes.h:90
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:25
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:13