P4C
The P4 Compiler
Loading...
Searching...
No Matches
flattenInterfaceStructs.h
1/*
2Copyright 2018 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 MIDEND_FLATTENINTERFACESTRUCTS_H_
18#define MIDEND_FLATTENINTERFACESTRUCTS_H_
19
20#include "frontends/p4/typeChecking/typeChecker.h"
21#include "ir/ir.h"
22#include "lib/cstring.h"
23
24namespace P4 {
25
31 public:
33
42 virtual bool keep(const IR::Annotation *) { return true; }
43};
44
65template <typename T>
66// T is the type of objects that will be replaced. E.g., IR::Type_Struct
68 StructTypeReplacement(const P4::TypeMap *typeMap, const IR::Type_StructLike *type,
71 flatten(typeMap, cstring::empty, type, type->annotations, vec, policy);
72 if (type->is<IR::Type_Struct>()) {
73 replacementType =
74 new IR::Type_Struct(type->srcInfo, type->name, IR::Annotations::empty, *vec);
75 } else if (type->is<IR::Type_Header>()) {
76 replacementType =
77 new IR::Type_Header(type->srcInfo, type->name, IR::Annotations::empty, *vec);
78 } else {
79 BUG("Unexpected type %1%", type);
80 }
81 }
82
83 // Maps nested field names to final field names.
84 // In our example this could be:
85 // .t.s.a -> _t_s_a0;
86 // .t.s.b -> _t_s_b1;
87 // .t.y -> _t_y2;
88 // .x -> _x3;
89 std::map<cstring, cstring> fieldNameRemap;
90 // Maps internal fields names to types.
91 // .t -> T
92 // .t.s -> S
93 std::map<cstring, const IR::Type_StructLike *> structFieldMap;
94 // Holds a new flat type
95 // struct M {
96 // bit _t_s_a0;
97 // bool _t_s_b1;
98 // bit<6> _t_y2;
99 // bit<3> _x3;
100 // }
101 const IR::Type *replacementType;
102 virtual void dbprint(std::ostream &out) const { out << replacementType; }
103
104 // Helper for constructor
105 void flatten(const P4::TypeMap *typeMap, cstring prefix, const IR::Type *type,
106 const IR::Annotations *annotations, IR::IndexedVector<IR::StructField> *fields,
108 // Drop name annotations
109 annotations = annotations->where(
110 [](const IR::Annotation *a) { return a->name != IR::Annotation::nameAnnotation; });
111 if (auto st = type->to<T>()) {
112 auto sannotations = st->annotations->where([policy](const IR::Annotation *annot) {
113 if (!policy) return false;
114 return policy->keep(annot);
115 });
116 structFieldMap.emplace(prefix, st);
117 for (auto f : st->fields) {
118 auto na = new IR::Annotations();
119 na->append(sannotations);
120 na->append(annotations);
121 na->append(f->annotations);
122 auto ft = typeMap->getType(f, true);
123 flatten(typeMap, prefix + "." + f->name, ft, na, fields, policy);
124 }
125 return;
126 }
127 cstring fieldName = prefix.replace('.', '_') + std::to_string(fieldNameRemap.size());
128 fieldNameRemap.emplace(prefix, fieldName);
129 fields->push_back(new IR::StructField(IR::ID(fieldName), annotations, type->getP4Type()));
130 LOG3("Flatten: " << type << " | " << prefix);
131 }
132
137 const IR::StructExpression *explode(const IR::Expression *root, cstring prefix) {
139 auto fieldType = ::P4::get(structFieldMap, prefix);
140 BUG_CHECK(fieldType, "No field for %1%", prefix);
141 for (auto f : fieldType->fields) {
142 cstring fieldName = prefix + "." + f->name.name;
143 auto newFieldname = ::P4::get(fieldNameRemap, fieldName);
144 const IR::Expression *expr;
145 if (!newFieldname.isNullOrEmpty()) {
146 expr = new IR::Member(root, newFieldname);
147 } else {
148 expr = explode(root, fieldName);
149 }
150 vec->push_back(new IR::NamedExpression(f->name, expr));
151 }
152 auto type = fieldType->getP4Type()->template to<IR::Type_Name>();
153 return new IR::StructExpression(root->srcInfo, type, type, *vec);
154 }
155};
156
162 P4::ReferenceMap *refMap;
163 P4::TypeMap *typeMap;
164
166
168 : refMap(refMap), typeMap(typeMap) {
169 CHECK_NULL(refMap);
170 CHECK_NULL(typeMap);
171 }
172 void createReplacement(const IR::Type_Struct *type);
173 StructTypeReplacement<IR::Type_Struct> *getReplacement(const IR::Type *type) const {
174 return ::P4::get(replacement, type);
175 }
176 bool empty() const { return replacement.empty(); }
177};
178
184 NestedStructMap *map;
185
186 public:
187 explicit FindTypesToReplace(NestedStructMap *map) : map(map) {
188 setName("FindTypesToReplace");
189 CHECK_NULL(map);
190 }
191 bool preorder(const IR::Declaration_Instance *inst) override;
192};
193
237 NestedStructMap *replacementMap;
238 std::map<const IR::Parameter *, StructTypeReplacement<IR::Type_Struct> *> toReplace;
239
240 public:
241 explicit ReplaceStructs(NestedStructMap *sm) : replacementMap(sm) {
242 CHECK_NULL(sm);
243 setName("ReplaceStructs");
244 }
245
246 const IR::Node *preorder(IR::P4Program *program) override;
247 const IR::Node *postorder(IR::Member *expression) override;
248 const IR::Node *preorder(IR::P4Parser *parser) override;
249 const IR::Node *preorder(IR::P4Control *control) override;
250 const IR::Node *postorder(IR::Type_Struct *type) override;
251};
252
254 public:
255 FlattenInterfaceStructs(ReferenceMap *refMap, TypeMap *typeMap) {
256 auto sm = new NestedStructMap(refMap, typeMap);
257 passes.push_back(new TypeChecking(refMap, typeMap));
258 passes.push_back(new FindTypesToReplace(sm));
259 passes.push_back(new ReplaceStructs(sm));
260 passes.push_back(new ClearTypeMap(typeMap));
261 setName("FlattenInterfaceStructs");
262 }
263};
264
265} // namespace P4
266
267#endif /* MIDEND_FLATTENINTERFACESTRUCTS_H_ */
Definition flattenInterfaceStructs.h:30
virtual bool keep(const IR::Annotation *)
Definition flattenInterfaceStructs.h:42
Definition typeChecker.h:32
Definition flattenInterfaceStructs.h:183
Definition flattenInterfaceStructs.h:253
Definition stringify.h:33
Definition node.h:52
Definition node.h:95
Definition visitor.h:400
Definition visitor.h:788
Definition pass_manager.h:40
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition flattenInterfaceStructs.h:236
Definition visitor.h:424
Definition typeChecker.h:55
Definition typeMap.h:41
Definition cstring.h:85
Definition ordered_map.h:32
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition id.h:28
Definition flattenInterfaceStructs.h:161
Definition flattenInterfaceStructs.h:67
const IR::StructExpression * explode(const IR::Expression *root, cstring prefix)
Definition flattenInterfaceStructs.h:137