Skip to content

Commit fa16c69

Browse files
author
Mihai Budiu
authored
Support for structured annotations (#2227)
* Support for structured annotations
1 parent 3f9d383 commit fa16c69

39 files changed

+223
-70
lines changed

backends/bmv2/common/backend.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class RenameUserMetadata : public Transform {
162162
auto stringLit = new IR::StringLiteral(newName);
163163
LOG2("Renaming " << f << " to " << newName);
164164
auto annos = f->annotations->addOrReplace(
165-
IR::Annotation::nameAnnotation, stringLit);
165+
IR::Annotation::nameAnnotation, stringLit, false);
166166
auto field = new IR::StructField(f->srcInfo, f->name, annos, f->type);
167167
fields.push_back(field);
168168
}

control-plane/flattenHeader.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void FlattenHeader::doFlatten(const IR::Type* type) {
4141
auto originalName = makeName(".");
4242
auto annotations = mergeAnnotations();
4343
annotations = annotations->addOrReplace(
44-
IR::Annotation::nameAnnotation, new IR::StringLiteral(originalName));
44+
IR::Annotation::nameAnnotation, new IR::StringLiteral(originalName), false);
4545
newFields.push_back(new IR::StructField(IR::ID(newName), annotations, type));
4646
}
4747
}

frontends/p4-14/header_type.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2013-present Barefoot Networks, Inc.
2+
Copyright 2013-present Barefoot Networks, Inc.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -24,13 +24,13 @@ HeaderTypeMaxLengthCalculator::preorder(IR::Type_StructLike *hdr_type) {
2424
unsigned len = 0;
2525
for (auto field : hdr_type->fields)
2626
len += field->type->width_bits();
27-
max_length = new IR::Annotation("max_length", len);
27+
max_length = new IR::Annotation("max_length", len, false);
2828
if (!annot) annot = hdr_type->annotations->clone();
2929
annot->annotations.push_back(max_length); }
3030
auto *length = hdr_type->getAnnotation("length");
3131
if (!length) {
3232
if (!annot) annot = hdr_type->annotations->clone();
33-
length = new IR::Annotation("length", max_length->expr);
33+
length = new IR::Annotation("length", max_length->expr, false);
3434
annot->annotations.push_back(length); }
3535
if (annot) hdr_type->annotations = annot;
3636
return false;

frontends/p4/createBuiltins.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ void CreateBuiltins::postorder(IR::ActionList* actions) {
7070
return;
7171
actions->push_back(
7272
new IR::ActionListElement(
73-
new IR::Annotations({new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}),
73+
new IR::Annotations(
74+
{new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {}, false)}),
7475
new IR::MethodCallExpression(
7576
new IR::PathExpression(P4::P4CoreLibrary::instance.noAction.Id(actions->srcInfo)),
7677
new IR::Vector<IR::Type>(), new IR::Vector<IR::Argument>())));

frontends/p4/directCalls.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ const IR::Node* DoInstantiateCalls::postorder(IR::MethodCallExpression* expressi
3434
auto name = refMap->newName(tn->typeName->path->name + "_inst");
3535
LOG3("Inserting instance " << name);
3636
auto annos = new IR::Annotations();
37-
annos->add(new IR::Annotation(IR::Annotation::nameAnnotation,
38-
{ new IR::StringLiteral(tn->typeName->path->toString()) }));
37+
annos->add(new IR::Annotation(
38+
IR::Annotation::nameAnnotation,
39+
{ new IR::StringLiteral(tn->typeName->path->toString()) }, false));
3940
auto inst = new IR::Declaration_Instance(
4041
expression->srcInfo, IR::ID(name), annos,
4142
tn->typeName->clone(), new IR::Vector<IR::Argument>());

frontends/p4/fromv1.0/converters.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ const IR::StructField *TypeConverter::postorder(IR::StructField *field) {
464464
auto fieldlen = new IR::Sub(
465465
scale->srcInfo, scale, new IR::Constant(type->width_bits()));
466466
field->annotations = field->annotations->add(
467-
new IR::Annotation("length", { fieldlen }));
467+
new IR::Annotation("length", { fieldlen }, false));
468468
}
469469
}
470470
}
@@ -492,7 +492,7 @@ class FixupExtern : public Modifier {
492492
void postorder(IR::Type_Extern *type) override {
493493
if (extname != type->name) {
494494
type->annotations = type->annotations->addAnnotationIfNew(
495-
IR::Annotation::nameAnnotation, new IR::StringLiteral(type->name.name));
495+
IR::Annotation::nameAnnotation, new IR::StringLiteral(type->name.name), false);
496496
type->name = extname; }
497497
// FIXME -- should create ctors based on attributes? For now just create a
498498
// FIXME -- 0-arg one if needed

frontends/p4/fromv1.0/converters.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -776,8 +776,9 @@ class InsertCompilerGeneratedStartState: public Transform {
776776
new IR::PathExpression(new IR::Path(p.second->name))));
777777
}
778778
auto instAnnos = new IR::Annotations();
779-
instAnnos->add(new IR::Annotation(IR::Annotation::nameAnnotation,
780-
{new IR::StringLiteral(IR::ID(".$InstanceType"))}));
779+
instAnnos->add(new IR::Annotation(
780+
IR::Annotation::nameAnnotation,
781+
{new IR::StringLiteral(IR::ID(".$InstanceType"))}, false));
781782
auto instEnum =
782783
new IR::Type_SerEnum(newInstanceType, instAnnos, IR::Type_Bits::get(32), members);
783784
allTypeDecls.push_back(instEnum);
@@ -790,7 +791,7 @@ class InsertCompilerGeneratedStartState: public Transform {
790791
auto selects = new IR::SelectExpression(new IR::ListExpression(selExpr), selCases);
791792
auto annos = new IR::Annotations();
792793
annos->add(new IR::Annotation(IR::Annotation::nameAnnotation,
793-
{new IR::StringLiteral(IR::ID(".$start"))}));
794+
{new IR::StringLiteral(IR::ID(".$start"))}, false));
794795
auto startState = new IR::ParserState(IR::ParserState::start, annos, selects);
795796
varDecls.push_back(startState);
796797

frontends/p4/fromv1.0/programStructure.cpp

+14-12
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ ProgramStructure::addNameAnnotation(cstring name, const IR::Annotations* annos)
5959
if (annos == nullptr)
6060
annos = IR::Annotations::empty;
6161
return annos->addAnnotationIfNew(IR::Annotation::nameAnnotation,
62-
new IR::StringLiteral(name));
62+
new IR::StringLiteral(name), false);
6363
}
6464

6565
const IR::Annotations*
@@ -810,9 +810,11 @@ ProgramStructure::convertActionProfile(const IR::ActionProfile* action_profile,
810810
auto width = new IR::Constant(v1model.action_selector.widthType, flc->output_width);
811811
args->push_back(new IR::Argument(width));
812812
if (action_selector->mode)
813-
annos = annos->addAnnotation("mode", new IR::StringLiteral(action_selector->mode));
813+
annos = annos->addAnnotation(
814+
"mode", new IR::StringLiteral(action_selector->mode), false);
814815
if (action_selector->type)
815-
annos = annos->addAnnotation("type", new IR::StringLiteral(action_selector->type));
816+
annos = annos->addAnnotation(
817+
"type", new IR::StringLiteral(action_selector->type), false);
816818
auto fl = getFieldLists(flc);
817819
for (auto annot : fl->annotations->annotations) {
818820
annos = annos->add(annot);
@@ -867,7 +869,7 @@ ProgramStructure::convertTable(const IR::V1Table* table, cstring newName,
867869
actionList->push_back(
868870
new IR::ActionListElement(
869871
new IR::Annotations(
870-
{new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}),
872+
{new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {}, false)}),
871873
new IR::PathExpression(default_action))); }
872874
props->push_back(new IR::Property(IR::ID(IR::TableProperties::actionsPropertyName),
873875
actionList, false));
@@ -1987,9 +1989,9 @@ ProgramStructure::convert(const IR::CounterOrMeter* cm, cstring newName) {
19871989
auto annos = addGlobalNameAnnotation(cm->name, cm->annotations);
19881990
if (auto *c = cm->to<IR::Counter>()) {
19891991
if (c->min_width >= 0)
1990-
annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width));
1992+
annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width), false);
19911993
if (c->max_width >= 0)
1992-
annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width));
1994+
annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width), false);
19931995
}
19941996
auto decl = new IR::Declaration_Instance(
19951997
newName, annos, type, args, nullptr);
@@ -2020,7 +2022,7 @@ ProgramStructure::convertDirectMeter(const IR::Meter* m, cstring newName) {
20202022
if (m->pre_color != nullptr) {
20212023
auto meterPreColor = ExpressionConverter(this).convert(m->pre_color);
20222024
if (meterPreColor != nullptr)
2023-
annos = annos->addAnnotation("pre_color", meterPreColor);
2025+
annos = annos->addAnnotation("pre_color", meterPreColor, false);
20242026
}
20252027
auto decl = new IR::Declaration_Instance(newName, annos, specType, args, nullptr);
20262028
return decl;
@@ -2038,9 +2040,9 @@ ProgramStructure::convertDirectCounter(const IR::Counter* c, cstring newName) {
20382040
args->push_back(new IR::Argument(kindarg));
20392041
auto annos = addGlobalNameAnnotation(c->name, c->annotations);
20402042
if (c->min_width >= 0)
2041-
annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width));
2043+
annos = annos->addAnnotation("min_width", new IR::Constant(c->min_width), false);
20422044
if (c->max_width >= 0)
2043-
annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width));
2045+
annos = annos->addAnnotation("max_width", new IR::Constant(c->max_width), false);
20442046
auto decl = new IR::Declaration_Instance(newName, annos, type, args, nullptr);
20452047
return decl;
20462048
}
@@ -2475,19 +2477,19 @@ void ProgramStructure::createChecksumUpdates() {
24752477
auto mc = new IR::MethodCallStatement(methodCallExpression);
24762478
if (flc->algorithm->names[0] == "csum16_udp") {
24772479
auto zeros_as_ones_annot = new IR::Annotation(IR::ID("zeros_as_ones"),
2478-
{methodCallExpression});
2480+
{methodCallExpression}, false);
24792481
body->annotations = body->annotations->add(zeros_as_ones_annot);
24802482
}
24812483

24822484
for (auto annot : cf->annotations->annotations) {
2483-
auto newAnnot = new IR::Annotation(annot->name, {});
2485+
auto newAnnot = new IR::Annotation(annot->name, {}, false);
24842486
for (auto expr : annot->expr)
24852487
newAnnot->expr.push_back(expr);
24862488
newAnnot->expr.push_back(methodCallExpression);
24872489
body->annotations = body->annotations->add(newAnnot);
24882490
}
24892491
for (auto annot : flc->annotations->annotations) {
2490-
auto newAnnot = new IR::Annotation(annot->name, {});
2492+
auto newAnnot = new IR::Annotation(annot->name, {}, false);
24912493
for (auto expr : annot->expr)
24922494
newAnnot->expr.push_back(expr);
24932495
newAnnot->expr.push_back(methodCallExpression);

frontends/p4/hierarchicalNames.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const IR::Node* HierarchicalNames::postorder(IR::Annotation* annotation) {
3434
newName += s + ".";
3535
newName += name;
3636
LOG2("Changing " << name << " to " << newName);
37-
annotation = new IR::Annotation(annotation->name, { new IR::StringLiteral(newName) });
37+
annotation = new IR::Annotation(annotation->name, { new IR::StringLiteral(newName) }, false);
3838
return annotation;
3939
}
4040

frontends/p4/inlining.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ setNameAnnotation(cstring name, const IR::Annotations* annos) {
220220
if (annos == nullptr)
221221
annos = IR::Annotations::empty;
222222
return annos->addOrReplace(IR::Annotation::nameAnnotation,
223-
new IR::StringLiteral(name));
223+
new IR::StringLiteral(name), false);
224224
}
225225

226226
/**

frontends/p4/localizeActions.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const IR::Node* TagGlobalActions::preorder(IR::P4Action* action) {
4343
annos = IR::Annotations::empty;
4444
cstring name = cstring(".") + action->name;
4545
annos = annos->addAnnotationIfNew(IR::Annotation::nameAnnotation,
46-
new IR::StringLiteral(name));
46+
new IR::StringLiteral(name), false);
4747
action->annotations = annos;
4848
}
4949
prune();
@@ -77,7 +77,7 @@ bool FindGlobalActionUses::preorder(const IR::PathExpression* path) {
7777
if (annos == nullptr)
7878
annos = IR::Annotations::empty;
7979
annos->addAnnotationIfNew(IR::Annotation::nameAnnotation,
80-
new IR::StringLiteral(action->name));
80+
new IR::StringLiteral(action->name), false);
8181
auto replacement = new IR::P4Action(action->srcInfo,
8282
IR::ID(action->name.srcInfo, newName, action->name.originalName),
8383
annos, params, replBody);
@@ -167,7 +167,7 @@ bool FindRepeatedActionUses::preorder(const IR::PathExpression* expression) {
167167
if (annos == nullptr)
168168
annos = IR::Annotations::empty;
169169
annos->addAnnotationIfNew(IR::Annotation::nameAnnotation,
170-
new IR::StringLiteral(action->name));
170+
new IR::StringLiteral(action->name), false);
171171
replacement = new IR::P4Action(action->srcInfo,
172172
IR::ID(action->name.srcInfo, newName, action->name.originalName),
173173
annos, params, replBody);

frontends/p4/tableKeyNames.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ const IR::Node* DoTableKeyNames::postorder(IR::KeyElement* keyElement) {
137137
return keyElement;
138138
keyElement->annotations = keyElement->annotations->addAnnotation(
139139
IR::Annotation::nameAnnotation,
140-
new IR::StringLiteral(keyElement->expression->srcInfo, name));
140+
new IR::StringLiteral(keyElement->expression->srcInfo, name), false);
141141
return keyElement;
142142
}
143143

frontends/p4/toP4/toP4.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -1126,15 +1126,17 @@ bool ToP4::preorder(const IR::SwitchStatement* s) {
11261126
bool ToP4::preorder(const IR::Annotation * a) {
11271127
builder.append("@");
11281128
builder.append(a->name);
1129+
char open = a->structured ? '[' : '(';
1130+
char close = a->structured ? ']' : ')';
11291131
if (!a->expr.empty()) {
1130-
builder.append("(");
1132+
builder.append(open);
11311133
setVecSep(", ");
11321134
preorder(&a->expr);
11331135
doneVec();
1134-
builder.append(")");
1136+
builder.append(close);
11351137
}
11361138
if (!a->kv.empty()) {
1137-
builder.append("(");
1139+
builder.append(open);
11381140
bool first = true;
11391141
for (auto kvp : a->kv) {
11401142
if (!first)
@@ -1144,13 +1146,16 @@ bool ToP4::preorder(const IR::Annotation * a) {
11441146
builder.append("=");
11451147
visit(kvp->expression);
11461148
}
1147-
builder.append(")");
1149+
builder.append(close);
1150+
}
1151+
if (a->expr.empty() && a->kv.empty() && a->structured) {
1152+
builder.append("[]");
11481153
}
11491154
if (!a->body.empty() && a->expr.empty() && a->kv.empty()) {
11501155
// Have an unparsed annotation.
11511156
// We could be prettier here with smarter logic, but let's do the easy
11521157
// thing by separating every token with a space.
1153-
builder.append("(");
1158+
builder.append(open);
11541159
bool first = true;
11551160
for (auto tok : a->body) {
11561161
if (!first) builder.append(" ");
@@ -1162,7 +1167,7 @@ bool ToP4::preorder(const IR::Annotation * a) {
11621167
builder.append(tok->text);
11631168
if (haveStringLiteral) builder.append("\"");
11641169
}
1165-
builder.append(")");
1170+
builder.append(close);
11661171
}
11671172
builder.spc();
11681173
return false;

frontends/p4/typeChecking/typeChecker.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,31 @@ TypeInference::assignment(const IR::Node* errorPosition, const IR::Type* destTyp
760760
return sourceExpression;
761761
}
762762

763+
const IR::Node* TypeInference::postorder(IR::Annotation* annotation) {
764+
auto checkAnnotation = [this] (const IR::Expression* e) {
765+
if (!isCompileTimeConstant(e))
766+
typeError("%1%: structured annotation must be compile-time constant values", e);
767+
auto t = getType(e);
768+
if (!t->is<IR::Type_InfInt>() &&
769+
!t->is<IR::Type_String>() &&
770+
!t->is<IR::Type_Boolean>())
771+
typeError("%1%: illegal type for structured annotation; must be int, string or bool",
772+
e);
773+
};
774+
775+
if (annotation->structured) {
776+
// If it happens here it was created in the compiler, so it's a bug, not an error.
777+
BUG_CHECK(annotation->expr.empty() || annotation->kv.empty(),
778+
"%1%: structured annotations cannot contain expressions and kv-pairs",
779+
annotation);
780+
for (auto e : annotation->expr)
781+
checkAnnotation(e);
782+
for (auto e : annotation->kv)
783+
checkAnnotation(e->expression);
784+
}
785+
return annotation;
786+
}
787+
763788
const IR::Node* TypeInference::postorder(IR::Declaration_Constant* decl) {
764789
if (done()) return decl;
765790
auto type = getTypeType(decl->type);

frontends/p4/typeChecking/typeChecker.h

+1
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ class TypeInference : public Transform {
280280
const IR::Node* postorder(IR::KeyElement* elem) override;
281281
const IR::Node* postorder(IR::Property* elem) override;
282282
const IR::Node* postorder(IR::SelectCase* elem) override;
283+
const IR::Node* postorder(IR::Annotation* annotation) override;
283284

284285
Visitor::profile_t init_apply(const IR::Node* node) override;
285286
void end_apply(const IR::Node* Node) override;

frontends/p4/uniqueNames.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ addNameAnnotation(cstring name, const IR::Annotations* annos) {
7676
if (annos == nullptr)
7777
annos = IR::Annotations::empty;
7878
return annos->addAnnotationIfNew(IR::Annotation::nameAnnotation,
79-
new IR::StringLiteral(name));
79+
new IR::StringLiteral(name), false);
8080
}
8181

8282
UniqueNames::UniqueNames(ReferenceMap* refMap) : renameMap(new RenameMap) {

frontends/p4/validateParsedProgram.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,20 @@ void ValidateParsedProgram::postorder(const IR::Method* m) {
5050
}
5151
}
5252

53+
/// Structured annotations cannot reuse names
54+
void ValidateParsedProgram::postorder(const IR::Annotations* annotations) {
55+
std::multiset<cstring> namesUsed;
56+
for (auto a : annotations->annotations)
57+
namesUsed.emplace(a->name);
58+
59+
for (auto a : annotations->annotations) {
60+
if (!a->structured)
61+
continue;
62+
if (namesUsed.count(a->name) > 1)
63+
::error(ErrorType::ERR_DUPLICATE, "%1%: duplicate name for structured annotation", a);
64+
}
65+
}
66+
5367
/// Struct field names cannot be underscore
5468
void ValidateParsedProgram::postorder(const IR::StructField* f) {
5569
if (f->name.isDontCare())

frontends/p4/validateParsedProgram.h

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class ValidateParsedProgram final : public Inspector {
5959
public:
6060
ValidateParsedProgram()
6161
{ setName("ValidateParsedProgram"); }
62+
void postorder(const IR::Annotations* annotations) override;
6263
void postorder(const IR::P4Program* program) override;
6364
void postorder(const IR::Constant* c) override;
6465
void postorder(const IR::SwitchStatement* statement) override;

frontends/parsers/p4/p4parser.ypp

+5-1
Original file line numberDiff line numberDiff line change
@@ -459,10 +459,14 @@ annotation
459459
$$ = new IR::Annotation(@1, *$2, body); }
460460
| "@" name "(" annotationBody ")"
461461
{ $$ = new IR::Annotation(@1, *$2, *$4); }
462+
| "@" name "[" expressionList "]"
463+
{ $$ = new IR::Annotation(@1, *$2, *$4, true); }
464+
| "@" name "[" kvList "]"
465+
{ $$ = new IR::Annotation(@1, *$2, *$4, true); }
462466
// Experimental: backwards compatibility with P4-14 pragmas (which
463467
// themselves are experimental!)
464468
| PRAGMA name annotationBody END_PRAGMA
465-
{ $$ = new IR::Annotation(@1, *$2, *$3); }
469+
{ $$ = new IR::Annotation(@1, *$2, *$3, false); }
466470
;
467471

468472
annotationBody

0 commit comments

Comments
 (0)