Skip to content

Commit c9c9f20

Browse files
author
Mihai Budiu
authored
Struct initializer (#1498)
* StructInitializerExpression data structure
1 parent 9302717 commit c9c9f20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1102
-203
lines changed

backends/bmv2/common/expression.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,21 @@ void ExpressionConverter::postorder(const IR::ListExpression* expression) {
535535
}
536536
}
537537

538+
void ExpressionConverter::postorder(const IR::StructInitializerExpression* expression) {
539+
// Handle like a ListExpression
540+
auto result = new Util::JsonArray();
541+
mapExpression(expression, result);
542+
if (simpleExpressionsOnly) {
543+
::error("%1%: expression to complex for this target", expression);
544+
return;
545+
}
546+
547+
for (auto e : expression->components) {
548+
auto t = get(e->expression);
549+
result->append(t);
550+
}
551+
}
552+
538553
void ExpressionConverter::postorder(const IR::Operation_Unary* expression) {
539554
auto result = new Util::JsonObject();
540555
mapExpression(expression, result);

backends/bmv2/common/expression.h

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class ExpressionConverter : public Inspector {
115115
void postorder(const IR::IntMod* expression) override;
116116
void postorder(const IR::Operation_Binary* expression) override;
117117
void postorder(const IR::ListExpression* expression) override;
118+
void postorder(const IR::StructInitializerExpression* expression) override;
118119
void postorder(const IR::Operation_Unary* expression) override;
119120
void postorder(const IR::PathExpression* expression) override;
120121
void postorder(const IR::TypeNameExpression* expression) override;

backends/bmv2/common/extern.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,16 @@ ExternConverter::modelError(const char* format, const IR::Node* node) const {
126126
void
127127
ExternConverter::addToFieldList(ConversionContext* ctxt,
128128
const IR::Expression* expr, Util::JsonArray* fl) {
129-
if (expr->is<IR::ListExpression>()) {
130-
auto le = expr->to<IR::ListExpression>();
129+
if (auto le = expr->to<IR::ListExpression>()) {
131130
for (auto e : le->components) {
132131
addToFieldList(ctxt, e, fl);
133132
}
134133
return;
134+
} else if (auto si = expr->to<IR::StructInitializerExpression>()) {
135+
for (auto e : si->components) {
136+
addToFieldList(ctxt, e->expression, fl);
137+
}
138+
return;
135139
}
136140

137141
auto type = ctxt->typeMap->getType(expr, true);

backends/bmv2/common/lower.cpp

+35-5
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,18 @@ RemoveComplexExpressions::simplifyExpressions(const IR::Vector<IR::Argument>* ar
189189

190190
const IR::Expression*
191191
RemoveComplexExpressions::simplifyExpression(const IR::Expression* expression, bool force) {
192-
if (expression->is<IR::ListExpression>()) {
193-
auto list = expression->to<IR::ListExpression>();
192+
// Note that 'force' is not applied recursively
193+
if (auto list = expression->to<IR::ListExpression>()) {
194194
auto simpl = simplifyExpressions(&list->components);
195195
if (simpl != &list->components)
196196
return new IR::ListExpression(expression->srcInfo, *simpl);
197197
return expression;
198+
} else if (auto si = expression->to<IR::StructInitializerExpression>()) {
199+
auto simpl = simplifyExpressions(&si->components);
200+
if (simpl != &si->components)
201+
return new IR::StructInitializerExpression(
202+
si->srcInfo, si->name, *simpl, si->isHeader);
203+
return expression;
198204
} else {
199205
ComplexExpression ce;
200206
(void)expression->apply(ce);
@@ -226,6 +232,25 @@ RemoveComplexExpressions::simplifyExpressions(const IR::Vector<IR::Expression>*
226232
return vec;
227233
}
228234

235+
const IR::IndexedVector<IR::NamedExpression>*
236+
RemoveComplexExpressions::simplifyExpressions(
237+
const IR::IndexedVector<IR::NamedExpression>* vec) {
238+
auto result = new IR::IndexedVector<IR::NamedExpression>();
239+
bool changes = false;
240+
for (auto e : *vec) {
241+
auto r = simplifyExpression(e->expression, true);
242+
if (r != e->expression) {
243+
changes = true;
244+
result->push_back(new IR::NamedExpression(e->srcInfo, e->name, r));
245+
} else {
246+
result->push_back(e);
247+
}
248+
}
249+
if (changes)
250+
return result;
251+
return vec;
252+
}
253+
229254
const IR::Node*
230255
RemoveComplexExpressions::postorder(IR::SelectExpression* expression) {
231256
auto vec = simplifyExpressions(&expression->select->components);
@@ -272,9 +297,14 @@ RemoveComplexExpressions::postorder(IR::MethodCallExpression* expression) {
272297
// It should be a list expression.
273298
vec->push_back(expression->arguments->at(0));
274299
auto arg1 = expression->arguments->at(1)->expression;
275-
if (arg1->is<IR::ListExpression>()) {
276-
auto list = simplifyExpressions(&arg1->to<IR::ListExpression>()->components, true);
277-
arg1 = new IR::ListExpression(arg1->srcInfo, *list);
300+
if (auto list = arg1->to<IR::ListExpression>()) {
301+
auto simplified = simplifyExpressions(&list->components, true);
302+
arg1 = new IR::ListExpression(arg1->srcInfo, *simplified);
303+
vec->push_back(new IR::Argument(arg1));
304+
} else if (auto si = arg1->to<IR::StructInitializerExpression>()) {
305+
auto list = simplifyExpressions(&si->components);
306+
arg1 = new IR::StructInitializerExpression(
307+
si->srcInfo, si->name, *list, si->isHeader);
278308
vec->push_back(new IR::Argument(arg1));
279309
} else {
280310
auto tmp = new IR::Argument(

backends/bmv2/common/lower.h

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class RemoveComplexExpressions : public Transform {
8181
const IR::Vector<IR::Expression>* vec, bool force = false);
8282
const IR::Vector<IR::Argument>* simplifyExpressions(
8383
const IR::Vector<IR::Argument>* vec);
84+
const IR::IndexedVector<IR::NamedExpression>* simplifyExpressions(
85+
const IR::IndexedVector<IR::NamedExpression>* vec);
8486

8587
public:
8688
RemoveComplexExpressions(P4::ReferenceMap* refMap, P4::TypeMap* typeMap,

backends/bmv2/common/midend.h

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class EnumOn32Bits : public P4::ChooseEnumRepresentation {
4545
{ return 32; }
4646

4747
public:
48+
/// Convert all enums except all the ones appearing in the
49+
/// specified file.
4850
explicit EnumOn32Bits(cstring filename) : filename(filename) { }
4951
};
5052

control-plane/p4RuntimeArchHandler.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ std::string serializeOneAnnotation(const IR::Annotation* annotation) {
134134
auto kvs = annotation->kv;
135135
if (expressions.size() > 0 && kvs.size() > 0) serializedAnnotation.append(", ");
136136
for (auto it = kvs.begin(); it != kvs.end();) {
137-
serializedAnnotation.append(it->first);
137+
serializedAnnotation.append((*it)->name.name);
138138
serializedAnnotation.append("=");
139-
serializedAnnotation.append(serializeAnnotationExpression(it->second));
139+
serializedAnnotation.append(serializeAnnotationExpression((*it)->expression));
140140
if (++it != kvs.end()) serializedAnnotation.append(", ");
141141
}
142142
serializedAnnotation.append(")");

frontends/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ set (P4_FRONTEND_SRCS
5151
p4/simplifyParsers.cpp
5252
p4/specialize.cpp
5353
p4/strengthReduction.cpp
54+
p4/structInitializers.cpp
5455
p4/symbol_table.cpp
5556
p4/tableApply.cpp
5657
p4/tableKeyNames.cpp
@@ -111,6 +112,7 @@ set (P4_FRONTEND_HDRS
111112
p4/simplifyParsers.h
112113
p4/specialize.h
113114
p4/strengthReduction.h
115+
p4/structInitializers.h
114116
p4/symbol_table.h
115117
p4/tableApply.h
116118
p4/tableKeyNames.h

frontends/common/constantFolding.cpp

+29-20
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ const IR::Expression* DoConstantFolding::getConstant(const IR::Expression* expr)
5757
if (getConstant(e) == nullptr)
5858
return nullptr;
5959
return expr;
60-
}
61-
if (auto cast = expr->to<IR::Cast>()) {
60+
} else if (auto si = expr->to<IR::StructInitializerExpression>()) {
61+
for (auto e : si->components)
62+
if (getConstant(e->expression) == nullptr)
63+
return nullptr;
64+
return expr;
65+
} else if (auto cast = expr->to<IR::Cast>()) {
6266
// Casts of a constant to a value with type Type_Newtype
6367
// are constants, but we cannot fold them.
6468
if (getConstant(cast->expr))
@@ -533,27 +537,32 @@ const IR::Node* DoConstantFolding::postorder(IR::Member* e) {
533537
auto expr = getConstant(e->expr);
534538
if (expr == nullptr)
535539
return e;
536-
if (!type->is<IR::Type_StructLike>())
537-
BUG("Expected a struct type, got %1%", type);
538-
if (!expr->is<IR::ListExpression>())
539-
BUG("Expected a list of constants, got %1%", expr);
540-
541-
auto list = expr->to<IR::ListExpression>();
542540
auto structType = type->to<IR::Type_StructLike>();
543-
544-
bool found = false;
545-
int index = 0;
546-
for (auto f : structType->fields) {
547-
if (f->name.name == e->member.name) {
548-
found = true;
549-
break;
541+
if (structType == nullptr)
542+
BUG("Expected a struct type, got %1%", type);
543+
if (auto list = expr->to<IR::ListExpression>()) {
544+
bool found = false;
545+
int index = 0;
546+
for (auto f : structType->fields) {
547+
if (f->name.name == e->member.name) {
548+
found = true;
549+
break;
550+
}
551+
index++;
550552
}
551-
index++;
552-
}
553553

554-
if (!found)
555-
BUG("Could not find field %1% in type %2%", e->member, type);
556-
result = CloneConstants::clone(list->components.at(index));
554+
if (!found)
555+
BUG("Could not find field %1% in type %2%", e->member, type);
556+
result = CloneConstants::clone(list->components.at(index));
557+
} else if (auto si = expr->to<IR::StructInitializerExpression>()) {
558+
if (si->isHeader && e->member.name == IR::Type_Header::isValid)
559+
return e;
560+
auto ne = si->components.getDeclaration<IR::NamedExpression>(e->member.name);
561+
BUG_CHECK(ne != nullptr, "Could not find field %1% in initializer %2%", e->member, si);
562+
return CloneConstants::clone(ne->expression);
563+
} else {
564+
BUG("Unexpected initializer: %1%", expr);
565+
}
557566
}
558567
return result;
559568
}

frontends/p4/frontend.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ limitations under the License.
5353
#include "simplifyParsers.h"
5454
#include "specialize.h"
5555
#include "strengthReduction.h"
56+
#include "structInitializers.h"
5657
#include "tableKeyNames.h"
5758
#include "toP4/toP4.h"
5859
#include "typeChecking/typeChecker.h"
@@ -142,6 +143,7 @@ const IR::P4Program *FrontEnd::run(const CompilerOptions &options, const IR::P4P
142143
new CheckNamedArgs(),
143144
new TypeInference(&refMap, &typeMap, false), // insert casts
144145
new BindTypeVariables(&typeMap),
146+
new StructInitializers(&refMap, &typeMap),
145147
// Another round of constant folding, using type information.
146148
new ClearTypeMap(&typeMap),
147149
new DefaultArguments(&refMap, &typeMap), // add default argument values to parameters

frontends/p4/setHeaders.cpp

+39-19
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,58 @@ limitations under the License.
1919
namespace P4 {
2020

2121
void DoSetHeaders::generateSetValid(
22-
const IR::Type* destType, const IR::Type* srcType,
23-
const IR::Expression* dest, IR::Vector<IR::StatOrDecl>* insert) {
24-
auto tt = srcType->to<IR::Type_Tuple>();
25-
if (tt == nullptr)
22+
const IR::Expression* dest, const IR::Expression* src,
23+
const IR::Type* destType,
24+
IR::Vector<IR::StatOrDecl>* insert) {
25+
26+
auto structType = destType->to<IR::Type_StructLike>();
27+
if (structType == nullptr)
2628
return;
2729

28-
// The source is either a tuple, or a list expression
29-
if (destType->is<IR::Type_Struct>()) {
30-
auto it = tt->components.begin();
31-
auto sl = destType->to<IR::Type_Struct>();
32-
for (auto f : sl->fields) {
33-
auto ftype = typeMap->getType(f, true);
34-
auto stype = *it;
35-
auto member = new IR::Member(dest, f->name);
36-
generateSetValid(ftype, stype, member, insert);
37-
++it;
38-
}
39-
} else if (destType->is<IR::Type_Header>()) {
30+
auto srcType = typeMap->getType(src, true);
31+
auto list = src->to<IR::ListExpression>();
32+
auto si = src->to<IR::StructInitializerExpression>();
33+
if (list == nullptr && si == nullptr)
34+
return;
35+
36+
if (structType->is<IR::Type_Header>()) {
4037
LOG3("Inserting setValid for " << dest);
4138
auto method = new IR::Member(dest->srcInfo, dest, IR::Type_Header::setValid);
4239
auto mc = new IR::MethodCallExpression(
4340
dest->srcInfo, method, new IR::Vector<IR::Argument>());
4441
auto stat = new IR::MethodCallStatement(mc->srcInfo, mc);
4542
insert->push_back(stat);
43+
return;
44+
}
45+
46+
// Recurse on fields of structType
47+
if (list != nullptr) {
48+
auto tt = srcType->to<IR::Type_Tuple>();
49+
CHECK_NULL(tt);
50+
auto it = list->components.begin();
51+
for (auto f : structType->fields) {
52+
auto member = new IR::Member(dest, f->name);
53+
auto ft = typeMap->getType(f);
54+
generateSetValid(member, *it, ft, insert);
55+
++it;
56+
}
57+
return;
58+
}
59+
60+
CHECK_NULL(si);
61+
for (auto f : structType->fields) {
62+
auto member = new IR::Member(dest, f->name);
63+
auto srcMember = si->components.getDeclaration<IR::NamedExpression>(f->name);
64+
auto ft = typeMap->getType(f);
65+
CHECK_NULL(srcMember);
66+
generateSetValid(member, srcMember->expression, ft, insert);
4667
}
4768
}
4869

4970
const IR::Node* DoSetHeaders::postorder(IR::AssignmentStatement* statement) {
5071
auto vec = new IR::Vector<IR::StatOrDecl>();
51-
auto ltype = typeMap->getType(statement->left, true);
52-
auto rtype = typeMap->getType(statement->right, true);
53-
generateSetValid(ltype, rtype, statement->left, vec);
72+
auto destType = typeMap->getType(statement->left, true);
73+
generateSetValid(statement->left, statement->right, destType, vec);
5474
if (vec->empty())
5575
return statement;
5676
vec->push_back(statement);

frontends/p4/setHeaders.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ class DoSetHeaders final : public Transform {
5151

5252
bool containsHeaderType(const IR::Type* type);
5353
void generateSetValid(
54-
const IR::Type* destType, const IR::Type* srcType,
55-
const IR::Expression* dest, IR::Vector<IR::StatOrDecl>* insert);
54+
const IR::Expression* dest, const IR::Expression* src,
55+
const IR::Type* destType, IR::Vector<IR::StatOrDecl>* insert);
5656

5757
public:
5858
DoSetHeaders(ReferenceMap* refMap, TypeMap* typeMap) : refMap(refMap), typeMap(typeMap)

frontends/p4/sideEffects.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,15 @@ class DismantleExpression : public Transform {
482482
rw.emplace(expression, result);
483483
}
484484

485+
void postorder(const IR::StructInitializerExpression* expression) override {
486+
const SetOfLocations* result = new SetOfLocations();
487+
for (auto e : expression->components) {
488+
auto s = ::get(rw, e->expression);
489+
result = result->join(s);
490+
}
491+
rw.emplace(expression, result);
492+
}
493+
485494
void postorder(const IR::ListExpression* expression) override {
486495
const SetOfLocations* result = new SetOfLocations();
487496
for (auto e : expression->components) {
@@ -568,16 +577,16 @@ class DismantleExpression : public Transform {
568577
continue;
569578
}
570579
// If the parameter contains header values and the
571-
// argument is a list expression then we also use a
572-
// temporary. This makes the job of the SetHeaders pass
573-
// later simpler (otherwise we have to handle this case
574-
// there).
580+
// argument is a list expression or a struct initializer
581+
// then we also use a temporary. This makes the job of
582+
// the SetHeaders pass later simpler (otherwise we have to
583+
// handle this case there).
575584
auto ptype = typeMap->getType(p, true);
576585
if (!containsHeaderType(ptype))
577586
continue;
578587

579-
auto argType = typeMap->getType(arg, true);
580-
if (argType->is<IR::Type_Tuple>()) {
588+
if (arg->expression->is<IR::ListExpression>() ||
589+
arg->expression->is<IR::StructInitializerExpression>()) {
581590
LOG3("Using temporary for " << dbp(mce) <<
582591
" param " << dbp(p) << " assigning tuple to header");
583592
useTemporary.emplace(p);

0 commit comments

Comments
 (0)