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