P4C
The P4 Compiler
Loading...
Searching...
No Matches
flattenInterfaceStructs.h
1/*
2 * Copyright 2018 VMware, Inc.
3 * SPDX-FileCopyrightText: 2018 VMware, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#ifndef MIDEND_FLATTENINTERFACESTRUCTS_H_
9#define MIDEND_FLATTENINTERFACESTRUCTS_H_
10
11#include "frontends/common/resolveReferences/resolveReferences.h"
12#include "frontends/p4/typeChecking/typeChecker.h"
13#include "ir/annotations.h"
14#include "ir/ir.h"
15#include "lib/cstring.h"
16
17namespace P4 {
18
24 public:
26
35 virtual bool keep(const IR::Annotation *) { return true; }
36};
37
58template <typename T>
59// T is the type of objects that will be replaced. E.g., IR::Type_Struct
60struct StructTypeReplacement : public IHasDbPrint {
61 StructTypeReplacement(const P4::TypeMap *typeMap, const IR::Type_StructLike *type,
64 flatten(typeMap, cstring::empty, type, type->annotations, vec, policy);
65 if (type->is<IR::Type_Struct>()) {
66 replacementType = new IR::Type_Struct(type->srcInfo, type->name, std::move(vec));
67 } else if (type->is<IR::Type_Header>()) {
68 replacementType = new IR::Type_Header(type->srcInfo, type->name, std::move(vec));
69 } else {
70 BUG("Unexpected type %1%", type);
71 }
72 }
73
74 // Maps nested field names to final field names.
75 // In our example this could be:
76 // .t.s.a -> _t_s_a0;
77 // .t.s.b -> _t_s_b1;
78 // .t.y -> _t_y2;
79 // .x -> _x3;
80 std::map<cstring, cstring> fieldNameRemap;
81 // Maps internal fields names to types.
82 // .t -> T
83 // .t.s -> S
84 std::map<cstring, const IR::Type_StructLike *> structFieldMap;
85 // Holds a new flat type
86 // struct M {
87 // bit _t_s_a0;
88 // bool _t_s_b1;
89 // bit<6> _t_y2;
90 // bit<3> _x3;
91 // }
92 const IR::Type *replacementType;
93 virtual void dbprint(std::ostream &out) const { out << replacementType; }
94
95 // Helper for constructor
96 void flatten(const P4::TypeMap *typeMap, cstring prefix, const IR::Type *type,
97 const IR::Vector<IR::Annotation> &annotations,
99 // Drop name annotations
100 auto ann = IR::Annotations::withoutNameAnnotation(annotations);
101 if (auto st = type->to<T>()) {
103 st->annotations.where([policy](const IR::Annotation *annot) {
104 if (!policy) return false;
105 return policy->keep(annot);
106 });
107 structFieldMap.emplace(prefix, st);
108 for (auto f : st->fields) {
110 fann.append(ann);
111 fann.append(f->annotations);
112 auto ft = typeMap->getType(f, true);
113 flatten(typeMap, prefix + "." + f->name, ft, fann, fields, policy);
114 }
115 return;
116 }
117 cstring fieldName = prefix.replace('.', '_') + std::to_string(fieldNameRemap.size());
118 fieldNameRemap.emplace(prefix, fieldName);
119 fields.push_back(new IR::StructField(IR::ID(fieldName), ann, type->getP4Type()));
120 LOG3("Flatten: " << type << " | " << prefix);
121 }
122
127 const IR::StructExpression *explode(const IR::Expression *root, cstring prefix) {
129 auto fieldType = ::P4::get(structFieldMap, prefix);
130 BUG_CHECK(fieldType, "No field for %1%", prefix);
131 for (auto f : fieldType->fields) {
132 cstring fieldName = prefix + "." + f->name.name;
133 auto newFieldname = ::P4::get(fieldNameRemap, fieldName);
134 const IR::Expression *expr;
135 if (!newFieldname.isNullOrEmpty()) {
136 expr = new IR::Member(root, newFieldname);
137 } else {
138 expr = explode(root, fieldName);
139 }
140 vec.push_back(new IR::NamedExpression(f->name, expr));
141 }
142 auto type = fieldType->getP4Type()->template to<IR::Type_Name>();
143 return new IR::StructExpression(root->srcInfo, type, type, std::move(vec));
144 }
145};
146
151struct NestedStructMap {
152 P4::TypeMap *typeMap;
153
155
156 explicit NestedStructMap(P4::TypeMap *typeMap) : typeMap(typeMap) { CHECK_NULL(typeMap); }
157 void createReplacement(const IR::Type_Struct *type);
158 StructTypeReplacement<IR::Type_Struct> *getReplacement(const IR::Type *type) const {
159 return ::P4::get(replacement, type);
160 }
161 bool empty() const { return replacement.empty(); }
162};
163
168class FindTypesToReplace : public Inspector {
169 NestedStructMap *map;
170
171 public:
172 explicit FindTypesToReplace(NestedStructMap *map) : map(map) {
173 setName("FindTypesToReplace");
174 CHECK_NULL(map);
175 }
176 bool preorder(const IR::Declaration_Instance *inst) override;
177};
178
221class ReplaceStructs : public Transform, P4WriteContext, ResolutionContext {
222 NestedStructMap *replacementMap;
223 std::map<const IR::Parameter *, StructTypeReplacement<IR::Type_Struct> *> toReplace;
224
225 public:
226 explicit ReplaceStructs(NestedStructMap *sm) : replacementMap(sm) {
227 CHECK_NULL(sm);
228 setName("ReplaceStructs");
229 }
230
231 const IR::Node *preorder(IR::P4Program *program) override;
232 const IR::Node *postorder(IR::Member *expression) override;
233 const IR::Node *preorder(IR::P4Parser *parser) override;
234 const IR::Node *preorder(IR::P4Control *control) override;
235 const IR::Node *postorder(IR::Type_Struct *type) override;
236};
237
238class FlattenInterfaceStructs final : public PassManager {
240
241 public:
242 explicit FlattenInterfaceStructs(TypeMap *typeMap) : sm(typeMap) {
243 passes.push_back(new TypeChecking(nullptr, typeMap));
244 passes.push_back(new FindTypesToReplace(&sm));
245 passes.push_back(new ReplaceStructs(&sm));
246 passes.push_back(new ClearTypeMap(typeMap));
247 setName("FlattenInterfaceStructs");
248 }
249};
250
251} // namespace P4
252
253#endif /* MIDEND_FLATTENINTERFACESTRUCTS_H_ */
Definition flattenInterfaceStructs.h:23
virtual bool keep(const IR::Annotation *)
Definition flattenInterfaceStructs.h:35
Definition typeChecker.h:32
Definition flattenInterfaceStructs.h:168
Definition stringify.h:33
Definition indexed_vector.h:31
Definition node.h:53
Definition ir/vector.h:59
Definition visitor.h:418
Definition visitor.h:811
Definition flattenInterfaceStructs.h:221
Definition visitor.h:442
Definition typeChecker.h:55
Definition typeMap.h:32
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:13
Definition id.h:28
Definition flattenInterfaceStructs.h:151
Definition flattenInterfaceStructs.h:60
const IR::StructExpression * explode(const IR::Expression *root, cstring prefix)
Definition flattenInterfaceStructs.h:127
Definition register_reference.h:28