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/common/resolveReferences/resolveReferences.h"
21#include "frontends/p4/typeChecking/typeChecker.h"
22#include "ir/annotations.h"
23#include "ir/ir.h"
24#include "lib/cstring.h"
25
26namespace P4 {
27
33 public:
35
44 virtual bool keep(const IR::Annotation *) { return true; }
45};
46
67template <typename T>
68// T is the type of objects that will be replaced. E.g., IR::Type_Struct
70 StructTypeReplacement(const P4::TypeMap *typeMap, const IR::Type_StructLike *type,
73 flatten(typeMap, cstring::empty, type, type->annotations, vec, policy);
74 if (type->is<IR::Type_Struct>()) {
75 replacementType = new IR::Type_Struct(type->srcInfo, type->name, std::move(vec));
76 } else if (type->is<IR::Type_Header>()) {
77 replacementType = new IR::Type_Header(type->srcInfo, type->name, std::move(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::Vector<IR::Annotation> &annotations,
108 // Drop name annotations
109 auto ann = IR::Annotations::withoutNameAnnotation(annotations);
110 if (auto st = type->to<T>()) {
112 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) {
119 fann.append(ann);
120 fann.append(f->annotations);
121 auto ft = typeMap->getType(f, true);
122 flatten(typeMap, prefix + "." + f->name, ft, fann, fields, policy);
123 }
124 return;
125 }
126 cstring fieldName = prefix.replace('.', '_') + std::to_string(fieldNameRemap.size());
127 fieldNameRemap.emplace(prefix, fieldName);
128 fields.push_back(new IR::StructField(IR::ID(fieldName), ann, type->getP4Type()));
129 LOG3("Flatten: " << type << " | " << prefix);
130 }
131
136 const IR::StructExpression *explode(const IR::Expression *root, cstring prefix) {
138 auto fieldType = ::P4::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 = ::P4::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, std::move(vec));
153 }
154};
155
161 P4::TypeMap *typeMap;
162
164
165 explicit NestedStructMap(P4::TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); }
166 void createReplacement(const IR::Type_Struct *type);
167 StructTypeReplacement<IR::Type_Struct> *getReplacement(const IR::Type *type) const {
168 return ::P4::get(replacement, type);
169 }
170 bool empty() const { return replacement.empty(); }
171};
172
178 NestedStructMap *map;
179
180 public:
181 explicit FindTypesToReplace(NestedStructMap *map) : map(map) {
182 setName("FindTypesToReplace");
183 CHECK_NULL(map);
184 }
185 bool preorder(const IR::Declaration_Instance *inst) override;
186};
187
231 NestedStructMap *replacementMap;
232 std::map<const IR::Parameter *, StructTypeReplacement<IR::Type_Struct> *> toReplace;
233
234 public:
235 explicit ReplaceStructs(NestedStructMap *sm) : replacementMap(sm) {
236 CHECK_NULL(sm);
237 setName("ReplaceStructs");
238 }
239
240 const IR::Node *preorder(IR::P4Program *program) override;
241 const IR::Node *postorder(IR::Member *expression) override;
242 const IR::Node *preorder(IR::P4Parser *parser) override;
243 const IR::Node *preorder(IR::P4Control *control) override;
244 const IR::Node *postorder(IR::Type_Struct *type) override;
245};
246
249
250 public:
251 explicit FlattenInterfaceStructs(TypeMap *typeMap) : sm(typeMap) {
252 passes.push_back(new TypeChecking(nullptr, typeMap));
253 passes.push_back(new FindTypesToReplace(&sm));
254 passes.push_back(new ReplaceStructs(&sm));
255 passes.push_back(new ClearTypeMap(typeMap));
256 setName("FlattenInterfaceStructs");
257 }
258};
259
260} // namespace P4
261
262#endif /* MIDEND_FLATTENINTERFACESTRUCTS_H_ */
Definition flattenInterfaceStructs.h:32
virtual bool keep(const IR::Annotation *)
Definition flattenInterfaceStructs.h:44
Definition typeChecker.h:32
Definition flattenInterfaceStructs.h:177
Definition flattenInterfaceStructs.h:247
Definition stringify.h:33
Definition node.h:52
Definition node.h:94
Definition vector.h:59
Definition visitor.h:400
Definition visitor.h:788
Definition ir/pass_manager.h:40
Definition flattenInterfaceStructs.h:230
Visitor mixin for looking up names in enclosing scopes from the Visitor::Context.
Definition resolveReferences.h:35
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:160
Definition flattenInterfaceStructs.h:69
const IR::StructExpression * explode(const IR::Expression *root, cstring prefix)
Definition flattenInterfaceStructs.h:136