From cce4c5bc19fc1bc58b483be6c289d9b91dedb582 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Mon, 21 Oct 2024 23:04:14 -0700 Subject: [PATCH 1/5] Simplify annotations query Signed-off-by: Anton Korobeynikov --- backends/bmv2/simple_switch/simpleSwitch.cpp | 2 +- backends/dpdk/dpdkAsmOpt.h | 2 +- backends/dpdk/dpdkContext.cpp | 9 ++++----- backends/dpdk/spec.cpp | 4 ++-- backends/tc/backend.cpp | 20 ++++++++----------- backends/tc/ebpfCodeGen.cpp | 3 +-- frontends/common/constantFolding.h | 2 +- frontends/p4-14/fromv1.0/programStructure.cpp | 2 +- frontends/p4/deprecated.cpp | 2 +- frontends/p4/reassociation.h | 2 +- frontends/p4/simplifyDefUse.h | 2 +- frontends/p4/strengthReduction.h | 2 +- frontends/p4/typeChecking/typeCheckDecl.cpp | 2 +- ir/base.def | 4 +++- 14 files changed, 27 insertions(+), 31 deletions(-) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 2a1b83ec7fe..fd100807e4d 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -1038,7 +1038,7 @@ void SimpleSwitchBackend::createRecirculateFieldsList(ConversionContext *ctxt, LOG2("Scanning user metadata fields for annotations"); for (auto f : userMetaType->fields) { LOG3("Scanning field " << f); - auto anno = f->getAnnotations()->getSingle("field_list"_cs); + auto anno = f->getAnnotation("field_list"_cs); if (anno == nullptr) continue; for (auto e : anno->expr) { diff --git a/backends/dpdk/dpdkAsmOpt.h b/backends/dpdk/dpdkAsmOpt.h index 471eaaabed5..cd18d4e55b2 100644 --- a/backends/dpdk/dpdkAsmOpt.h +++ b/backends/dpdk/dpdkAsmOpt.h @@ -210,7 +210,7 @@ class ShortenTokenLength : public Transform { } const IR::Node *preorder(IR::DpdkStructType *s) override { - if (s->getAnnotations()->getSingle("__packet_data__"_cs)) { + if (s->getAnnotation("__packet_data__"_cs)) { s->name = shortenString(s->name); IR::IndexedVector changedFields; for (auto field : s->fields) { diff --git a/backends/dpdk/dpdkContext.cpp b/backends/dpdk/dpdkContext.cpp index 8390b0fbbbf..a48dc456bc1 100644 --- a/backends/dpdk/dpdkContext.cpp +++ b/backends/dpdk/dpdkContext.cpp @@ -52,7 +52,7 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { auto size = tbl->getSizeProperty(); tblAttr.size = dpdk_default_table_size; if (size) tblAttr.size = size->asUnsigned(); - auto hidden = tbl->annotations->getSingle(IR::Annotation::hiddenAnnotation); + auto hidden = tbl->getAnnotation(IR::Annotation::hiddenAnnotation); auto selector = tbl->properties->getProperty("selector"); tblAttr.is_add_on_miss = false; tblAttr.idle_timeout_with_auto_delete = false; @@ -247,10 +247,9 @@ void DpdkContextGenerator::setActionAttributes(const IR::P4Table *tbl) { bool can_be_default_action = !has_constant_default_action; // First, check for action annotations - auto actAnnot = action_decl->annotations; - auto table_only_annot = actAnnot->getSingle(IR::Annotation::tableOnlyAnnotation); - auto default_only_annot = actAnnot->getSingle(IR::Annotation::defaultOnlyAnnotation); - auto hidden = actAnnot->getSingle(IR::Annotation::hiddenAnnotation); + auto table_only_annot = action_decl->getAnnotation(IR::Annotation::tableOnlyAnnotation); + auto default_only_annot = action_decl->getAnnotation(IR::Annotation::defaultOnlyAnnotation); + auto hidden = action_decl->getAnnotation(IR::Annotation::hiddenAnnotation); if (table_only_annot) { can_be_default_action = false; diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index 60083e567c4..d23ed1b7aed 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -223,7 +223,7 @@ std::ostream &IR::DpdkHeaderInstance::toSpec(std::ostream &out) const { } std::ostream &IR::DpdkStructType::toSpec(std::ostream &out) const { - if (getAnnotations()->getSingle("__packet_data__"_cs)) { + if (getAnnotation("__packet_data__"_cs)) { for (auto it = fields.begin(); it != fields.end(); ++it) { add_comment(out, (*it)->name.toString()); if (auto t = (*it)->type->to()) { @@ -270,7 +270,7 @@ std::ostream &IR::DpdkStructType::toSpec(std::ostream &out) const { out << std::endl; } out << "}" << std::endl; - if (getAnnotations()->getSingle("__metadata__"_cs)) { + if (getAnnotation("__metadata__"_cs)) { out << "metadata instanceof " << name << std::endl; } } diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 5f149d09e7f..7fedba821cb 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -304,11 +304,8 @@ void ConvertToBackendIR::updateConstEntries(const IR::P4Table *t, IR::TCTable *t for (size_t itr = 0; itr < keyset->components.size(); itr++) { auto keyElement = keys->keyElements.at(itr); auto keyString = keyElement->expression->toString(); - auto annotations = keyElement->getAnnotations(); - if (annotations) { - if (auto anno = annotations->getSingle("name"_cs)) { - keyString = anno->expr.at(0)->to()->value; - } + if (auto anno = keyElement->getAnnotation("name"_cs)) { + keyString = anno->expr.at(0)->to()->value; } auto keySetElement = keyset->components.at(itr); auto key = keySetElement->toString(); @@ -385,8 +382,7 @@ void ConvertToBackendIR::updateDefaultMissAction(const IR::P4Table *t, IR::TCTab } bool isTCMayOverrideMiss = false; const IR::Annotation *overrideAnno = - defaultActionProperty->getAnnotations()->getSingle( - ParseTCAnnotations::tcMayOverride); + defaultActionProperty->getAnnotation(ParseTCAnnotations::tcMayOverride); if (overrideAnno) { isTCMayOverrideMiss = true; } @@ -876,12 +872,12 @@ safe_vector ConvertToBackendIR::processExternConstructor( for (unsigned itr = 0; itr < params->size(); itr++) { auto parameter = params->getParameter(itr); auto exp = decl->arguments->at(itr)->expression; - if (parameter->getAnnotations()->getSingle(ParseTCAnnotations::tc_numel)) { + if (parameter->getAnnotation(ParseTCAnnotations::tc_numel)) { if (exp->is()) { instance->is_num_elements = true; instance->num_elements = exp->to()->asInt(); } - } else if (parameter->getAnnotations()->getSingle(ParseTCAnnotations::tc_init_val)) { + } else if (parameter->getAnnotation(ParseTCAnnotations::tc_init_val)) { // TODO: Process tc_init_val. } else { /* If a parameter is not annoated by tc_init or tc_numel then it is emitted as @@ -1022,7 +1018,7 @@ safe_vector ConvertToBackendIR::HandleTypeNameStructField( if (auto param_struct = param_val->to()) { for (auto f : param_struct->fields) { cstring ptype = absl::StrCat("bit", f->type->width_bits()); - if (auto anno = f->getAnnotations()->getSingle(ParseTCAnnotations::tcType)) { + if (auto anno = f->getAnnotation(ParseTCAnnotations::tcType)) { auto expr = anno->expr[0]; if (auto typeLiteral = expr->to()) { ptype = typeLiteral->value; @@ -1034,7 +1030,7 @@ safe_vector ConvertToBackendIR::HandleTypeNameStructField( } } else { cstring ptype = absl::StrCat("bit", param_val->width_bits()); - if (auto anno = field->getAnnotations()->getSingle(ParseTCAnnotations::tcType)) { + if (auto anno = field->getAnnotation(ParseTCAnnotations::tcType)) { auto expr = anno->expr[0]; if (auto typeLiteral = expr->to()) { ptype = typeLiteral->value; @@ -1057,7 +1053,7 @@ bool ConvertToBackendIR::hasExecuteMethod(const IR::Type_Extern *extn) { } auto method = gd->getNode()->to(); const IR::Annotation *execAnnotation = - method->getAnnotations()->getSingle(ParseTCAnnotations::tc_md_exec); + method->getAnnotation(ParseTCAnnotations::tc_md_exec); if (execAnnotation) { return true; } diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index 052cc6f2db0..eb3087406a4 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -1607,8 +1607,7 @@ const IR::P4Action *ControlBodyTranslatorPNA::GetAddOnMissHitAction(cstring acti auto adecl = control->program->refMap->getDeclaration(a->getPath(), true); auto action = adecl->getNode()->to(); if (action->name.originalName == actionName) { - auto annotations = a->getAnnotations(); - if (annotations && annotations->getSingle("defaultonly"_cs)) { + if (a->getAnnotation("defaultonly"_cs)) { ::P4::error(ErrorType::ERR_UNEXPECTED, "add_entry hit action %1% cannot be annotated with defaultonly.", actionName); diff --git a/frontends/common/constantFolding.h b/frontends/common/constantFolding.h index 904b791d878..befd022fac3 100644 --- a/frontends/common/constantFolding.h +++ b/frontends/common/constantFolding.h @@ -174,7 +174,7 @@ class DoConstantFolding : public Transform, public ResolutionContext { const IR::Node *preorder(IR::ArrayIndex *e) override; const IR::Node *preorder(IR::SwitchCase *c) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); + if (bs->getAnnotation("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/p4-14/fromv1.0/programStructure.cpp b/frontends/p4-14/fromv1.0/programStructure.cpp index 5ce120a494d..de5c041aa1a 100644 --- a/frontends/p4-14/fromv1.0/programStructure.cpp +++ b/frontends/p4-14/fromv1.0/programStructure.cpp @@ -555,7 +555,7 @@ const IR::ParserState *ProgramStructure::convertParser( value_sets_implemented.emplace(first->path->name); auto type = explodeType(fieldTypes); - auto sizeAnnotation = value_set->annotations->getSingle("parser_value_set_size"_cs); + auto sizeAnnotation = value_set->getAnnotation("parser_value_set_size"_cs); const IR::Constant *sizeConstant; if (sizeAnnotation) { if (sizeAnnotation->expr.size() != 1) { diff --git a/frontends/p4/deprecated.cpp b/frontends/p4/deprecated.cpp index 02a04e9cdff..f29ef72867f 100644 --- a/frontends/p4/deprecated.cpp +++ b/frontends/p4/deprecated.cpp @@ -20,7 +20,7 @@ namespace P4 { void Deprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR::Node *errorNode) { if (annotated == nullptr) return; - auto anno = annotated->getAnnotations()->getSingle(IR::Annotation::deprecatedAnnotation); + auto anno = annotated->getAnnotation(IR::Annotation::deprecatedAnnotation); if (anno == nullptr) return; std::string message; diff --git a/frontends/p4/reassociation.h b/frontends/p4/reassociation.h index c4ae466ad78..8825f36c4d8 100644 --- a/frontends/p4/reassociation.h +++ b/frontends/p4/reassociation.h @@ -43,7 +43,7 @@ class Reassociation final : public Transform { const IR::Node *postorder(IR::BAnd *expr) override { return reassociate(expr); } const IR::Node *postorder(IR::BXor *expr) override { return reassociate(expr); } const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); + if (bs->getAnnotation("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/p4/simplifyDefUse.h b/frontends/p4/simplifyDefUse.h index ebee8e1d4c3..b8c88fbc3b5 100644 --- a/frontends/p4/simplifyDefUse.h +++ b/frontends/p4/simplifyDefUse.h @@ -54,7 +54,7 @@ class RemoveHidden : public Transform { const IR::Node *postorder(IR::BlockStatement *stat) override { if (!stat->components.empty()) return stat; if (stat->annotations->size() != 1) return stat; - auto anno = stat->annotations->getSingle(IR::Annotation::hiddenAnnotation); + auto anno = stat->getAnnotation(IR::Annotation::hiddenAnnotation); if (!anno) return stat; // Lose the annotation. return new IR::BlockStatement(stat->srcInfo); diff --git a/frontends/p4/strengthReduction.h b/frontends/p4/strengthReduction.h index 01ef0b10048..79eea6ff837 100644 --- a/frontends/p4/strengthReduction.h +++ b/frontends/p4/strengthReduction.h @@ -111,7 +111,7 @@ class DoStrengthReduction final : public Transform { const IR::Node *postorder(IR::ArrayIndex *expr) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->annotations->getSingle("disable_optimization"_cs)) prune(); + if (bs->getAnnotation("disable_optimization"_cs)) prune(); return bs; } }; diff --git a/frontends/p4/typeChecking/typeCheckDecl.cpp b/frontends/p4/typeChecking/typeCheckDecl.cpp index 5cf30ccb2fd..96190ac8f09 100644 --- a/frontends/p4/typeChecking/typeCheckDecl.cpp +++ b/frontends/p4/typeChecking/typeCheckDecl.cpp @@ -213,7 +213,7 @@ bool TypeInferenceBase::checkAbstractMethods(const IR::Declaration_Instance *ins } bool rv = true; for (const auto &vm : virt) { - if (!vm.second->annotations->getSingle("optional"_cs)) { + if (!vm.second->getAnnotation("optional"_cs)) { typeError("%1%: %2% abstract method not implemented", inst, vm.second); rv = false; } diff --git a/ir/base.def b/ir/base.def index 4b9ceea30e0..bab94d3c0ec 100644 --- a/ir/base.def +++ b/ir/base.def @@ -375,7 +375,9 @@ class Annotations { interface IAnnotated { virtual Annotations getAnnotations() const = 0; Annotation getAnnotation(cstring name) const override { - return getAnnotations()->getSingle(name); } + auto annotations = getAnnotations(); + return annotations ? annotations->getSingle(name) : nullptr; + } } interface IInstance { From 4b457aaf4627334fc08180b7527b5165f3c3aa0a Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Tue, 22 Oct 2024 10:56:17 -0700 Subject: [PATCH 2/5] Rearrange the fields to reduce the size of object. Fix broken initializer_list while there Signed-off-by: Anton Korobeynikov --- ir/base.def | 71 ++++++++++++++++++++++++++++------------------------- ir/vector.h | 2 +- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/ir/base.def b/ir/base.def index bab94d3c0ec..7b77cae1fa2 100644 --- a/ir/base.def +++ b/ir/base.def @@ -223,54 +223,39 @@ class AnnotationToken { class Annotation { ID name; - /// An unparsed annotation body - inline Vector body; - - /// Whether the annotation body needs to be parsed. - /// Invariant: if this is true, then expr and kv must both be empty. If the - /// annotation is compiler-generated (e.g., derived from a P4₁₄ pragma), - /// then needsParsing will be false and the body will be empty, but expr or - /// kv may be populated. - bool needsParsing; - - /// Annotations that are simple expressions - inline Vector expr; - - /// Annotations described as key-value pairs - inline IndexedVector kv; - - /// If this is true this is a structured annotation, and there are some - /// constraints on its contents. - bool structured; - Annotation { if (!srcInfo) srcInfo = name.srcInfo; } /// For annotations parsed from P4-16 source. Annotation(Util::SourceInfo si, ID n, const Vector &a) - : Node(si), name(n), body(a), needsParsing(true), structured(false) {} + : Node(si), name(n), body(a), needsParsing(true), structured(false) {} // Used by JSON loader Annotation(Util::SourceInfo si, ID n, const Vector &a, bool structured) - : Node(si), name(n), body(a), needsParsing(true), structured(structured) {} + : Node(si), name(n), body(a), needsParsing(true), structured(structured) {} // The remaining constructors are for compiler-generated annotations. Annotation(Util::SourceInfo si, ID n, - const std::initializer_list &a, bool structured = false) - : Node(si), name(n), needsParsing(false), expr(a), structured(structured) {} + std::initializer_list a, bool structured = false) + : Node(si), name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(Util::SourceInfo si, ID n, const IR::Vector &a, bool structured = false) - : Node(si), name(n), needsParsing(false), expr(a), structured(structured) {} + : Node(si), name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(Util::SourceInfo si, ID n, const IndexedVector &kv, bool structured = false) - : Node(si), name(n), needsParsing(false), kv(kv), structured(structured) {} - Annotation(ID n, const std::initializer_list &a, bool structured = false) - : name(n), needsParsing(false), expr(a), structured(structured) {} + : Node(si), name(n), kv(kv), needsParsing(false), structured(structured) {} + Annotation(ID n, std::initializer_list a, bool structured = false) + : name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(ID n, const IR::Vector &a, bool structured = false) - : name(n), needsParsing(false), expr(a), structured(structured) {} + : name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(ID n, intmax_t v, bool structured = false) - : name(n), needsParsing(false), structured(structured) { - expr.push_back(new Constant(v)); } + : name(n), needsParsing(false), structured(structured) { + expr.push_back(new Constant(v)); + } + // Cannot use delegating ctors are ir-generator does not support initializer lists + // : Annotation(n, { new Constant(v) }, structured) { } Annotation(ID n, cstring v, bool structured = false) - : name(n), needsParsing(false), structured(structured) { - expr.push_back(new StringLiteral(v)); } + : name(n), needsParsing(false), structured(structured) { + expr.push_back(new StringLiteral(v)); + } + // : Annotation(n, { new StringLiteral(v) }, structured) { } static const cstring nameAnnotation; /// Indicates the control-plane name. static const cstring tableOnlyAnnotation; /// Action cannot be a default_action. @@ -318,6 +303,26 @@ class Annotation { return Kind::StructuredKVList; return Kind::StructuredEmpty; } + + /// An unparsed annotation body + inline Vector body; + + /// Annotations that are simple expressions + inline Vector expr; + + /// Annotations described as key-value pairs + inline IndexedVector kv; + + /// Whether the annotation body needs to be parsed. + /// Invariant: if this is true, then expr and kv must both be empty. If the + /// annotation is compiler-generated (e.g., derived from a P4₁₄ pragma), + /// then needsParsing will be false and the body will be empty, but expr or + /// kv may be populated. + bool needsParsing; + + /// If this is true this is a structured annotation, and there are some + /// constraints on its contents. + bool structured; } /// There can be several annotations with the same "name", so this is a vector. diff --git a/ir/vector.h b/ir/vector.h index 3f6da26bb92..beb0f53d4a7 100644 --- a/ir/vector.h +++ b/ir/vector.h @@ -69,7 +69,7 @@ class Vector : public VectorBase { Vector &operator=(Vector &&) = default; explicit Vector(const T *a) { vec.emplace_back(std::move(a)); } explicit Vector(const safe_vector &a) { vec.insert(vec.end(), a.begin(), a.end()); } - Vector(const std::initializer_list &a) : vec(a) {} + Vector(std::initializer_list a) : vec(a) {} static Vector *fromJSON(JSONLoader &json); typedef typename safe_vector::iterator iterator; typedef typename safe_vector::const_iterator const_iterator; From 9e3ddebd96f35693b2738a184d36fd3f15cc373f Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Tue, 22 Oct 2024 11:26:15 -0700 Subject: [PATCH 3/5] Reduce the overheads Signed-off-by: Anton Korobeynikov --- ir/base.def | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ir/base.def b/ir/base.def index 7b77cae1fa2..3a90915dec8 100644 --- a/ir/base.def +++ b/ir/base.def @@ -313,16 +313,18 @@ class Annotation { /// Annotations described as key-value pairs inline IndexedVector kv; +#emit /// Whether the annotation body needs to be parsed. /// Invariant: if this is true, then expr and kv must both be empty. If the /// annotation is compiler-generated (e.g., derived from a P4₁₄ pragma), /// then needsParsing will be false and the body will be empty, but expr or /// kv may be populated. - bool needsParsing; + bool needsParsing : 1; /// If this is true this is a structured annotation, and there are some /// constraints on its contents. - bool structured; + bool structured : 1; +#end } /// There can be several annotations with the same "name", so this is a vector. From 1600e735b420ab6181294e2195c6a7153945b874 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Fri, 1 Nov 2024 15:43:07 +0300 Subject: [PATCH 4/5] Remove IR::Annotations and make IAnnotated to carry annotations inline. Lots of cleanups and fixes here and there Signed-off-by: Anton Korobeynikov --- backends/bmv2/common/backend.h | 7 +- backends/dpdk/dpdk.def | 6 +- backends/dpdk/dpdkArch.cpp | 42 ++--- backends/dpdk/dpdkMetadata.cpp | 7 +- backends/dpdk/dpdkUtils.cpp | 16 +- backends/dpdk/spec.cpp | 5 +- backends/ebpf/target.h | 10 +- backends/graphs/controls.cpp | 2 +- backends/p4fmt/p4formatter.cpp | 151 ++++------------ backends/p4fmt/p4formatter.h | 2 +- .../p4tools/common/compiler/reachability.cpp | 28 +-- backends/p4tools/common/lib/table_utils.cpp | 5 +- .../modules/smith/common/declarations.cpp | 7 +- .../modules/smith/common/declarations.h | 2 +- .../p4tools/modules/smith/common/table.cpp | 6 +- .../testgen/core/small_step/table_stepper.cpp | 2 +- .../targets/bmv2/p4_refers_to_parser.cpp | 16 +- .../targets/bmv2/p4runtime_translation.cpp | 22 +-- backends/tc/backend.cpp | 42 ++--- backends/tc/ebpfCodeGen.cpp | 14 +- backends/tc/introspection.cpp | 6 +- control-plane/addMissingIds.cpp | 42 +---- control-plane/flattenHeader.cpp | 18 +- control-plane/flattenHeader.h | 6 +- control-plane/p4RuntimeArchHandler.h | 4 +- control-plane/p4RuntimeSerializer.cpp | 4 +- control-plane/p4RuntimeSymbolTable.cpp | 29 ++-- control-plane/p4RuntimeSymbolTable.h | 2 +- control-plane/typeSpecConverter.cpp | 4 +- frontends/common/constantFolding.h | 2 +- .../resolveReferences/resolveReferences.cpp | 3 +- frontends/p4-14/fromv1.0/converters.cpp | 19 +- frontends/p4-14/fromv1.0/converters.h | 18 +- frontends/p4-14/fromv1.0/programStructure.cpp | 141 +++++++-------- frontends/p4-14/fromv1.0/programStructure.h | 24 +-- frontends/p4-14/header_type.cpp | 18 +- frontends/p4-14/ir-v1.def | 52 +++--- frontends/p4/actionsInlining.cpp | 6 +- frontends/p4/createBuiltins.cpp | 2 +- frontends/p4/deprecated.cpp | 2 +- frontends/p4/directCalls.cpp | 8 +- frontends/p4/inlining.cpp | 48 ++---- frontends/p4/localizeActions.cpp | 24 +-- frontends/p4/methodInstance.cpp | 2 +- frontends/p4/reassociation.h | 4 +- frontends/p4/sideEffects.h | 30 +--- frontends/p4/simplify.cpp | 2 +- frontends/p4/simplifyDefUse.h | 9 +- frontends/p4/simplifyParsers.cpp | 8 +- frontends/p4/strengthReduction.h | 4 +- frontends/p4/tableKeyNames.cpp | 8 +- frontends/p4/toP4/toP4.cpp | 163 +++++------------- frontends/p4/toP4/toP4.h | 2 +- frontends/p4/typeChecking/typeCheckDecl.cpp | 2 +- frontends/p4/typeChecking/typeCheckExpr.cpp | 9 +- frontends/p4/typeChecking/typeCheckStmt.cpp | 6 +- frontends/p4/uniqueNames.cpp | 7 - frontends/p4/uniqueNames.h | 7 +- frontends/p4/validateParsedProgram.cpp | 16 +- frontends/p4/validateParsedProgram.h | 5 +- frontends/parsers/p4/p4parser.ypp | 97 +++++------ frontends/parsers/parserDriver.cpp | 7 - frontends/parsers/parserDriver.h | 4 - frontends/parsers/v1/v1parser.ypp | 56 +++--- ir/CMakeLists.txt | 2 + ir/annotations.cpp | 85 +++++++++ ir/annotations.h | 41 +++++ ir/base.cpp | 9 +- ir/base.def | 113 ++++++------ ir/ir.cpp | 4 +- ir/ir.def | 80 +++++---- ir/node.h | 1 - ir/type.cpp | 19 -- ir/type.def | 52 +++--- ir/vector.h | 8 + ir/visitor.cpp | 18 +- midend/actionSynthesis.cpp | 11 +- midend/def_use.h | 2 +- midend/eliminateSwitch.cpp | 12 +- midend/flattenInterfaceStructs.h | 32 ++-- midend/has_side_effects.h | 7 +- midend/local_copyprop.cpp | 4 +- midend/nestedStructs.cpp | 6 +- midend/unrollLoops.cpp | 7 +- .../structured-annotation-e1.p4-stderr | 3 - .../pna-action-selector-1.p4.spec | 2 +- .../pna-dpdk-add_on_miss0.p4.spec | 2 +- .../pna-dpdk-add_on_miss1.p4.spec | 2 +- .../pna-dpdk-header-stack-assignment.p4.spec | 4 +- .../pna-example-tunnel.p4.spec | 4 +- .../psa-dpdk-128bitCast.p4.spec | 2 +- .../psa-dpdk-hdr-field-non-align.p4.spec | 2 +- .../psa-dpdk-large-header-fields.p4.spec | 2 +- .../psa-dpdk-large-struct-fields.p4.spec | 2 +- .../psa-dpdk-struct-field.p4.spec | 2 +- .../psa-example-incremental-checksum.p4.spec | 2 +- 96 files changed, 839 insertions(+), 1025 deletions(-) create mode 100644 ir/annotations.cpp create mode 100644 ir/annotations.h diff --git a/backends/bmv2/common/backend.h b/backends/bmv2/common/backend.h index 2b2c583bc22..8c3032e3925 100644 --- a/backends/bmv2/common/backend.h +++ b/backends/bmv2/common/backend.h @@ -23,6 +23,7 @@ limitations under the License. #include "frontends/common/model.h" #include "frontends/p4/coreLibrary.h" #include "helpers.h" +#include "ir/annotations.h" #include "ir/ir.h" #include "lib/cstring.h" #include "lib/error.h" @@ -167,10 +168,10 @@ class RenameUserMetadata : public Transform { else suffix = "."_cs + f->name; cstring newName = namePrefix + suffix; - auto stringLit = new IR::StringLiteral(newName); LOG2("Renaming " << f << " to " << newName); - auto annos = f->annotations->addOrReplace(IR::Annotation::nameAnnotation, stringLit); - auto field = new IR::StructField(f->srcInfo, f->name, annos, f->type); + auto field = new IR::StructField( + f->srcInfo, f->name, IR::Annotations::setNameAnnotation(newName, f->annotations), + f->type); fields.push_back(field); } diff --git a/backends/dpdk/dpdk.def b/backends/dpdk/dpdk.def index fd9dd896b49..80603b3ab87 100644 --- a/backends/dpdk/dpdk.def +++ b/backends/dpdk/dpdk.def @@ -34,12 +34,14 @@ abstract DpdkAsmStatement : IDPDKNode { std::ostream& toSpec(std::ostream& out) const override; } -class DpdkAction { - optional Annotations annotations = Annotations::empty; +class DpdkAction : IAnnotated { + optional inline Vector annotations; inline IndexedVector statements; inline ID name; inline ParameterList para; std::ostream& toSpec(std::ostream& out) const; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } #nodbprint } diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index 7c081300223..e6ca7e0a0c7 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -673,12 +673,11 @@ bool CollectTableInfo::preorder(const IR::Key *keys) { const IR::Node *InjectJumboStruct::preorder(IR::Type_Struct *s) { if (s->name == structure->local_metadata_type) { - auto *annotations = new IR::Annotations({new IR::Annotation(IR::ID("__metadata__"), {})}); - return new IR::Type_Struct(s->name, annotations, structure->compiler_added_fields); + return new IR::Type_Struct(s->name, {new IR::Annotation(IR::ID("__metadata__"), {})}, + structure->compiler_added_fields); } else if (s->name == structure->header_type) { - auto *annotations = - new IR::Annotations({new IR::Annotation(IR::ID("__packet_data__"), {})}); - return new IR::Type_Struct(s->name, annotations, s->fields); + return new IR::Type_Struct(s->name, {new IR::Annotation(IR::ID("__packet_data__"), {})}, + s->fields); } return s; } @@ -1835,13 +1834,12 @@ std::tuple SplitP4TableCommon::create_mat const IR::P4Action *SplitP4TableCommon::create_action(cstring actionName, cstring group_id, cstring param) { - auto hidden = new IR::Annotations(); - hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); auto set_id = new IR::AssignmentStatement(new IR::PathExpression(group_id), new IR::PathExpression(param)); auto parameter = new IR::Parameter(param, IR::Direction::None, IR::Type_Bits::get(32)); - auto action = new IR::P4Action(actionName, hidden, new IR::ParameterList({parameter}), - new IR::BlockStatement({set_id})); + auto action = + new IR::P4Action(actionName, {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}, + new IR::ParameterList({parameter}), new IR::BlockStatement({set_id})); return action; } @@ -1856,12 +1854,11 @@ const IR::P4Table *SplitP4TableCommon::create_member_table(const IR::P4Table *tb IR::IndexedVector member_properties; member_properties.push_back(new IR::Property("key", new IR::Key(member_keys), false)); - auto hidden = new IR::Annotations(); - hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); + IR::Vector hidden(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); auto nameAnnon = tbl->getAnnotation(IR::Annotation::nameAnnotation); cstring nameA = nameAnnon->getSingleString(); cstring memName = nameA.replace(nameA.findlast('.'), "." + memberTableName); - hidden->addAnnotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(memName), false); + hidden.emplace_back(IR::Annotation::nameAnnotation, memName); IR::IndexedVector memberActionList; for (auto action : tbl->getActionList()->actionList) memberActionList.push_back(action); @@ -1874,10 +1871,8 @@ const IR::P4Table *SplitP4TableCommon::create_member_table(const IR::P4Table *tb member_properties.push_back(new IR::Property( "default_action", new IR::ExpressionValue(tbl->getDefaultAction()), false)); - auto member_table = - new IR::P4Table(memberTableName, hidden, new IR::TableProperties(member_properties)); - - return member_table; + return new IR::P4Table(memberTableName, std::move(hidden), + new IR::TableProperties(member_properties)); } const IR::P4Table *SplitP4TableCommon::create_group_table(const IR::P4Table *tbl, @@ -1891,12 +1886,11 @@ const IR::P4Table *SplitP4TableCommon::create_group_table(const IR::P4Table *tbl selector_keys.push_back(key); } } - auto hidden = new IR::Annotations(); - hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); + IR::Vector hidden(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); auto nameAnnon = tbl->getAnnotation(IR::Annotation::nameAnnotation); cstring nameA = nameAnnon->getSingleString(); cstring selName = nameA.replace(nameA.findlast('.'), "." + selectorTableName); - hidden->addAnnotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(selName), false); + hidden.emplace_back(IR::Annotation::nameAnnotation, selName); IR::IndexedVector selector_properties; selector_properties.push_back(new IR::Property("selector", new IR::Key(selector_keys), false)); selector_properties.push_back(new IR::Property( @@ -2908,8 +2902,8 @@ const IR::Node *ElimHeaderCopy::postorder(IR::Member *m) { const IR::Node *DpdkAddPseudoHeaderDecl::preorder(IR::P4Program *program) { if (is_all_args_header) return program; - auto *annotations = new IR::Annotations({new IR::Annotation(IR::ID("__pseudo_header__"), {})}); - const IR::Type_Header *pseudo_hdr = new IR::Type_Header(pseudoHeaderTypeName, annotations); + const IR::Type_Header *pseudo_hdr = new IR::Type_Header( + pseudoHeaderTypeName, {new IR::Annotation(IR::ID("__pseudo_header__"), {})}); allTypeDecls.push_back(pseudo_hdr); allTypeDecls.append(program->objects); program->objects = allTypeDecls; @@ -2922,11 +2916,9 @@ const IR::Node *DpdkAddPseudoHeaderDecl::preorder(IR::Type_Struct *st) { bool header_found = isHeadersStruct(st); if (header_found) { IR::IndexedVector fields; - auto *annotations = - new IR::Annotations({new IR::Annotation(IR::ID("__pseudo_header__"), {})}); auto *type = new IR::Type_Name(new IR::Path(pseudoHeaderTypeName)); - const IR::StructField *new_field1 = - new IR::StructField(pseudoHeaderInstanceName, annotations, type); + const IR::StructField *new_field1 = new IR::StructField( + pseudoHeaderInstanceName, {new IR::Annotation(IR::ID("__pseudo_header__"), {})}, type); fields = st->fields; fields.push_back(new_field1); auto *st1 = diff --git a/backends/dpdk/dpdkMetadata.cpp b/backends/dpdk/dpdkMetadata.cpp index 70116b8f48e..1a336938f09 100644 --- a/backends/dpdk/dpdkMetadata.cpp +++ b/backends/dpdk/dpdkMetadata.cpp @@ -60,9 +60,10 @@ IR::DpdkExternDeclaration *DirectionToRegRead::addRegDeclInstance(cstring instan auto spectype = new IR::Type_Specialized(type, typeargs); auto args = new IR::Vector(); args->push_back(new IR::Argument(new IR::Constant(IR::Type::Bits::get(32), 256))); - auto annot = IR::Annotations::empty; - annot->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(instanceName)); - auto decl = new IR::DpdkExternDeclaration(instanceName, annot, spectype, args, nullptr); + auto decl = new IR::DpdkExternDeclaration( + instanceName, + {new IR::Annotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(instanceName))}, + spectype, args, nullptr); return decl; } diff --git a/backends/dpdk/dpdkUtils.cpp b/backends/dpdk/dpdkUtils.cpp index 62f2ffda0ad..115ed5dc6ea 100644 --- a/backends/dpdk/dpdkUtils.cpp +++ b/backends/dpdk/dpdkUtils.cpp @@ -57,14 +57,7 @@ bool isHeadersStruct(const IR::Type_Struct *st) { if (annon) return true; return false; } -bool isMetadataStruct(const IR::Type_Struct *st) { - for (auto anno : st->annotations->annotations) { - if (anno->name == "__metadata__"_cs) { - return true; - } - } - return false; -} +bool isMetadataStruct(const IR::Type_Struct *st) { return st->hasAnnotation("__metadata__"_cs); } bool isMetadataField(const IR::Expression *e) { if (!e->is()) return false; @@ -139,9 +132,10 @@ IR::Declaration_Instance *createRegDeclarationInstance(cstring instanceName, int auto spectype = new IR::Type_Specialized(type, typeargs); auto args = new IR::Vector(); args->push_back(new IR::Argument(new IR::Constant(IR::Type::Bits::get(32), regSize))); - auto annot = IR::Annotations::empty; - annot->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(instanceName)); - auto decl = new IR::Declaration_Instance(instanceName, annot, spectype, args, nullptr); + auto decl = new IR::Declaration_Instance( + instanceName, + {new IR::Annotation(IR::Annotation::nameAnnotation, new IR::StringLiteral(instanceName))}, + spectype, args, nullptr); return decl; } diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index d23ed1b7aed..bde9c0b56c9 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -2,6 +2,7 @@ #include "dpdkArch.h" #include "dpdkAsmOpt.h" #include "dpdkHelpers.h" +#include "ir/annotations.h" #include "ir/dbprint.h" #include "printUtils.h" @@ -414,8 +415,8 @@ std::ostream &IR::DpdkTable::toSpec(std::ostream &out) const { } else { out << "\t\t" << DPDK::toStr(action->expression); } - if (action->annotations->getAnnotation("tableonly"_cs)) out << " @tableonly"; - if (action->annotations->getAnnotation("defaultonly"_cs)) out << " @defaultonly"; + if (action->hasAnnotation(IR::Annotation::tableOnlyAnnotation)) out << " @tableonly"; + if (action->hasAnnotation(IR::Annotation::defaultOnlyAnnotation)) out << " @defaultonly"; out << std::endl; } out << "\t}" << std::endl; diff --git a/backends/ebpf/target.h b/backends/ebpf/target.h index 5cab0095029..b624c2718d6 100644 --- a/backends/ebpf/target.h +++ b/backends/ebpf/target.h @@ -203,10 +203,10 @@ class KernelSamplesTarget : public Target { class P4TCTarget : public KernelSamplesTarget { public: explicit P4TCTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "P4TC"_cs) {} - cstring getByteOrderFromAnnotation(const IR::Vector annotations) const { - for (auto anno : annotations) { + cstring getByteOrderFromAnnotation(const IR::Vector &annotations) const { + for (const auto *anno : annotations) { if (anno->name != "tc_type") continue; - for (auto annoVal : anno->body) { + for (const auto *annoVal : anno->body) { if (annoVal->text == "macaddr" || annoVal->text == "ipv4" || annoVal->text == "ipv6" || annoVal->text == "be16" || annoVal->text == "be32" || annoVal->text == "be64") { @@ -223,14 +223,14 @@ class P4TCTarget : public KernelSamplesTarget { auto type = typeMap->getType(mem->expr, true); if (type->is()) { auto field = type->to()->getField(mem->member); - return getByteOrderFromAnnotation(field->getAnnotations()->annotations); + return getByteOrderFromAnnotation(field->getAnnotations()); } } else if (action) { auto paramList = action->getParameters(); if (paramList != nullptr && !paramList->empty()) { for (auto param : paramList->parameters) { if (param->name.originalName == exp->toString()) { - return getByteOrderFromAnnotation(param->getAnnotations()->annotations); + return getByteOrderFromAnnotation(param->getAnnotations()); } } } diff --git a/backends/graphs/controls.cpp b/backends/graphs/controls.cpp index f49949316e4..d4b3907bd65 100644 --- a/backends/graphs/controls.cpp +++ b/backends/graphs/controls.cpp @@ -254,7 +254,7 @@ bool ControlGraphs::preorder(const IR::Key *key) { for (auto elVec : key->keyElements) { sstream << elVec->matchType->path->name.name << ": "; bool has_name = false; - for (auto ann : elVec->annotations->annotations) { + for (auto ann : elVec->annotations) { if (ann->toString() == "@name") { sstream << ann->getName(); has_name = true; diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 4cdaeaac6f0..ae0968d3b53 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -172,11 +172,16 @@ bool P4Formatter::preorder(const IR::Argument *arg) { return false; } +bool P4Formatter::printAnnotations(const IR::IAnnotated *ann) { + if (!ann->hasAnnotations()) return false; + + visitCollection(ann->getAnnotations(), " ", [&](const auto *anno) { visit(anno); }); + + return true; +} + bool P4Formatter::preorder(const IR::Type_Typedef *t) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("typedef "); visit(t->type); builder.spc(); @@ -186,10 +191,7 @@ bool P4Formatter::preorder(const IR::Type_Typedef *t) { } bool P4Formatter::preorder(const IR::Type_Newtype *t) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("type "); visit(t->type); builder.spc(); @@ -210,10 +212,7 @@ bool P4Formatter::preorder(const IR::Type_BaseList *t) { } bool P4Formatter::preorder(const IR::P4ValueSet *t) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("value_set<"); auto p4type = t->elementType->getP4Type(); CHECK_NULL(p4type); @@ -229,10 +228,7 @@ bool P4Formatter::preorder(const IR::P4ValueSet *t) { } bool P4Formatter::preorder(const IR::Type_Enum *t) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("enum "); builder.append(t->name); builder.spc(); @@ -247,10 +243,7 @@ bool P4Formatter::preorder(const IR::Type_Enum *t) { } bool P4Formatter::preorder(const IR::Type_SerEnum *t) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("enum "); visit(t->type); builder.spc(); @@ -281,10 +274,7 @@ bool P4Formatter::preorder(const IR::TypeParameters *t) { } bool P4Formatter::preorder(const IR::Method *m) { - if (!m->annotations->annotations.empty()) { - visit(m->annotations); - builder.spc(); - } + if (printAnnotations(m)) builder.spc(); const Context *ctx = getContext(); bool standaloneFunction = !ctx || !ctx->node->is(); // standalone function declaration: not in a Vector of methods @@ -305,10 +295,7 @@ bool P4Formatter::preorder(const IR::Method *m) { } bool P4Formatter::preorder(const IR::Function *function) { - if (!function->annotations->annotations.empty()) { - visit(function->annotations); - builder.spc(); - } + if (printAnnotations(function)) builder.spc(); auto t = function->type; BUG_CHECK(t != nullptr, "Function %1% has no type", function); if (t->returnType != nullptr) { @@ -325,10 +312,7 @@ bool P4Formatter::preorder(const IR::Function *function) { bool P4Formatter::preorder(const IR::Type_Extern *t) { if (isDeclaration) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("extern "); } builder.append(t->name); @@ -372,10 +356,7 @@ bool P4Formatter::preorder(const IR::Type_Varbits *t) { bool P4Formatter::preorder(const IR::Type_Package *package) { builder.emitIndent(); - if (!package->annotations->annotations.empty()) { - visit(package->annotations); - builder.spc(); - } + if (printAnnotations(package)) builder.spc(); builder.append("package "); builder.append(package->name); visit(package->typeParameters); @@ -387,10 +368,7 @@ bool P4Formatter::preorder(const IR::Type_Package *package) { bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { if (isDeclaration) { builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.appendFormat("%s ", name); } builder.append(t->name); @@ -412,12 +390,8 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { } for (auto f : t->fields) { - if (f->annotations->size() > 0) { - builder.emitIndent(); - if (!f->annotations->annotations.empty()) { - visit(f->annotations); - } - builder.newline(); + if (f->hasAnnotations()) { + if (printAnnotations(f)) builder.newline(); } builder.emitIndent(); cstring t = get(type, f); @@ -434,10 +408,7 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { bool P4Formatter::preorder(const IR::Type_Parser *t) { builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("parser "); builder.append(t->name); visit(t->typeParameters); @@ -448,10 +419,7 @@ bool P4Formatter::preorder(const IR::Type_Parser *t) { bool P4Formatter::preorder(const IR::Type_Control *t) { builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("control "); builder.append(t->name); visit(t->typeParameters); @@ -489,10 +457,7 @@ bool P4Formatter::preorder(const IR::StringLiteral *s) { } bool P4Formatter::preorder(const IR::Declaration_Constant *cst) { - if (!cst->annotations->annotations.empty()) { - visit(cst->annotations); - builder.spc(); - } + if (printAnnotations(cst)) builder.spc(); builder.append("const "); auto type = cst->type->getP4Type(); CHECK_NULL(type); @@ -510,10 +475,7 @@ bool P4Formatter::preorder(const IR::Declaration_Constant *cst) { } bool P4Formatter::preorder(const IR::Declaration_Instance *i) { - if (!i->annotations->annotations.empty()) { - visit(i->annotations); - builder.spc(); - } + if (printAnnotations(i)) builder.spc(); auto type = i->type->getP4Type(); CHECK_NULL(type); visit(type); @@ -534,10 +496,7 @@ bool P4Formatter::preorder(const IR::Declaration_Instance *i) { } bool P4Formatter::preorder(const IR::Declaration_Variable *v) { - if (!v->annotations->annotations.empty()) { - visit(v->annotations); - builder.spc(); - } + if (printAnnotations(v)) builder.spc(); auto type = v->type->getP4Type(); CHECK_NULL(type); visit(type); @@ -962,10 +921,7 @@ bool P4Formatter::preorder(const IR::AssignmentStatement *a) { } bool P4Formatter::preorder(const IR::BlockStatement *s) { - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.blockStart(); { WithSeparator newline(*this, "\n", "\n"); @@ -1045,10 +1001,7 @@ bool P4Formatter::preorder(const IR::IfStatement *s) { } bool P4Formatter::preorder(const IR::ForStatement *s) { - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("for ("); visitCollection(s->init, ", ", [&](auto *d) { builder.supressStatementSemi(); @@ -1081,10 +1034,7 @@ bool P4Formatter::preorder(const IR::ForStatement *s) { } bool P4Formatter::preorder(const IR::ForInStatement *s) { - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("for ("); if (s->decl) { builder.supressStatementSemi(); @@ -1145,11 +1095,6 @@ bool P4Formatter::preorder(const IR::SwitchStatement *s) { //////////////////////////////////// -bool P4Formatter::preorder(const IR::Annotations *a) { - visitCollection(a->annotations, " ", [&](const auto *anno) { visit(anno); }); - return false; -} - bool P4Formatter::preorder(const IR::Annotation *a) { builder.append("@"); builder.append(a->name); @@ -1193,10 +1138,7 @@ bool P4Formatter::preorder(const IR::Annotation *a) { } bool P4Formatter::preorder(const IR::Parameter *p) { - if (!p->annotations->annotations.empty()) { - visit(p->annotations); - builder.spc(); - } + if (printAnnotations(p)) builder.spc(); switch (p->direction) { case IR::Direction::None: break; @@ -1255,10 +1197,7 @@ bool P4Formatter::preorder(const IR::ParameterList *p) { } bool P4Formatter::preorder(const IR::P4Action *c) { - if (!c->annotations->annotations.empty()) { - visit(c->annotations); - builder.spc(); - } + if (printAnnotations(c)) builder.spc(); builder.append("action "); builder.append(c->name); visit(c->parameters); @@ -1270,10 +1209,7 @@ bool P4Formatter::preorder(const IR::P4Action *c) { bool P4Formatter::preorder(const IR::ParserState *s) { if (s->isBuiltin()) return false; - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("state "); builder.append(s->name); builder.spc(); @@ -1325,10 +1261,7 @@ bool P4Formatter::preorder(const IR::ExpressionValue *v) { } bool P4Formatter::preorder(const IR::ActionListElement *ale) { - if (!ale->annotations->annotations.empty()) { - visit(ale->annotations); - builder.spc(); - } + if (printAnnotations(ale)) builder.spc(); visit(ale->expression); return false; } @@ -1366,9 +1299,9 @@ bool P4Formatter::preorder(const IR::Key *v) { builder.append(std::string(spaces, ' ')); builder.append(": "); visit(f->matchType); - if (!f->annotations->annotations.empty()) { - builder.append(" "); - visit(f->annotations); + if (f->hasAnnotations()) { + builder.spc(); + printAnnotations(f); } builder.endOfStatement(true); } @@ -1377,10 +1310,7 @@ bool P4Formatter::preorder(const IR::Key *v) { } bool P4Formatter::preorder(const IR::Property *p) { - if (!p->annotations->annotations.empty()) { - visit(p->annotations); - builder.spc(); - } + if (printAnnotations(p)) builder.spc(); if (p->isConstant) builder.append("const "); builder.append(p->name); builder.append(" = "); @@ -1424,18 +1354,13 @@ bool P4Formatter::preorder(const IR::Entry *e) { doneList(); builder.append(" : "); visit(e->action); - if (!e->annotations->annotations.empty()) { - visit(e->annotations); - } + printAnnotations(e); builder.append(";"); return false; } bool P4Formatter::preorder(const IR::P4Table *c) { - if (!c->annotations->annotations.empty()) { - visit(c->annotations); - builder.spc(); - } + if (printAnnotations(c)) builder.spc(); builder.append("table "); builder.append(c->name); builder.spc(); diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index 8a0844d89fc..daa31ec3a6c 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -156,6 +156,7 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { bool process(const IR::Type_StructLike *t, const char *name); bool preorder(const IR::Node *node) override; + bool printAnnotations(const IR::IAnnotated *ann); // types bool preorder(const IR::Type_Boolean *t) override; @@ -265,7 +266,6 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { bool preorder(const IR::Argument *arg) override; bool preorder(const IR::Path *p) override; bool preorder(const IR::Parameter *p) override; - bool preorder(const IR::Annotations *a) override; bool preorder(const IR::Annotation *a) override; bool preorder(const IR::P4Program *program) override; bool preorder(const IR::P4Control *c) override; diff --git a/backends/p4tools/common/compiler/reachability.cpp b/backends/p4tools/common/compiler/reachability.cpp index f7bfd58130a..bbe28904493 100644 --- a/backends/p4tools/common/compiler/reachability.cpp +++ b/backends/p4tools/common/compiler/reachability.cpp @@ -26,7 +26,7 @@ P4ProgramDCGCreator::P4ProgramDCGCreator(NodesCallGraph *dcg) : dcg(dcg), p4prog } bool P4ProgramDCGCreator::preorder(const IR::Annotation *annotation) { - if (annotation->name.name != IR::Annotation::nameAnnotation) { + if (annotation->name != IR::Annotation::nameAnnotation) { return true; } IR::ID name; @@ -140,7 +140,7 @@ bool P4ProgramDCGCreator::preorder(const IR::MethodCallStatement *method) { bool P4ProgramDCGCreator::preorder(const IR::P4Action *action) { addEdge(action, action->name); - for (const auto *annotation : action->annotations->annotations) { + for (const auto *annotation : action->getAnnotations()) { visit(annotation); } visit(action->body); @@ -155,16 +155,12 @@ bool P4ProgramDCGCreator::preorder(const IR::P4Parser *parser) { bool P4ProgramDCGCreator::preorder(const IR::P4Table *table) { addEdge(table, table->name); - if (table->annotations != nullptr) { - for (const auto *annotation : table->annotations->annotations) { - visit(annotation); - } - } + for (const auto *annotation : table->getAnnotations()) visit(annotation); bool wasImplementations = false; if (table->properties != nullptr) { for (const auto *property : table->properties->properties) { if (property->name.name == "implementation") { - visit(property->annotations->annotations); + visit(property->annotations); wasImplementations = true; } } @@ -210,10 +206,8 @@ bool P4ProgramDCGCreator::preorder(const IR::P4Table *table) { bool P4ProgramDCGCreator::preorder(const IR::ParserState *parserState) { addEdge(parserState, parserState->name); visited.insert(parserState); - if (parserState->annotations != nullptr) { - for (const auto *annotation : parserState->annotations->annotations) { - visit(annotation); - } + for (const auto *annotation : parserState->annotations) { + visit(annotation); } for (const auto *component : parserState->components) { visit(component); @@ -345,14 +339,8 @@ bool P4ProgramDCGCreator::preorder(const IR::SwitchStatement *switchStatement) { bool P4ProgramDCGCreator::preorder(const IR::StatOrDecl *statOrDecl) { if (const auto *block = statOrDecl->to()) { - if (block->annotations != nullptr) { - for (const auto *a : block->annotations->annotations) { - visit(a); - } - } - for (const auto *c : block->components) { - visit(c); - } + for (const auto *a : block->annotations) visit(a); + for (const auto *c : block->components) visit(c); return false; } IR::ID name; diff --git a/backends/p4tools/common/lib/table_utils.cpp b/backends/p4tools/common/lib/table_utils.cpp index ff3a3f9ea9b..2ec26666ca7 100644 --- a/backends/p4tools/common/lib/table_utils.cpp +++ b/backends/p4tools/common/lib/table_utils.cpp @@ -14,7 +14,8 @@ void checkTableImmutability(const IR::P4Table &table, TableProperties &propertie } // Also check if the table is invisible to the control plane. // This also implies that it cannot be modified. - properties.tableIsImmutable = isConstant || table.getAnnotation("hidden"_cs) != nullptr; + properties.tableIsImmutable = + isConstant || table.hasAnnotation(IR::Annotation::hiddenAnnotation); const auto *defaultAction = table.properties->getProperty("default_action"); CHECK_NULL(defaultAction); properties.defaultIsImmutable = defaultAction->isConstant; @@ -28,7 +29,7 @@ std::vector buildTableActionList(const IR::P4Tabl } for (size_t idx = 0; idx < actionList->size(); idx++) { const auto *action = actionList->actionList.at(idx); - if (action->getAnnotation("defaultonly"_cs) != nullptr) { + if (action->hasAnnotation(IR::Annotation::defaultOnlyAnnotation)) { continue; } tableActionList.emplace_back(action); diff --git a/backends/p4tools/modules/smith/common/declarations.cpp b/backends/p4tools/modules/smith/common/declarations.cpp index 5b8925c3174..6ed2f09c4e1 100644 --- a/backends/p4tools/modules/smith/common/declarations.cpp +++ b/backends/p4tools/modules/smith/common/declarations.cpp @@ -50,7 +50,7 @@ IR::StatOrDecl *DeclarationGenerator::generateRandomStatementOrDeclaration(bool return stmt; } -IR::Annotations *DeclarationGenerator::genAnnotation() { +IR::Vector DeclarationGenerator::genAnnotation() { Util::SourceInfo si; IR::Vector annotations; IR::Vector exprs; @@ -59,10 +59,7 @@ IR::Annotations *DeclarationGenerator::genAnnotation() { exprs.push_back(strLiteral); - auto *annotation = new IR::Annotation(si, name, exprs, false); - annotations.push_back(annotation); - - return new IR::Annotations(annotations); + return {new IR::Annotation(si, name, exprs, false)}; } IR::Declaration_Constant *DeclarationGenerator::genConstantDeclaration() { diff --git a/backends/p4tools/modules/smith/common/declarations.h b/backends/p4tools/modules/smith/common/declarations.h index e794ce454f2..d9ff904cc88 100644 --- a/backends/p4tools/modules/smith/common/declarations.h +++ b/backends/p4tools/modules/smith/common/declarations.h @@ -18,7 +18,7 @@ class DeclarationGenerator : public Generator { virtual IR::StatOrDecl *generateRandomStatementOrDeclaration(bool is_in_func); - virtual IR::Annotations *genAnnotation(); + virtual IR::Vector genAnnotation(); virtual IR::P4Action *genActionDeclaration(); diff --git a/backends/p4tools/modules/smith/common/table.cpp b/backends/p4tools/modules/smith/common/table.cpp index 49a4d296b01..adad0e4e576 100644 --- a/backends/p4tools/modules/smith/common/table.cpp +++ b/backends/p4tools/modules/smith/common/table.cpp @@ -48,7 +48,7 @@ IR::Key *TableGenerator::genKeyElementList(size_t len) { } // @name // Tao: actually, this may never happen - const auto *keyAnno = key->annotations->annotations.at(0); + const auto *keyAnno = key->getAnnotations().at(0); const auto *annotExpr = keyAnno->expr.at(0); cstring keyAnnotatName; if (annotExpr->is()) { @@ -66,7 +66,7 @@ IR::Key *TableGenerator::genKeyElementList(size_t len) { IR::KeyElement *TableGenerator::genKeyElement(IR::ID match_kind) { auto *match = new IR::PathExpression(std::move(match_kind)); - auto *annotations = target().declarationGenerator().genAnnotation(); + auto annotations = target().declarationGenerator().genAnnotation(); auto *bitType = P4Scope::pickDeclaredBitType(false); // Ideally this should have a fallback option @@ -78,7 +78,7 @@ IR::KeyElement *TableGenerator::genKeyElement(IR::ID match_kind) { P4Scope::req.require_scalar = true; auto *expr = target().expressionGenerator().genExpression(bitType); P4Scope::req.require_scalar = false; - auto *key = new IR::KeyElement(annotations, expr, match); + auto *key = new IR::KeyElement(expr, match, annotations); return key; } diff --git a/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp b/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp index 88ef436bc96..2e5b3958948 100644 --- a/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp +++ b/backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp @@ -466,7 +466,7 @@ bool TableStepper::resolveTableKeys() { return true; } - const auto *nameAnnot = keyElement->getAnnotation("name"_cs); + const auto *nameAnnot = keyElement->getAnnotation(IR::Annotation::nameAnnotation); // Some hidden tables do not have any key name annotations. BUG_CHECK(nameAnnot != nullptr || properties.tableIsImmutable, "Non-constant table key without an annotation"); diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp b/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp index 39db90be3d0..e0a055649c6 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4_refers_to_parser.cpp @@ -78,8 +78,7 @@ const IR::SymbolicVariable *RefersToParser::lookUpKeyInTable(const IR::P4Table & const auto *key = srcTable.getKey(); BUG_CHECK(key != nullptr, "Table %1% does not have any keys.", srcTable); for (const auto *keyElement : key->keyElements) { - auto annotations = keyElement->annotations->annotations; - const auto *nameAnnot = keyElement->getAnnotation("name"_cs); + const auto *nameAnnot = keyElement->getAnnotation(IR::Annotation::nameAnnotation); // Some hidden tables do not have any key name annotations. BUG_CHECK(nameAnnot != nullptr, "Refers-to table key without a name annotation"); if (keyReference == nameAnnot->getName()) { @@ -131,10 +130,9 @@ bool RefersToParser::preorder(const IR::P4Table *tableContext) { CHECK_NULL(controlContext); for (const auto *keyElement : key->keyElements) { - auto annotations = keyElement->annotations->annotations; - for (const auto *annotation : annotations) { - if (annotation->name.name == "refers_to" || annotation->name.name == "referenced_by") { - const auto *nameAnnot = keyElement->getAnnotation("name"_cs); + for (const auto *annotation : keyElement->getAnnotations()) { + if (annotation->name == "refers_to" || annotation->name == "referenced_by") { + const auto *nameAnnot = keyElement->getAnnotation(IR::Annotation::nameAnnotation); BUG_CHECK(nameAnnot != nullptr, "%1% table key without a name annotation", annotation->name.name); const auto *srcKey = ControlPlaneState::getTableKey( @@ -161,10 +159,8 @@ bool RefersToParser::preorder(const IR::P4Table *tableContext) { return false; } for (const auto *parameter : params->parameters) { - auto annotations = parameter->annotations->annotations; - for (const auto *annotation : annotations) { - if (annotation->name.name == "refers_to" || - annotation->name.name == "referenced_by") { + for (const auto *annotation : parameter->getAnnotations()) { + if (annotation->name == "refers_to" || annotation->name == "referenced_by") { const auto *referredKey = getReferencedKey(*controlContext, *annotation); const auto *srcKey = ControlPlaneState::getTableActionArgument( tableContext->controlPlaneName(), actionCall->controlPlaneName(), diff --git a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp index 6dfb3708543..fdea09165b9 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/p4runtime_translation.cpp @@ -39,28 +39,18 @@ P4Tools::P4Testgen::Bmv2::PropagateP4RuntimeTranslation::lookupP4RuntimeAnnotati const IR::Parameter *P4Tools::P4Testgen::Bmv2::PropagateP4RuntimeTranslation::preorder( IR::Parameter *parameter) { auto p4RuntimeAnnotations = lookupP4RuntimeAnnotations(_typeMap, parameter->type); - if (p4RuntimeAnnotations.empty()) { - return parameter; - } - auto *annotationsVector = parameter->annotations->clone(); - for (const auto *p4runtimeAnnotation : p4RuntimeAnnotations) { - annotationsVector->annotations.push_back(p4runtimeAnnotation); - } - parameter->annotations = annotationsVector; + if (p4RuntimeAnnotations.empty()) return parameter; + + parameter->annotations.append(p4RuntimeAnnotations); return parameter; } const IR::KeyElement *P4Tools::P4Testgen::Bmv2::PropagateP4RuntimeTranslation::preorder( IR::KeyElement *keyElement) { auto p4RuntimeAnnotations = lookupP4RuntimeAnnotations(_typeMap, keyElement->expression->type); - if (p4RuntimeAnnotations.empty()) { - return keyElement; - } - auto *annotationsVector = keyElement->annotations->clone(); - for (const auto *p4runtimeAnnotation : p4RuntimeAnnotations) { - annotationsVector->annotations.push_back(p4runtimeAnnotation); - } - keyElement->annotations = annotationsVector; + if (p4RuntimeAnnotations.empty()) return keyElement; + + keyElement->annotations.append(p4RuntimeAnnotations); return keyElement; } diff --git a/backends/tc/backend.cpp b/backends/tc/backend.cpp index 7fedba821cb..5f894a5de0b 100644 --- a/backends/tc/backend.cpp +++ b/backends/tc/backend.cpp @@ -246,9 +246,7 @@ void ConvertToBackendIR::postorder(const IR::P4Action *action) { unsigned int width = paramType->to()->width_bits(); tcActionParam->setBitSize(width); } - auto annoList = param->getAnnotations()->annotations; - for (auto anno : annoList) { - if (anno->name != ParseTCAnnotations::tcType) continue; + if (const auto *anno = param->getAnnotation(ParseTCAnnotations::tcType)) { auto expr = anno->expr[0]; if (auto typeLiteral = expr->to()) { auto val = getTcType(typeLiteral); @@ -438,28 +436,24 @@ void ConvertToBackendIR::updateDefaultHitAction(const IR::P4Table *t, IR::TCTabl cstring defaultActionName = nullptr; bool isTcMayOverrideHitAction = false; for (auto action : actionlist->actionList) { - auto annoList = action->getAnnotations()->annotations; bool isTableOnly = false; bool isDefaultHit = false; bool isDefaultHitConst = false; bool isTcMayOverrideHit = false; - for (auto anno : annoList) { + for (const auto *anno : action->getAnnotations()) { if (anno->name == IR::Annotation::tableOnlyAnnotation) { isTableOnly = true; - } - if (anno->name == ParseTCAnnotations::defaultHit) { + } else if (anno->name == ParseTCAnnotations::defaultHit) { isDefaultHit = true; defaultHit++; auto adecl = refMap->getDeclaration(action->getPath(), true); defaultActionName = externalName(adecl); - } - if (anno->name == ParseTCAnnotations::defaultHitConst) { + } else if (anno->name == ParseTCAnnotations::defaultHitConst) { isDefaultHitConst = true; defaultHitConst++; auto adecl = refMap->getDeclaration(action->getPath(), true); defaultActionName = externalName(adecl); - } - if (anno->name == ParseTCAnnotations::tcMayOverride) { + } else if (anno->name == ParseTCAnnotations::tcMayOverride) { isTcMayOverrideHit = true; } } @@ -767,8 +761,7 @@ void ConvertToBackendIR::postorder(const IR::P4Table *t) { } tableDefinition->setKeySize(keySize); tableKeysizeList.emplace(tId, keySize); - auto annoList = t->getAnnotations()->annotations; - for (auto anno : annoList) { + for (const auto *anno : t->getAnnotations()) { if (anno->name == ParseTCAnnotations::tc_acl) { tablePermissions.emplace(t->name.originalName, GetAnnotatedAccessPath(anno)); } else if (anno->name == ParseTCAnnotations::numMask) { @@ -799,13 +792,11 @@ void ConvertToBackendIR::postorder(const IR::P4Table *t) { if (actionName == P4::P4CoreLibrary::instance().noAction.name) { tcAction = tcPipeline->NoAction; } - auto annoList = action->getAnnotations()->annotations; unsigned int tableFlag = TC::TABLEDEFAULT; - for (auto anno : annoList) { + for (const auto *anno : action->getAnnotations()) { if (anno->name == IR::Annotation::tableOnlyAnnotation) { tableFlag = TC::TABLEONLY; - } - if (anno->name == IR::Annotation::defaultOnlyAnnotation) { + } else if (anno->name == IR::Annotation::defaultOnlyAnnotation) { tableFlag = TC::DEFAULTONLY; } } @@ -828,13 +819,10 @@ void ConvertToBackendIR::postorder(const IR::P4Table *t) { cstring ConvertToBackendIR::processExternPermission(const IR::Type_Extern *ext) { cstring control_path, data_path; // Check if access permissions is defined with annotation @tc_acl - auto annoList = ext->getAnnotations()->annotations; - for (auto anno : annoList) { - if (anno->name == ParseTCAnnotations::tc_acl) { - auto path = GetAnnotatedAccessPath(anno); - control_path = path->first; - data_path = path->second; - } + if (const auto *anno = ext->getAnnotation(ParseTCAnnotations::tc_acl)) { + auto path = GetAnnotatedAccessPath(anno); + control_path = path->first; + data_path = path->second; } // Default access value of Control_path and Data_Path if (control_path.isNullOrEmpty()) { @@ -897,7 +885,7 @@ safe_vector ConvertToBackendIR::processExternConstructor( cstring ConvertToBackendIR::getControlPathKeyAnnotation(const IR::StructField *field) { cstring annoName; - auto annotation = field->getAnnotations()->annotations.at(0); + auto annotation = field->getAnnotations().at(0); if (annotation->name == ParseTCAnnotations::tc_key || annotation->name == ParseTCAnnotations::tc_data_scalar) { annoName = annotation->name; @@ -927,7 +915,7 @@ safe_vector ConvertToBackendIR::processCounterControlPathKeys int kId = 1; for (auto field : extern_control_path->fields) { /* If there is no annotation to control path key, ignore the key.*/ - if (field->getAnnotations()->annotations.size() != 1) { + if (field->getAnnotations().size() != 1) { continue; } cstring annoName = getControlPathKeyAnnotation(field); @@ -975,7 +963,7 @@ safe_vector ConvertToBackendIR::processExternControlPath( int kId = 1; for (auto field : extern_control_path->fields) { /* If there is no annotation to control path key, ignore the key.*/ - if (field->getAnnotations()->annotations.size() != 1) { + if (field->getAnnotations().size() != 1) { continue; } cstring annoName = getControlPathKeyAnnotation(field); diff --git a/backends/tc/ebpfCodeGen.cpp b/backends/tc/ebpfCodeGen.cpp index eb3087406a4..37df9d92b11 100644 --- a/backends/tc/ebpfCodeGen.cpp +++ b/backends/tc/ebpfCodeGen.cpp @@ -614,9 +614,7 @@ void PnaStateTranslationVisitor::compileExtractField(const IR::Expression *expr, cstring fieldName = field->name.name; bool noEndiannessConversion = false; - auto annolist = field->getAnnotations()->annotations; - for (auto anno : annolist) { - if (anno->name != ParseTCAnnotations::tcType) continue; + if (const auto *anno = field->getAnnotation(ParseTCAnnotations::tcType)) { auto annoBody = anno->body; for (auto annoVal : annoBody) { if (annoVal->text == "macaddr" || annoVal->text == "ipv4" || annoVal->text == "ipv6") { @@ -1865,15 +1863,13 @@ void ControlBodyTranslatorPNA::processApply(const P4::ApplyMethod *method) { cstring swap; auto tcTarget = dynamic_cast(builder->target); - cstring isKeyBigEndian = - tcTarget->getByteOrderFromAnnotation(c->getAnnotations()->annotations); + cstring isKeyBigEndian = tcTarget->getByteOrderFromAnnotation(c->getAnnotations()); cstring isDefnBigEndian = "HOST"_cs; if (auto mem = c->expression->to()) { auto type = typeMap->getType(mem->expr, true); if (type->is()) { auto field = type->to()->getField(mem->member); - isDefnBigEndian = - tcTarget->getByteOrderFromAnnotation(field->getAnnotations()->annotations); + isDefnBigEndian = tcTarget->getByteOrderFromAnnotation(field->getAnnotations()); } } @@ -2238,9 +2234,7 @@ void DeparserHdrEmitTranslatorPNA::processMethod(const P4::ExternMethod *method) return; } bool noEndiannessConversion = false; - auto annotations = f->getAnnotations()->annotations; - for (auto anno : annotations) { - if (anno->name != ParseTCAnnotations::tcType) continue; + if (const auto *anno = f->getAnnotation(ParseTCAnnotations::tcType)) { for (auto annoVal : anno->body) { if (annoVal->text == "macaddr" || annoVal->text == "ipv4" || annoVal->text == "ipv6" || annoVal->text == "be16" || diff --git a/backends/tc/introspection.cpp b/backends/tc/introspection.cpp index 035ffa44c98..876b0c81b94 100644 --- a/backends/tc/introspection.cpp +++ b/backends/tc/introspection.cpp @@ -66,8 +66,7 @@ void IntrospectionGenerator::collectKeyInfo(const IR::Key *key, struct TableAttr auto keyExpType = typeMap->getType(keyExp); auto widthBits = keyExpType->width_bits(); keyField->type = "bit" + Util::toString(widthBits); - auto keyAnno = k->getAnnotations()->annotations; - for (auto anno : keyAnno) { + for (auto anno : k->getAnnotations()) { if (anno->name == ParseTCAnnotations::tcType) { auto expr = anno->expr[0]; if (auto typeLiteral = expr->to()) { @@ -107,10 +106,9 @@ void IntrospectionGenerator::collectActionInfo(const IR::ActionList *actionlist, auto actionInfo = new struct ActionAttributes(); actionInfo->id = actionDef->actId; actionInfo->name = actionDef->actionName; - auto annoList = action->getAnnotations()->annotations; bool isTableOnly = false; bool isDefaultOnly = false; - for (auto anno : annoList) { + for (auto anno : action->getAnnotations()) { if (anno->name == IR::Annotation::tableOnlyAnnotation) { isTableOnly = true; } diff --git a/control-plane/addMissingIds.cpp b/control-plane/addMissingIds.cpp index 664294b5f22..e7594c05d9e 100644 --- a/control-plane/addMissingIds.cpp +++ b/control-plane/addMissingIds.cpp @@ -32,14 +32,9 @@ const IR::Property *MissingIdAssigner::postorder(IR::Property *property) { auto *keyElement = key->keyElements.at(symbolId)->clone(); auto anno = ControlPlaneAPI::getIdAnnotation(keyElement); if (!anno) { - const auto *annos = keyElement->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId + 1); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - keyElement->annotations = newAnnos; + keyElement->annotations.emplace_back("id", idConst); } newKeys.push_back(keyElement); } @@ -56,14 +51,9 @@ const IR::P4Table *MissingIdAssigner::postorder(IR::P4Table *table) { CHECK_NULL(symbols); auto anno = ControlPlaneAPI::getIdAnnotation(table); if (!anno) { - const auto *annos = table->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; auto symbolId = symbols->getId(ControlPlaneAPI::P4RuntimeSymbolType::P4RT_TABLE(), table); const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - table->annotations = newAnnos; + table->annotations.emplace_back("id", idConst); } return table; } @@ -75,15 +65,10 @@ const IR::Type_Header *MissingIdAssigner::postorder(IR::Type_Header *hdr) { CHECK_NULL(symbols); auto anno = ControlPlaneAPI::getIdAnnotation(hdr); if (!anno) { - const auto *annos = hdr->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; auto symbolId = symbols->getId(ControlPlaneAPI::P4RuntimeSymbolType::P4RT_CONTROLLER_HEADER(), hdr); const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - hdr->annotations = newAnnos; + hdr->annotations.emplace_back("id", idConst); } return hdr; @@ -96,15 +81,10 @@ const IR::P4ValueSet *MissingIdAssigner::postorder(IR::P4ValueSet *valueSet) { CHECK_NULL(symbols); auto anno = ControlPlaneAPI::getIdAnnotation(valueSet); if (!anno) { - const auto *annos = valueSet->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; auto symbolId = symbols->getId(ControlPlaneAPI::P4RuntimeSymbolType::P4RT_VALUE_SET(), valueSet); const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - valueSet->annotations = newAnnos; + valueSet->annotations.emplace_back("id", idConst); } return valueSet; } @@ -116,14 +96,9 @@ const IR::P4Action *MissingIdAssigner::postorder(IR::P4Action *action) { CHECK_NULL(symbols); auto anno = ControlPlaneAPI::getIdAnnotation(action); if (!anno) { - const auto *annos = action->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; auto symbolId = symbols->getId(ControlPlaneAPI::P4RuntimeSymbolType::P4RT_ACTION(), action); const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - action->annotations = newAnnos; + action->annotations.emplace_back("id", idConst); } auto *paramList = new IR::ParameterList(); @@ -131,14 +106,9 @@ const IR::P4Action *MissingIdAssigner::postorder(IR::P4Action *action) { auto *param = action->parameters->getParameter(symbolId)->clone(); auto anno = ControlPlaneAPI::getIdAnnotation(param); if (!anno) { - const auto *annos = param->getAnnotations(); - auto *newAnnos = annos->clone(); - IR::Vector annoExprs; const auto *idConst = new IR::Constant(IR::Type_Bits::get(ID_BIT_WIDTH, false), symbolId + 1); - annoExprs.push_back(idConst); - newAnnos->add(new IR::Annotation("id", annoExprs)); - param->annotations = newAnnos; + param->annotations.emplace_back("id", idConst); } paramList->parameters.push_back(param); } diff --git a/control-plane/flattenHeader.cpp b/control-plane/flattenHeader.cpp index 8494fcf4b85..e124835842c 100644 --- a/control-plane/flattenHeader.cpp +++ b/control-plane/flattenHeader.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "flattenHeader.h" #include "frontends/p4/typeMap.h" +#include "ir/annotations.h" namespace P4 { @@ -30,7 +31,7 @@ void FlattenHeader::doFlatten(const IR::Type *type) { if (auto st = type->to()) { for (auto f : st->fields) { nameSegments.push_back(f->name); - allAnnotations.push_back(f->annotations); + allAnnotations.push_back(&f->annotations); doFlatten(typeMap->getType(f, true)); allAnnotations.pop_back(); nameSegments.pop_back(); @@ -41,9 +42,8 @@ void FlattenHeader::doFlatten(const IR::Type *type) { // preserve the original name using an annotation auto originalName = makeName("."); auto annotations = mergeAnnotations(); - annotations = annotations->addOrReplace(IR::Annotation::nameAnnotation, - new IR::StringLiteral(originalName)); - auto field = new IR::StructField(IR::ID(newName), annotations, type); + auto field = new IR::StructField( + IR::ID(newName), IR::Annotations::setNameAnnotation(originalName, annotations), type); newFields.push_back(field); auto ftype = typeMap->getTypeType(type, true); typeMap->setType(field, ftype); @@ -62,13 +62,13 @@ cstring FlattenHeader::makeName(std::string_view sep) const { /// Merge all the annotation vectors in allAnnotations into a single /// one. Duplicates are resolved, with preference given to the ones towards the /// end of allAnnotations, which correspond to the most "nested" ones. -const IR::Annotations *FlattenHeader::mergeAnnotations() const { - auto mergedAnnotations = new IR::Annotations(); +IR::Vector FlattenHeader::mergeAnnotations() const { + IR::Vector mergedAnnotations; for (auto annosIt = allAnnotations.rbegin(); annosIt != allAnnotations.rend(); annosIt++) { - for (auto anno : (*annosIt)->annotations) { + for (auto anno : **annosIt) { // if an annotation with the same name was added previously, skip - if (mergedAnnotations->getSingle(anno->name)) continue; - mergedAnnotations->add(anno); + if (get(mergedAnnotations, anno->name)) continue; + mergedAnnotations.push_back(anno); } } return mergedAnnotations; diff --git a/control-plane/flattenHeader.h b/control-plane/flattenHeader.h index 97364534114..b0ff517259f 100644 --- a/control-plane/flattenHeader.h +++ b/control-plane/flattenHeader.h @@ -32,8 +32,8 @@ class FlattenHeader { private: P4::TypeMap *typeMap; IR::Type_Header *flattenedHeader; - std::vector nameSegments{}; - std::vector allAnnotations{}; + std::vector nameSegments; + std::vector *> allAnnotations; bool needsFlattening{false}; FlattenHeader(P4::TypeMap *typeMap, IR::Type_Header *flattenedHeader); @@ -41,7 +41,7 @@ class FlattenHeader { void doFlatten(const IR::Type *type); cstring makeName(std::string_view sep) const; - const IR::Annotations *mergeAnnotations() const; + IR::Vector mergeAnnotations() const; public: /// If the @headerType needs flattening, creates a clone of the IR node with diff --git a/control-plane/p4RuntimeArchHandler.h b/control-plane/p4RuntimeArchHandler.h index d3dba572651..923091a5c89 100644 --- a/control-plane/p4RuntimeArchHandler.h +++ b/control-plane/p4RuntimeArchHandler.h @@ -274,7 +274,7 @@ void addAnnotations(Message *message, const IR::IAnnotated *annotated, UnaryPred // Synthesized resources may have no annotations. if (annotated == nullptr) return; - for (const IR::Annotation *annotation : annotated->getAnnotations()->annotations) { + for (const IR::Annotation *annotation : annotated->getAnnotations()) { // Always add all structured annotations. if (annotation->annotationKind() != IR::Annotation::Kind::Unstructured) { serializeOneStructuredAnnotation(annotation, message->add_structured_annotations()); @@ -316,7 +316,7 @@ void addDocumentation(Message *message, const IR::IAnnotated *annotated) { // we iterate over all annotations looking for '@brief' and / or // '@description'. As per the P4Runtime spec, we only set the 'doc' field in // the message if at least one of them is present. - for (const IR::Annotation *annotation : annotated->getAnnotations()->annotations) { + for (const IR::Annotation *annotation : annotated->getAnnotations()) { if (annotation->name == "brief") { auto brief = annotation->expr[0]->to(); // guaranteed by ParseAnnotations pass diff --git a/control-plane/p4RuntimeSerializer.cpp b/control-plane/p4RuntimeSerializer.cpp index e6120d824ca..b17d29cac3b 100644 --- a/control-plane/p4RuntimeSerializer.cpp +++ b/control-plane/p4RuntimeSerializer.cpp @@ -938,7 +938,7 @@ class P4RuntimeAnalyzer { std::set keysVisited; // @pkginfo annotation - for (auto *annotation : decl->getAnnotations()->annotations) { + for (auto *annotation : decl->getAnnotations()) { if (annotation->name != IR::Annotation::pkginfoAnnotation) continue; for (auto *kv : annotation->kv) { auto name = kv->name.name; @@ -981,7 +981,7 @@ class P4RuntimeAnalyzer { } // Parse `@platform_property` annotation into the PkgInfo. - for (auto *annotation : decl->getAnnotations()->annotations) { + for (auto *annotation : decl->getAnnotations()) { if (annotation->name != "platform_property") continue; auto *platform_properties = pkginfo->mutable_platform_properties(); for (auto *kv : annotation->kv) { diff --git a/control-plane/p4RuntimeSymbolTable.cpp b/control-plane/p4RuntimeSymbolTable.cpp index 2365043974f..898aaf1471e 100644 --- a/control-plane/p4RuntimeSymbolTable.cpp +++ b/control-plane/p4RuntimeSymbolTable.cpp @@ -25,24 +25,29 @@ namespace P4 { namespace ControlPlaneAPI { +static const cstring controllerHeaderAnnotation = "controller_header"_cs; +static const cstring idAnnotation = "id"_cs; + bool isControllerHeader(const IR::Type_Header *type) { - return type->getAnnotation("controller_header"_cs) != nullptr; + return type->getAnnotation(controllerHeaderAnnotation) != nullptr; } -bool isHidden(const IR::Node *node) { return node->getAnnotation("hidden"_cs) != nullptr; } +bool isHidden(const IR::IAnnotated *node) { + return node->hasAnnotation(IR::Annotation::hiddenAnnotation); +} std::optional getIdAnnotation(const IR::IAnnotated *node) { - const auto *idAnnotation = node->getAnnotation("id"_cs); - if (idAnnotation == nullptr) { - return std::nullopt; - } - const auto *idConstant = idAnnotation->expr[0]->to(); - CHECK_NULL(idConstant); - if (!idConstant->fitsUint()) { - ::P4::error(ErrorType::ERR_INVALID, "%1%: @id should be an unsigned integer", node); - return std::nullopt; + if (const auto *idAnn = node->getAnnotation(idAnnotation)) { + const auto *idConstant = idAnn->expr.at(0)->to(); + CHECK_NULL(idConstant); + if (!idConstant->fitsUint()) { + ::P4::error(ErrorType::ERR_INVALID, "%1%: @id should be an unsigned integer", node); + return std::nullopt; + } + return static_cast(idConstant->value); } - return static_cast(idConstant->value); + + return std::nullopt; } /// @return the value of any P4 '@id' annotation @declaration may have, and diff --git a/control-plane/p4RuntimeSymbolTable.h b/control-plane/p4RuntimeSymbolTable.h index 3ac2aa12389..ca724e30671 100644 --- a/control-plane/p4RuntimeSymbolTable.h +++ b/control-plane/p4RuntimeSymbolTable.h @@ -46,7 +46,7 @@ const p4rt_id_t INVALID_ID = ::p4::config::v1::P4Ids::UNSPECIFIED; bool isControllerHeader(const IR::Type_Header *type); /// @return true if @node has an @hidden annotation. -bool isHidden(const IR::Node *node); +bool isHidden(const IR::IAnnotated *node); /// @return the id allocated to the object through the @id annotation if any, or /// std::nullopt. diff --git a/control-plane/typeSpecConverter.cpp b/control-plane/typeSpecConverter.cpp index 57ae67d0761..50855513db5 100644 --- a/control-plane/typeSpecConverter.cpp +++ b/control-plane/typeSpecConverter.cpp @@ -41,7 +41,9 @@ namespace P4 { namespace ControlPlaneAPI { bool hasTranslationAnnotation(const IR::Type *type, TranslationAnnotation *payload) { - auto ann = type->getAnnotation("p4runtime_translation"_cs); + const IR::Annotation *ann = nullptr; + if (auto *annotated = type->to()) + ann = annotated->getAnnotation("p4runtime_translation"_cs); if (!ann) return false; // Syntax: @pruntime_translation(, ). diff --git a/frontends/common/constantFolding.h b/frontends/common/constantFolding.h index befd022fac3..c44032b6619 100644 --- a/frontends/common/constantFolding.h +++ b/frontends/common/constantFolding.h @@ -174,7 +174,7 @@ class DoConstantFolding : public Transform, public ResolutionContext { const IR::Node *preorder(IR::ArrayIndex *e) override; const IR::Node *preorder(IR::SwitchCase *c) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->getAnnotation("disable_optimization"_cs)) prune(); + if (bs->hasAnnotation(IR::Annotation::disableOptimizationAnnotation)) prune(); return bs; } }; diff --git a/frontends/common/resolveReferences/resolveReferences.cpp b/frontends/common/resolveReferences/resolveReferences.cpp index 5ce6dbff49a..42ee4e5a6db 100644 --- a/frontends/common/resolveReferences/resolveReferences.cpp +++ b/frontends/common/resolveReferences/resolveReferences.cpp @@ -169,6 +169,7 @@ std::vector ResolutionContext::lookup(const IR::INames } std::vector ResolutionContext::lookupMatchKind(const IR::ID &name) const { + LOG2("Resolving " << name << " as match kind"); if (const auto *global = findOrigCtxt()) { for (const auto *obj : global->objects) { if (const auto *match_kind = obj->to()) { @@ -260,7 +261,7 @@ const IR::IDeclaration *ResolutionContext::getDeclaration(const IR::Path *path, bool notNull) const { const IR::IDeclaration *result = nullptr; const Context *ctxt = nullptr; - if (findOrigCtxt(ctxt) && ctxt->child_index == 2) { + if (findOrigCtxt(ctxt) && ctxt->child_index == 1) { // looking up a matchType in a key, so need to do a special lookup auto decls = lookupMatchKind(path->name); if (decls.empty()) { diff --git a/frontends/p4-14/fromv1.0/converters.cpp b/frontends/p4-14/fromv1.0/converters.cpp index e04e244b8b7..242a56a0772 100644 --- a/frontends/p4-14/fromv1.0/converters.cpp +++ b/frontends/p4-14/fromv1.0/converters.cpp @@ -410,7 +410,7 @@ const IR::Statement *StatementConverter::convert(const IR::Vectorsize == 0) { if (auto type = findContext()) { - if (auto max = type->getAnnotation("max_length"_cs)) { + if (auto max = type->getAnnotation(IR::Annotation::maxLengthAnnotation)) { if (max->expr.size() != 1 || !max->expr[0]->is()) error(ErrorType::ERR_UNSUPPORTED, "%s: max_length must be a constant", max); else @@ -460,7 +460,7 @@ const IR::StructField *TypeConverter::postorder(IR::StructField *field) { // given a struct with length and max_length, the // varbit field size is max_length * 8 - struct_size if (field->type->is()) { - if (auto len = type->getAnnotation("length"_cs)) { + if (auto len = type->getAnnotation(IR::Annotation::lengthAnnotation)) { if (len->expr.size() == 1) { auto lenexpr = len->expr[0]; ValidateLenExpr vle(type, field); @@ -469,19 +469,20 @@ const IR::StructField *TypeConverter::postorder(IR::StructField *field) { auto scale = new IR::Mul(lenexpr->srcInfo, lenexpr, new IR::Constant(8)); auto fieldlen = new IR::Sub(scale->srcInfo, scale, new IR::Constant(type->width_bits())); - field->annotations = - field->annotations->add(new IR::Annotation("length"_cs, {fieldlen})); + field->addAnnotation( + new IR::Annotation(IR::Annotation::lengthAnnotation, {fieldlen})); } } } if (auto vec = structure->listIndexes(type->name.name, field->name.name)) - field->annotations = field->annotations->add(new IR::Annotation("field_list"_cs, *vec)); + field->addAnnotation(new IR::Annotation("field_list"_cs, *vec)); return field; } const IR::Type_StructLike *TypeConverter::postorder(IR::Type_StructLike *str) { - str->annotations = str->annotations->where([](const IR::Annotation *a) -> bool { - return a->name != "length" && a->name != "max_length"; + str->annotations = str->annotations.where([](const IR::Annotation *a) -> bool { + return a->name != IR::Annotation::lengthAnnotation && + a->name != IR::Annotation::maxLengthAnnotation; }); return str; } @@ -501,8 +502,8 @@ class FixupExtern : public Modifier { } void postorder(IR::Type_Extern *type) override { if (extname != type->name) { - type->annotations = type->annotations->addAnnotationIfNew( - IR::Annotation::nameAnnotation, new IR::StringLiteral(type->name.name), false); + type->addAnnotationIfNew(IR::Annotation::nameAnnotation, + new IR::StringLiteral(type->name.name), false); type->name = extname; } // FIXME -- should create ctors based on attributes? For now just create a diff --git a/frontends/p4-14/fromv1.0/converters.h b/frontends/p4-14/fromv1.0/converters.h index 58290452faa..6ab05e99b27 100644 --- a/frontends/p4-14/fromv1.0/converters.h +++ b/frontends/p4-14/fromv1.0/converters.h @@ -771,8 +771,8 @@ class CheckIfMultiEntryPoint : public Inspector { setName("CheckIfMultiEntryPoint"); } bool preorder(const IR::ParserState *state) { - for (const auto *anno : state->getAnnotations()->annotations) { - if (anno->name.name == "packet_entry") { + for (const auto *anno : state->getAnnotations()) { + if (anno->name == "packet_entry") { structure->parserEntryPoints.emplace(state->name, state); } } @@ -855,10 +855,10 @@ class InsertCompilerGeneratedStartState : public Transform { p.first), new IR::PathExpression(new IR::Path(p.second->name)))); } - auto instAnnos = new IR::Annotations(); - instAnnos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$InstanceType"_cs)); - auto instEnum = - new IR::Type_SerEnum(newInstanceType, instAnnos, IR::Type_Bits::get(32), members); + auto instEnum = new IR::Type_SerEnum( + newInstanceType, + {new IR::Annotation(IR::Annotation::nameAnnotation, ".$InstanceType"_cs)}, + IR::Type_Bits::get(32), members); allTypeDecls.push_back(instEnum); IR::Vector selExpr; @@ -867,9 +867,9 @@ class InsertCompilerGeneratedStartState : public Transform { new IR::Member(new IR::PathExpression(new IR::Path("standard_metadata"_cs)), "instance_type"_cs))); auto selects = new IR::SelectExpression(new IR::ListExpression(selExpr), selCases); - auto annos = new IR::Annotations(); - annos->add(new IR::Annotation(IR::Annotation::nameAnnotation, ".$start"_cs)); - auto startState = new IR::ParserState(IR::ParserState::start, annos, selects); + auto startState = new IR::ParserState( + IR::ParserState::start, + {new IR::Annotation(IR::Annotation::nameAnnotation, ".$start"_cs)}, selects); parserStates.push_back(startState); if (!parserStates.empty()) { diff --git a/frontends/p4-14/fromv1.0/programStructure.cpp b/frontends/p4-14/fromv1.0/programStructure.cpp index de5c041aa1a..270f8afacdd 100644 --- a/frontends/p4-14/fromv1.0/programStructure.cpp +++ b/frontends/p4-14/fromv1.0/programStructure.cpp @@ -25,6 +25,7 @@ limitations under the License. #include "frontends/p4/reservedWords.h" #include "frontends/p4/tableKeyNames.h" #include "frontends/parsers/parserDriver.h" +#include "ir/annotations.h" #include "lib/big_int_util.h" #include "lib/bitops.h" @@ -81,15 +82,9 @@ ProgramStructure::ProgramStructure() for (auto c : P4::reservedWords) allNames.insert({c, 0}); } -const IR::Annotations *ProgramStructure::addNameAnnotation(cstring name, - const IR::Annotations *annos) { - if (annos == nullptr) annos = IR::Annotations::empty; - return annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); -} - -const IR::Annotations *ProgramStructure::addGlobalNameAnnotation(cstring name, - const IR::Annotations *annos) { - return addNameAnnotation("."_cs + name, annos); +IR::Vector ProgramStructure::addGlobalNameAnnotation( + cstring name, const IR::Vector &annos) { + return IR::Annotations::addNameAnnotation(absl::StrCat(".", name), annos); } cstring ProgramStructure::makeUniqueName(cstring base) { @@ -180,11 +175,13 @@ cstring ProgramStructure::createType(const IR::Type_StructLike *type, bool heade auto type_name = types.get(type); auto newType = type->apply(TypeConverter(this)); if (newType->name.name != type_name) { - auto annos = addNameAnnotation(type->name.name, type->annotations); + auto annos = IR::Annotations::addNameAnnotation(type->name.name, type->annotations); if (header) { - newType = new IR::Type_Header(newType->srcInfo, type_name, annos, newType->fields); + newType = + new IR::Type_Header(newType->srcInfo, type_name, std::move(annos), newType->fields); } else { - newType = new IR::Type_Struct(newType->srcInfo, type_name, annos, newType->fields); + newType = + new IR::Type_Struct(newType->srcInfo, type_name, std::move(annos), newType->fields); } } if (header) finalHeaderType.emplace(type->externalName(), newType); @@ -240,8 +237,9 @@ void ProgramStructure::createTypes() { // Must convert to a struct type cstring type_name = makeUniqueName(st->name.name); // Registers always use struct types - auto annos = addNameAnnotation(layoutTypeName, type->annotations); - auto newType = new IR::Type_Struct(type->srcInfo, type_name, annos, st->fields); + auto newType = new IR::Type_Struct( + type->srcInfo, type_name, + IR::Annotations::addNameAnnotation(layoutTypeName, type->annotations), st->fields); checkHeaderType(newType, false); LOG3("Added type " << dbp(newType) << " named " << type_name << " from " << dbp(type)); declarations->push_back(newType); @@ -278,8 +276,8 @@ const IR::Type_Struct *ProgramStructure::createFieldListType(const IR::Expressio } auto name = makeUniqueName(nr->path->name.name); - auto annos = addNameAnnotation(nr->path->name); - auto result = new IR::Type_Struct(expression->srcInfo, name, annos); + auto result = new IR::Type_Struct(expression->srcInfo, name, + IR::Annotations::addNameAnnotation(nr->path->name, {})); std::set fieldNames; int field_id = 0; for (auto f : fl->fields) { @@ -499,6 +497,8 @@ const IR::Type *ProgramStructure::explodeType( return new IR::Type_Tuple(*rv); } +static const cstring parserValueSetSizeAnnotation = "parser_value_set_size"_cs; + /** * convert a P4-14 parser to P4-16 parser state. * @param parser The P4-14 parser IR node to be converted @@ -555,9 +555,9 @@ const IR::ParserState *ProgramStructure::convertParser( value_sets_implemented.emplace(first->path->name); auto type = explodeType(fieldTypes); - auto sizeAnnotation = value_set->getAnnotation("parser_value_set_size"_cs); const IR::Constant *sizeConstant; - if (sizeAnnotation) { + if (const auto *sizeAnnotation = + value_set->getAnnotation(parserValueSetSizeAnnotation)) { if (sizeAnnotation->expr.size() != 1) { ::P4::error(ErrorType::ERR_INVALID, "@size should be an integer for declaration %1%", value_set); @@ -882,6 +882,9 @@ void ProgramStructure::createDeparser() { createDeparserInternal(v1model.deparser.Id(), packetOut, headers); } +static const cstring modeAnnotation = "mode"_cs; +static const cstring typeAnnotation = "type"_cs; + const IR::Declaration_Instance *ProgramStructure::convertActionProfile( const IR::ActionProfile *action_profile, cstring newName) { auto *action_selector = action_selectors.get(action_profile->selector.name); @@ -890,7 +893,7 @@ const IR::Declaration_Instance *ProgramStructure::convertActionProfile( action_profile->selector); const IR::Type *type = nullptr; auto args = new IR::Vector(); - auto annos = addGlobalNameAnnotation(action_profile->name); + auto annos = addGlobalNameAnnotation(action_profile->name, {}); if (action_selector) { type = new IR::Type_Name(new IR::Path(v1model.action_selector.Id())); auto flc = field_list_calculations.get(action_selector->key.name); @@ -903,13 +906,11 @@ const IR::Declaration_Instance *ProgramStructure::convertActionProfile( auto width = new IR::Constant(v1model.action_selector.widthType, flc->output_width); args->push_back(new IR::Argument(width)); if (action_selector->mode) - annos = annos->addAnnotation("mode"_cs, new IR::StringLiteral(action_selector->mode)); + annos.emplace_back(modeAnnotation, new IR::StringLiteral(action_selector->mode)); if (action_selector->type) - annos = annos->addAnnotation("type"_cs, new IR::StringLiteral(action_selector->type)); + annos.emplace_back(typeAnnotation, new IR::StringLiteral(action_selector->type)); auto fl = getFieldLists(flc); - for (auto annot : fl->annotations->annotations) { - annos = annos->add(annot); - } + annos.append(fl->annotations); } else { type = new IR::Type_Name(new IR::Path(v1model.action_profile.Id())); auto size = new IR::Constant(action_profile->srcInfo, v1model.action_profile.sizeType, @@ -959,7 +960,7 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr if (!table->default_action.name.isNullOrEmpty() && !actionList->getDeclaration(default_action)) { actionList->push_back(new IR::ActionListElement( - new IR::Annotations({new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}), + {new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}, new IR::PathExpression(default_action))); } props->push_back( @@ -973,7 +974,7 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr if (rt.name == "valid") rt.name = p4lib.exactMatch.Id(); auto ce = conv.convert(e); - const IR::Annotations *annos = IR::Annotations::empty; + IR::Vector annos; // Generate a name annotation for the key if it contains a mask. if (auto bin = e->to()) { // This is a bit heuristic, but P4-14 does not allow arbitrary expressions for keys @@ -982,11 +983,11 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr name = bin->right->toString(); else if (bin->right->is()) name = bin->left->toString(); - if (!name.isNullOrEmpty()) annos = addNameAnnotation(name, annos); + if (!name.isNullOrEmpty()) annos = IR::Annotations::addNameAnnotation(name, annos); } // Here we rely on the fact that the spelling of 'rt' is // the same in P4-14 and core.p4/v1model.p4. - auto keyComp = new IR::KeyElement(annos, ce, new IR::PathExpression(rt)); + auto keyComp = new IR::KeyElement(ce, new IR::PathExpression(rt), annos); key->push_back(keyComp); } @@ -1069,7 +1070,7 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr auto path = new IR::PathExpression(name); auto propvalue = new IR::ExpressionValue(path); auto prop = new IR::Property(IR::ID(v1model.tableAttributes.counters.Id()), - IR::Annotations::empty, propvalue, false); + IR::Vector(), propvalue, false); props->push_back(prop); } @@ -1080,9 +1081,8 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr props->push_back(prop); } - auto annos = addGlobalNameAnnotation(table->name, table->annotations); - auto result = new IR::P4Table(table->srcInfo, newName, annos, props); - return result; + return new IR::P4Table(table->srcInfo, newName, + addGlobalNameAnnotation(table->name, table->annotations), props); } const IR::Expression *ProgramStructure::convertHashAlgorithm(Util::SourceInfo srcInfo, @@ -1140,13 +1140,15 @@ static bool sameBitsType(const IR::Node *errorPosition, const IR::Type *left, return true; // to prevent inserting a cast } +static const cstring saturatingAnnotation = "saturating"_cs; + static bool isSaturatedField(const IR::Expression *expr) { auto member = expr->to(); if (!member) return false; auto header_type = member->expr->type->to(); if (!header_type) return false; auto field = header_type->getField(member->member.name); - if (field && field->getAnnotation("saturating"_cs)) { + if (field && field->hasAnnotation(saturatingAnnotation)) { return true; } return false; @@ -1977,9 +1979,9 @@ const IR::P4Action *ProgramStructure::convertAction(const IR::ActionFunction *ac } // Save the original action name in an annotation - auto annos = addGlobalNameAnnotation(action->name, action->annotations); - auto result = new IR::P4Action(action->srcInfo, newName, annos, params, body); - return result; + return new IR::P4Action(action->srcInfo, newName, + addGlobalNameAnnotation(action->name, action->annotations), params, + body); } const IR::Type_Control *ProgramStructure::controlType(IR::ID name) { @@ -2072,9 +2074,8 @@ const IR::Declaration_Instance *ProgramStructure::convert(const IR::Register *re args->push_back( new IR::Argument(new IR::Constant(v1model.registers.size_type, reg->instance_count))); } - auto annos = addGlobalNameAnnotation(reg->name, reg->annotations); - auto decl = new IR::Declaration_Instance(newName, annos, spectype, args, nullptr); - return decl; + return new IR::Declaration_Instance( + newName, addGlobalNameAnnotation(reg->name, reg->annotations), spectype, args, nullptr); } const IR::Declaration_Instance *ProgramStructure::convert(const IR::CounterOrMeter *cm, @@ -2096,13 +2097,10 @@ const IR::Declaration_Instance *ProgramStructure::convert(const IR::CounterOrMet args->push_back(new IR::Argument(kindarg)); auto annos = addGlobalNameAnnotation(cm->name, cm->annotations); if (auto *c = cm->to()) { - if (c->min_width >= 0) - annos = annos->addAnnotation("min_width"_cs, new IR::Constant(c->min_width)); - if (c->max_width >= 0) - annos = annos->addAnnotation("max_width"_cs, new IR::Constant(c->max_width)); + if (c->min_width >= 0) annos.emplace_back("min_width"_cs, new IR::Constant(c->min_width)); + if (c->max_width >= 0) annos.emplace_back("max_width"_cs, new IR::Constant(c->max_width)); } - auto decl = new IR::Declaration_Instance(newName, annos, type, args, nullptr); - return decl; + return new IR::Declaration_Instance(newName, std::move(annos), type, args, nullptr); } const IR::Declaration_Instance *ProgramStructure::convertDirectMeter(const IR::Meter *m, @@ -2128,10 +2126,9 @@ const IR::Declaration_Instance *ProgramStructure::convertDirectMeter(const IR::M auto annos = addGlobalNameAnnotation(m->name, m->annotations); if (m->pre_color != nullptr) { auto meterPreColor = ExpressionConverter(this).convert(m->pre_color); - if (meterPreColor != nullptr) annos = annos->addAnnotation("pre_color"_cs, meterPreColor); + if (meterPreColor != nullptr) annos.emplace_back("pre_color"_cs, meterPreColor); } - auto decl = new IR::Declaration_Instance(newName, annos, specType, args, nullptr); - return decl; + return new IR::Declaration_Instance(newName, std::move(annos), specType, args, nullptr); } const IR::Declaration_Instance *ProgramStructure::convertDirectCounter(const IR::Counter *c, @@ -2145,12 +2142,9 @@ const IR::Declaration_Instance *ProgramStructure::convertDirectCounter(const IR: auto kindarg = counterType(c); args->push_back(new IR::Argument(kindarg)); auto annos = addGlobalNameAnnotation(c->name, c->annotations); - if (c->min_width >= 0) - annos = annos->addAnnotation("min_width"_cs, new IR::Constant(c->min_width)); - if (c->max_width >= 0) - annos = annos->addAnnotation("max_width"_cs, new IR::Constant(c->max_width)); - auto decl = new IR::Declaration_Instance(newName, annos, type, args, nullptr); - return decl; + if (c->min_width >= 0) annos.emplace_back("min_width"_cs, new IR::Constant(c->min_width)); + if (c->max_width >= 0) annos.emplace_back("max_width"_cs, new IR::Constant(c->max_width)); + return new IR::Declaration_Instance(newName, std::move(annos), type, args, nullptr); } IR::Vector *ProgramStructure::createApplyArguments(cstring /* name unused */) { @@ -2307,9 +2301,8 @@ const IR::P4Control *ProgramStructure::convertControl(const IR::V1Control *contr cstring newname = controls.get(control); auto typepath = new IR::Path(IR::ID(newname)); auto type = new IR::Type_Name(typepath); - auto annos = addGlobalNameAnnotation(cc); - auto decl = new IR::Declaration_Instance(IR::ID(iname), annos, type, - new IR::Vector(), nullptr); + auto decl = new IR::Declaration_Instance(IR::ID(iname), addGlobalNameAnnotation(cc, {}), + type, new IR::Vector(), nullptr); locals.push_back(decl); } } @@ -2456,9 +2449,7 @@ const IR::FieldList *ProgramStructure::getFieldLists(const IR::FieldListCalculat } result->fields.insert(result->fields.end(), fl->fields.begin(), fl->fields.end()); result->payload = result->payload || fl->payload; - for (auto annot : fl->annotations->annotations) { - result->annotations = result->annotations->add(annot); - } + result->annotations.append(fl->annotations); } return result; } @@ -2513,18 +2504,14 @@ void ProgramStructure::createChecksumVerifications() { auto mc = new IR::MethodCallStatement(new IR::MethodCallExpression(method, args)); body->push_back(mc); - - for (auto annot : cf->annotations->annotations) - body->annotations = body->annotations->add(annot); - - for (auto annot : flc->annotations->annotations) - body->annotations = body->annotations->add(annot); + body->annotations.append(cf->annotations); + body->annotations.append(flc->annotations); LOG3("Converted " << flc); } } - verifyChecksums = new IR::P4Control(v1model.verify.Id(), type, - *new IR::IndexedVector(), body); + verifyChecksums = + new IR::P4Control(v1model.verify.Id(), type, IR::IndexedVector(), body); declarations->push_back(verifyChecksums); conversionContext->clear(); } @@ -2579,22 +2566,18 @@ void ProgramStructure::createChecksumUpdates() { auto methodCallExpression = new IR::MethodCallExpression(method, args); auto mc = new IR::MethodCallStatement(methodCallExpression); if (flc->algorithm->names[0] == "csum16_udp") { - auto zeros_as_ones_annot = - new IR::Annotation(IR::ID("zeros_as_ones"), {methodCallExpression}, false); - body->annotations = body->annotations->add(zeros_as_ones_annot); + body->annotations.emplace_back("zeros_as_ones"_cs, methodCallExpression); } - for (auto annot : cf->annotations->annotations) { - auto newAnnot = new IR::Annotation(annot->name, {}, false); - for (auto expr : annot->expr) newAnnot->expr.push_back(expr); + for (auto *annot : cf->annotations) { + auto newAnnot = new IR::Annotation(annot->name, annot->expr, false); newAnnot->expr.push_back(new IR::StringLiteral(methodCallExpression->toString())); - body->annotations = body->annotations->add(newAnnot); + body->annotations.push_back(newAnnot); } - for (auto annot : flc->annotations->annotations) { - auto newAnnot = new IR::Annotation(annot->name, {}, false); - for (auto expr : annot->expr) newAnnot->expr.push_back(expr); + for (auto *annot : flc->annotations) { + auto newAnnot = new IR::Annotation(annot->name, annot->expr, false); newAnnot->expr.push_back(new IR::StringLiteral(methodCallExpression->toString())); - body->annotations = body->annotations->add(newAnnot); + body->annotations.push_back(newAnnot); } body->push_back(mc); diff --git a/frontends/p4-14/fromv1.0/programStructure.h b/frontends/p4-14/fromv1.0/programStructure.h index 14bb14ce195..7c38ab91b54 100644 --- a/frontends/p4-14/fromv1.0/programStructure.h +++ b/frontends/p4-14/fromv1.0/programStructure.h @@ -214,33 +214,13 @@ class ProgramStructure { virtual const IR::Statement *convertPrimitive(const IR::Primitive *primitive); virtual void checkHeaderType(const IR::Type_StructLike *hrd, bool toStruct); - /** - * Extend the provided set of annotations with an '@name' annotation for the - * given name. This is used to preserve the original, P4-14 object names. - * - * In general, because P4-14 names do not have the hierarchical structure - * that P4-16 names do, you should use addGlobalNameAnnotation() rather than - * this method. The exception is type names; these are already global in - * P4-16, so there isn't much to be gained, and there is currently some code - * that doesn't handling "." prefixes in type names well. - * - * XXX(seth): For uniformity, we should probably fix the issues with "." in - * type names and get rid of this method. - * - * @param annos The set of annotations to extend. If null, a new set of - * annotations is created. - * @return the extended set of annotations. - */ - static const IR::Annotations *addNameAnnotation(cstring name, - const IR::Annotations *annos = nullptr); - /** * Like addNameAnnotation(), but prefixes a "." to make the name global. You * should generally prefer this method; @see addNameAnnotation() for more * discussion. */ - static const IR::Annotations *addGlobalNameAnnotation(cstring name, - const IR::Annotations *annos = nullptr); + static IR::Vector addGlobalNameAnnotation( + cstring name, const IR::Vector &annos); virtual const IR::ParserState *convertParser(const IR::V1Parser *, IR::IndexedVector *); diff --git a/frontends/p4-14/header_type.cpp b/frontends/p4-14/header_type.cpp index a6b7bd855c2..c6a7a7b6595 100644 --- a/frontends/p4-14/header_type.cpp +++ b/frontends/p4-14/header_type.cpp @@ -21,22 +21,16 @@ namespace P4 { using namespace P4::literals; bool HeaderTypeMaxLengthCalculator::preorder(IR::Type_StructLike *hdr_type) { - IR::Annotations *annot = nullptr; - auto *max_length = hdr_type->getAnnotation("max_length"_cs); + auto *max_length = hdr_type->getAnnotation(IR::Annotation::maxLengthAnnotation); if (!max_length) { unsigned len = 0; for (auto field : hdr_type->fields) len += field->type->width_bits(); - max_length = new IR::Annotation("max_length"_cs, len); - if (!annot) annot = hdr_type->annotations->clone(); - annot->annotations.push_back(max_length); + max_length = new IR::Annotation(IR::Annotation::maxLengthAnnotation, len); + hdr_type->addAnnotation(max_length); } - auto *length = hdr_type->getAnnotation("length"_cs); - if (!length) { - if (!annot) annot = hdr_type->annotations->clone(); - length = new IR::Annotation("length"_cs, max_length->expr); - annot->annotations.push_back(length); - } - if (annot) hdr_type->annotations = annot; + if (!hdr_type->hasAnnotation(IR::Annotation::lengthAnnotation)) + hdr_type->addAnnotation( + new IR::Annotation(IR::Annotation::lengthAnnotation, max_length->expr)); return false; } diff --git a/frontends/p4-14/ir-v1.def b/frontends/p4-14/ir-v1.def index b38fd3b900f..39b1899bbae 100644 --- a/frontends/p4-14/ir-v1.def +++ b/frontends/p4-14/ir-v1.def @@ -86,12 +86,13 @@ class Type_AnyTable : Type_Base { abstract HeaderOrMetadata : IAnnotated { ID type_name; ID name; - Annotations annotations; + optional inline Vector annotations; NullOK Type_StructLike type = nullptr; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } HeaderOrMetadata(ID n, Type_StructLike t) - : type_name(t->name), name(n), annotations(Annotations::empty), type(t) {} + : type_name(t->name), name(n), type(t) {} dbprint { out << type_name << ' ' << name; } } @@ -223,9 +224,10 @@ class Primitive : Operation { class FieldList : IAnnotated { optional ID name; bool payload = false; - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; inline Vector fields = {}; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } class FieldListCalculation : IAnnotated { @@ -234,8 +236,9 @@ class FieldListCalculation : IAnnotated { NullOK FieldList input_fields = nullptr; NullOK NameList algorithm = nullptr; int output_width = 0; - optional Annotations annotations = Annotations::empty; - Annotations getAnnotations() const override { return annotations; } + optional inline Vector annotations; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } class CalculatedField : IAnnotated { @@ -248,8 +251,9 @@ class CalculatedField : IAnnotated { update_or_verify() { } // FIXME -- needed by umpack_json(safe_vector) -- should not be } safe_vector specs = {}; - Annotations annotations; - Annotations getAnnotations() const override { return annotations; } + optional inline Vector annotations; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } visit_children { v.visit(field, "field"); for (auto &s : specs) v.visit(s.cond, s.name.name.c_str()); @@ -258,8 +262,9 @@ class CalculatedField : IAnnotated { class ParserValueSet : IAnnotated { ID name; - optional Annotations annotations = Annotations::empty; - Annotations getAnnotations() const override { return annotations; } + optional inline Vector annotations; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } dbprint { out << node_type_name() << " " << name; } toString { return node_type_name() + " " + name; } } @@ -277,8 +282,9 @@ class V1Parser :IAnnotated { ID default_return = {}; ID parse_error = {}; bool drop = false; - Annotations annotations; - Annotations getAnnotations() const override { return annotations; } + optional inline Vector annotations; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } toString { return node_type_name() + " " + name; } } @@ -286,11 +292,12 @@ class ParserException {} abstract Attached : IInstance, IAnnotated { optional ID name; - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; ID Name() const override { return name; } virtual const char *kind() const = 0; Type getType() const override { return Type_Unknown::get(); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } virtual bool indexed() const { return false; } Attached *clone_rename(const char *ext) const { Attached *rv = clone(); @@ -367,9 +374,10 @@ class ActionFunction : IAnnotated { optional ID name; inline Vector action = {}; safe_vector args = {}; - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } ActionArg arg(cstring n) const { for (auto a : args) if (a->name == n) @@ -417,10 +425,11 @@ class V1Table : IInstance, IAnnotated { bool default_action_is_const = false; NullOK Vector default_action_args = 0; inline TableProperties properties = {}; // non-standard properties - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; void addProperty(Property prop) { properties.push_back(prop); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } toString { return node_type_name() + " " + name; } ID Name() const override { return name; } Type getType() const override { return Type_AnyTable::get(); } @@ -429,12 +438,13 @@ class V1Table : IInstance, IAnnotated { class V1Control : IAnnotated { ID name; Vector code; - Annotations annotations; + optional inline Vector annotations; V1Control(ID n) : name(n), code(new Vector()) {} V1Control(Util::SourceInfo si, ID n) : Node(si), name(n), code(new Vector()) {} #apply - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } toString { return node_type_name() + " " + name; } } diff --git a/frontends/p4/actionsInlining.cpp b/frontends/p4/actionsInlining.cpp index 7111af78e8a..3c78985a78c 100644 --- a/frontends/p4/actionsInlining.cpp +++ b/frontends/p4/actionsInlining.cpp @@ -20,6 +20,7 @@ limitations under the License. #include "frontends/p4/evaluator/substituteParameters.h" #include "frontends/p4/methodInstance.h" #include "frontends/p4/parameterSubstitution.h" +#include "ir/vector.h" namespace P4 { @@ -141,11 +142,12 @@ const IR::Node *ActionsInliner::preorder(IR::MethodCallStatement *statement) { } } - auto annotations = callee->annotations->where([&](const IR::Annotation *a) { + auto annotations = callee->annotations.where([&](const IR::Annotation *a) { return !(a->name == IR::Annotation::nameAnnotation || (a->name == IR::Annotation::noWarnAnnotation && a->getSingleString() == "unused")); }); - auto result = new IR::BlockStatement(statement->srcInfo, annotations, body); + auto result = new IR::BlockStatement(statement->srcInfo, + {annotations->begin(), annotations->end()}, body); LOG2("Replacing " << orig << " with " << result); return result; } diff --git a/frontends/p4/createBuiltins.cpp b/frontends/p4/createBuiltins.cpp index 3e0beaab5fe..70b66a3eee9 100644 --- a/frontends/p4/createBuiltins.cpp +++ b/frontends/p4/createBuiltins.cpp @@ -122,7 +122,7 @@ const IR::Node *CreateBuiltins::postorder(IR::ActionList *actions) { if (decl != nullptr) return actions; checkGlobalAction(); actions->push_back(new IR::ActionListElement( - new IR::Annotations({new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}), + {new IR::Annotation(IR::Annotation::defaultOnlyAnnotation, {})}, new IR::MethodCallExpression( new IR::PathExpression(P4::P4CoreLibrary::instance().noAction.Id(actions->srcInfo)), new IR::Vector(), new IR::Vector()))); diff --git a/frontends/p4/deprecated.cpp b/frontends/p4/deprecated.cpp index f29ef72867f..9b20f0b4e69 100644 --- a/frontends/p4/deprecated.cpp +++ b/frontends/p4/deprecated.cpp @@ -20,7 +20,7 @@ namespace P4 { void Deprecated::warnIfDeprecated(const IR::IAnnotated *annotated, const IR::Node *errorNode) { if (annotated == nullptr) return; - auto anno = annotated->getAnnotation(IR::Annotation::deprecatedAnnotation); + const auto *anno = annotated->getAnnotation(IR::Annotation::deprecatedAnnotation); if (anno == nullptr) return; std::string message; diff --git a/frontends/p4/directCalls.cpp b/frontends/p4/directCalls.cpp index ecb4bb8eff4..390bcdbfe77 100644 --- a/frontends/p4/directCalls.cpp +++ b/frontends/p4/directCalls.cpp @@ -33,10 +33,10 @@ const IR::Node *InstantiateDirectCalls::postorder(IR::MethodCallExpression *expr auto name = nameGen.newName(tname->path->name + "_inst"); LOG3("Inserting instance " << name); - auto annos = new IR::Annotations(); - annos->add(new IR::Annotation(IR::Annotation::nameAnnotation, tname->path->toString())); - auto inst = new IR::Declaration_Instance(expression->srcInfo, IR::ID(name), annos, - tn->typeName->clone(), new IR::Vector()); + auto inst = new IR::Declaration_Instance( + expression->srcInfo, IR::ID(name), + {new IR::Annotation(IR::Annotation::nameAnnotation, tname->path->toString())}, + tn->typeName->clone(), new IR::Vector()); insert.push_back(inst); auto path = new IR::PathExpression(expression->srcInfo, diff --git a/frontends/p4/inlining.cpp b/frontends/p4/inlining.cpp index e8505276b65..5f60dde86b7 100644 --- a/frontends/p4/inlining.cpp +++ b/frontends/p4/inlining.cpp @@ -25,6 +25,7 @@ limitations under the License. #include "frontends/p4/resetHeaders.h" #include "frontends/p4/toP4/toP4.h" #include "frontends/p4/typeChecking/typeChecker.h" +#include "ir/annotations.h" #include "lib/nullstream.h" namespace P4 { @@ -220,12 +221,6 @@ class ComputeNewNames : public Inspector { void postorder(const IR::Declaration_Variable *decl) override { rename(decl); } }; -// Add a @name annotation ONLY. -static const IR::Annotations *setNameAnnotation(cstring name, const IR::Annotations *annos) { - if (annos == nullptr) annos = IR::Annotations::empty; - return annos->addOrReplace(IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); -} - /** Perform multiple substitutions and rename global objects, such as tables, actions and instances. Unfortunately these transformations @@ -248,37 +243,35 @@ class Substitutions : public SubstituteParameters { cstring newName = renameMap->getName(orig); cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << " (" << extName << ")"); - auto annos = setNameAnnotation(extName, table->annotations); - auto result = new IR::P4Table(table->srcInfo, newName, annos, table->properties); - return result; + return new IR::P4Table(table->srcInfo, newName, + IR::Annotations::setNameAnnotation(extName, table->annotations), + table->properties); } const IR::Node *postorder(IR::P4ValueSet *set) override { auto orig = getOriginal(); cstring newName = renameMap->getName(orig); cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); - auto annos = setNameAnnotation(extName, set->annotations); - auto result = new IR::P4ValueSet(set->srcInfo, newName, annos, set->elementType, set->size); - return result; + return new IR::P4ValueSet(set->srcInfo, newName, + IR::Annotations::setNameAnnotation(extName, set->annotations), + set->elementType, set->size); } const IR::Node *postorder(IR::P4Action *action) override { auto orig = getOriginal(); cstring newName = renameMap->getName(orig); cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); - auto annos = setNameAnnotation(extName, action->annotations); - auto result = - new IR::P4Action(action->srcInfo, newName, annos, action->parameters, action->body); - return result; + return new IR::P4Action(action->srcInfo, newName, + IR::Annotations::setNameAnnotation(extName, action->annotations), + action->parameters, action->body); } const IR::Node *postorder(IR::Declaration_Instance *instance) override { auto orig = getOriginal(); cstring newName = renameMap->getName(orig); cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); - auto annos = setNameAnnotation(extName, instance->annotations); instance->name = newName; - instance->annotations = annos; + instance->annotations = IR::Annotations::setNameAnnotation(extName, instance->annotations); return instance; } const IR::Node *postorder(IR::Declaration_Variable *decl) override { @@ -286,9 +279,8 @@ class Substitutions : public SubstituteParameters { cstring newName = renameMap->getName(orig); cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); - auto annos = setNameAnnotation(extName, decl->annotations); decl->name = newName; - decl->annotations = annos; + decl->annotations = IR::Annotations::setNameAnnotation(extName, decl->annotations); return decl; } const IR::Node *postorder(IR::PathExpression *expression) override { @@ -464,7 +456,7 @@ void GeneralInliner::inline_subst(P4Block *caller, LOG3("Analyzing " << dbp(caller)); IR::IndexedVector locals; P4BlockType *type = (caller->*blockType)->clone(); - IR::Annotations *annos = type->annotations->clone(); + IR::Vector annos = type->annotations; for (auto s : caller->*blockLocals) { /* Even if we inline the block, the declaration may still be needed. Consider this example: @@ -487,11 +479,9 @@ void GeneralInliner::inline_subst(P4Block *caller, workToDo->substitutions[inst] = substs; // Propagate annotations - const IR::Annotations *calleeAnnos = (callee->*blockType)->annotations; - for (auto *ann : calleeAnnos->annotations) { - if (!annos->getSingle(ann->name) && !Inline::isAnnotationNoPropagate(ann->name)) { - annos->add(ann); - } + for (const auto *ann : (callee->*blockType)->annotations) { + if (Inline::isAnnotationNoPropagate(ann->name)) continue; + IR::Annotations::addIfNew(annos, ann); } // Substitute constructor parameters @@ -592,7 +582,7 @@ void GeneralInliner::inline_subst(P4Block *caller, } } caller->*blockLocals = locals; - type->annotations = annos; + type->annotations = std::move(annos); caller->*blockType = type; } @@ -678,7 +668,7 @@ const IR::Node *GeneralInliner::preorder(IR::MethodCallStatement *statement) { } } - auto annotations = callee->type->annotations->where( + auto annotations = callee->type->annotations.where( [](const IR::Annotation *a) { return a->name != IR::Annotation::nameAnnotation; }); auto result = new IR::BlockStatement(statement->srcInfo, annotations, body); LOG3("Replacing " << dbp(orig) << " with " << dbp(result)); @@ -888,8 +878,8 @@ const IR::Node *GeneralInliner::preorder(IR::ParserState *state) { } // Prepare next state - annotations = IR::Annotations::empty; name = IR::ID(nextState, state->name); + annotations.clear(); current.clear(); // Copy back out and inout parameters diff --git a/frontends/p4/localizeActions.cpp b/frontends/p4/localizeActions.cpp index f0b338a6138..e0e8daa7c84 100644 --- a/frontends/p4/localizeActions.cpp +++ b/frontends/p4/localizeActions.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "localizeActions.h" #include "frontends/p4/cloner.h" +#include "ir/annotations.h" namespace P4 { @@ -41,12 +42,9 @@ class ParamCloner : public CloneExpressions { const IR::Node *TagGlobalActions::preorder(IR::P4Action *action) { if (findContext() == nullptr) { - auto annos = action->annotations; - if (annos == nullptr) annos = IR::Annotations::empty; - cstring name = "."_cs + action->name; - annos = annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, - new IR::StringLiteral(name), false); - action->annotations = annos; + cstring name = absl::StrCat(".", action->name); + action->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(name), + false); } prune(); return action; @@ -78,13 +76,10 @@ bool FindGlobalActionUses::preorder(const IR::PathExpression *path) { auto replBody = cloner.clone(action->body); auto params = cloner.clone(action->parameters); - auto annos = action->annotations; - if (annos == nullptr) annos = IR::Annotations::empty; - annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, - new IR::StringLiteral(action->name), false); auto replacement = new IR::P4Action( action->srcInfo, IR::ID(action->name.srcInfo, newName, action->name.originalName), - annos, params, replBody); + IR::Annotations::addNameAnnotation(action->name, action->annotations), params, + replBody); repl->addReplacement(action, control, replacement); } return false; @@ -166,15 +161,12 @@ bool FindRepeatedActionUses::preorder(const IR::PathExpression *expression) { auto newName = nameGen.newName(action->name.string_view()); ParamCloner cloner; auto replBody = cloner.clone(action->body); - auto annos = action->annotations; auto params = cloner.clone(action->parameters); - if (annos == nullptr) annos = IR::Annotations::empty; - annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, - new IR::StringLiteral(action->name), false); replacement = new IR::P4Action( action->srcInfo, IR::ID(action->name.srcInfo, newName, action->name.originalName), - annos, params, replBody); + IR::Annotations::addNameAnnotation(action->name, action->annotations), params, + replBody); repl->createReplacement(action, actionUser, replacement); } repl->setRefReplacement(expression, replacement); diff --git a/frontends/p4/methodInstance.cpp b/frontends/p4/methodInstance.cpp index 8098cd7a71a..075b8236964 100644 --- a/frontends/p4/methodInstance.cpp +++ b/frontends/p4/methodInstance.cpp @@ -213,7 +213,7 @@ std::vector ExternMethod::mayCall() const { if (auto *am = di->initializer->components.getDeclaration(meth->name)) { rv.push_back(am); - } else if (!meth->getAnnotation(IR::Annotation::optionalAnnotation)) { + } else if (!meth->hasAnnotation(IR::Annotation::optionalAnnotation)) { error(ErrorType::ERR_INVALID, "No implementation for abstract %s in %s called via %s", meth, di, method); diff --git a/frontends/p4/reassociation.h b/frontends/p4/reassociation.h index 8825f36c4d8..e29fba21138 100644 --- a/frontends/p4/reassociation.h +++ b/frontends/p4/reassociation.h @@ -43,7 +43,9 @@ class Reassociation final : public Transform { const IR::Node *postorder(IR::BAnd *expr) override { return reassociate(expr); } const IR::Node *postorder(IR::BXor *expr) override { return reassociate(expr); } const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->getAnnotation("disable_optimization"_cs)) prune(); + // FIXME: Do we need to check for expression, so we'd be able to fine tune, e.g. + // @disable_optimization("reassociation") + if (bs->hasAnnotation(IR::Annotation::disableOptimizationAnnotation)) prune(); return bs; } }; diff --git a/frontends/p4/sideEffects.h b/frontends/p4/sideEffects.h index 8844bebc244..e0445016385 100644 --- a/frontends/p4/sideEffects.h +++ b/frontends/p4/sideEffects.h @@ -118,29 +118,13 @@ class SideEffects : public Inspector { // * isValid() // * function, extern function, or extern method with noSideEffects annotation auto mi = MethodInstance::resolve(mce, refMap, typeMap); - if (auto em = mi->to()) { - if (em->method->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) { - return false; - } - return true; - } - if (auto ef = mi->to()) { - if (ef->method->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) { - return false; - } - return true; - } - if (auto ef = mi->to()) { - if (ef->function->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) { - return false; - } - return true; - } - if (auto bim = mi->to()) { - if (bim->name.name == IR::Type_Header::isValid) { - return false; - } - } + if (const auto *em = mi->to()) + return !em->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); + if (const auto *ef = mi->to()) + return !ef->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); + if (const auto *ef = mi->to()) + return !ef->function->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); + if (const auto *bim = mi->to()) return bim->name != IR::Type_Header::isValid; return true; } }; diff --git a/frontends/p4/simplify.cpp b/frontends/p4/simplify.cpp index e20ac25c245..5f215385e99 100644 --- a/frontends/p4/simplify.cpp +++ b/frontends/p4/simplify.cpp @@ -23,7 +23,7 @@ namespace P4 { const IR::Node *DoSimplifyControlFlow::postorder(IR::BlockStatement *statement) { LOG3("Visiting " << dbp(getOriginal())); - if (statement->annotations->size() > 0) return statement; + if (statement->hasAnnotations()) return statement; auto parent = getContext()->node; CHECK_NULL(parent); if (parent->is() || parent->is() || parent->is() || diff --git a/frontends/p4/simplifyDefUse.h b/frontends/p4/simplifyDefUse.h index b8c88fbc3b5..b3dcfb556eb 100644 --- a/frontends/p4/simplifyDefUse.h +++ b/frontends/p4/simplifyDefUse.h @@ -53,9 +53,7 @@ class DoSimplifyDefUse : public Transform { class RemoveHidden : public Transform { const IR::Node *postorder(IR::BlockStatement *stat) override { if (!stat->components.empty()) return stat; - if (stat->annotations->size() != 1) return stat; - auto anno = stat->getAnnotation(IR::Annotation::hiddenAnnotation); - if (!anno) return stat; + if (!stat->hasOnlyAnnotation(IR::Annotation::hiddenAnnotation)) return stat; // Lose the annotation. return new IR::BlockStatement(stat->srcInfo); } @@ -78,11 +76,10 @@ class SimplifyDefUse : public PassManager { // it and add an new annotation to force it to be // different from the original one. if (stat->components.empty()) { - auto annos = new IR::Annotations(); // We are losing the original annotations, but hopefully these don't // matter on an empty block. - annos->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); - auto result = new IR::BlockStatement(stat->srcInfo, annos); + auto result = new IR::BlockStatement( + stat->srcInfo, {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}); LOG2("Cloning " << getOriginal()->id << " into " << result->id); return result; } diff --git a/frontends/p4/simplifyParsers.cpp b/frontends/p4/simplifyParsers.cpp index 39f40533718..dd5fbe327e2 100644 --- a/frontends/p4/simplifyParsers.cpp +++ b/frontends/p4/simplifyParsers.cpp @@ -120,10 +120,8 @@ class CollapseChains : public Transform { for (auto oe : *transitions) { auto node = oe.first; // Avoid merging in case of state annotation - if (!node->annotations->annotations.empty()) { - if (!node->getAnnotation(IR::Annotation::nameAnnotation) || - node->annotations->annotations.size() != 1) - continue; + if (node->hasAnnotations()) { + if (!node->hasOnlyAnnotation(IR::Annotation::nameAnnotation)) continue; } auto outedges = oe.second; if (outedges->size() != 1) continue; @@ -134,7 +132,7 @@ class CollapseChains : public Transform { auto callers = transitions->getCallers(next); if (callers->size() != 1) continue; // Avoid merging in case of state annotation - if (!next->annotations->annotations.empty()) + if (next->hasAnnotations()) // we are not sure what to do with the annotations continue; chain.emplace(node, next); diff --git a/frontends/p4/strengthReduction.h b/frontends/p4/strengthReduction.h index 79eea6ff837..7026bd9655b 100644 --- a/frontends/p4/strengthReduction.h +++ b/frontends/p4/strengthReduction.h @@ -111,7 +111,9 @@ class DoStrengthReduction final : public Transform { const IR::Node *postorder(IR::ArrayIndex *expr) override; const IR::BlockStatement *preorder(IR::BlockStatement *bs) override { - if (bs->getAnnotation("disable_optimization"_cs)) prune(); + // FIXME: Do we need to check for expression, so we'd be able to fine tune, e.g. + // @disable_optimization("strength_reduce") + if (bs->hasAnnotation(IR::Annotation::disableOptimizationAnnotation)) prune(); return bs; } }; diff --git a/frontends/p4/tableKeyNames.cpp b/frontends/p4/tableKeyNames.cpp index dfc30daa1df..7a66b06ec01 100644 --- a/frontends/p4/tableKeyNames.cpp +++ b/frontends/p4/tableKeyNames.cpp @@ -125,20 +125,18 @@ void KeyNameGenerator::postorder(const IR::MethodCallExpression *expression) { const IR::Node *DoTableKeyNames::postorder(IR::KeyElement *keyElement) { LOG3("Visiting " << getOriginal()); - if (keyElement->getAnnotation(IR::Annotation::nameAnnotation) != nullptr) + if (keyElement->hasAnnotation(IR::Annotation::nameAnnotation)) // already present: no changes return keyElement; KeyNameGenerator kng(typeMap); - ; kng.setCalledBy(this); (void)keyElement->expression->apply(kng); cstring name = kng.getName(keyElement->expression); LOG3("Generated name " << name); if (!name) return keyElement; - keyElement->annotations = keyElement->annotations->addAnnotation( - IR::Annotation::nameAnnotation, - new IR::StringLiteral(keyElement->expression->srcInfo, name), false); + keyElement->addAnnotation(IR::Annotation::nameAnnotation, + new IR::StringLiteral(keyElement->expression->srcInfo, name)); return keyElement; } diff --git a/frontends/p4/toP4/toP4.cpp b/frontends/p4/toP4/toP4.cpp index 92390092bb4..3f211a587fe 100644 --- a/frontends/p4/toP4/toP4.cpp +++ b/frontends/p4/toP4/toP4.cpp @@ -274,12 +274,19 @@ bool ToP4::preorder(const IR::Argument *arg) { return false; } +bool ToP4::printAnnotations(const IR::IAnnotated *ann) { + if (!ann->hasAnnotations()) return false; + + setVecSep(" "); + visit(&ann->getAnnotations()); + doneVec(); + + return true; +} + bool ToP4::preorder(const IR::Type_Typedef *t) { dump(2); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("typedef "); visit(t->type); builder.spc(); @@ -290,10 +297,7 @@ bool ToP4::preorder(const IR::Type_Typedef *t) { bool ToP4::preorder(const IR::Type_Newtype *t) { dump(2); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("type "); visit(t->type); builder.spc(); @@ -319,10 +323,7 @@ bool ToP4::preorder(const IR::Type_BaseList *t) { bool ToP4::preorder(const IR::P4ValueSet *t) { dump(1); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("value_set<"); auto p4type = t->elementType->getP4Type(); CHECK_NULL(p4type); @@ -339,10 +340,7 @@ bool ToP4::preorder(const IR::P4ValueSet *t) { bool ToP4::preorder(const IR::Type_Enum *t) { dump(1); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("enum "); builder.append(t->name); builder.spc(); @@ -362,10 +360,7 @@ bool ToP4::preorder(const IR::Type_Enum *t) { bool ToP4::preorder(const IR::Type_SerEnum *t) { dump(1); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("enum "); visit(t->type); builder.spc(); @@ -406,10 +401,7 @@ bool ToP4::preorder(const IR::TypeParameters *t) { bool ToP4::preorder(const IR::Method *m) { dump(1); - if (!m->annotations->annotations.empty()) { - visit(m->annotations); - builder.spc(); - } + if (printAnnotations(m)) builder.spc(); const Context *ctx = getContext(); bool standaloneFunction = !ctx || !ctx->node->is(); // standalone function declaration: not in a Vector of methods @@ -431,10 +423,7 @@ bool ToP4::preorder(const IR::Method *m) { bool ToP4::preorder(const IR::Function *function) { dump(1); - if (!function->annotations->annotations.empty()) { - visit(function->annotations); - builder.spc(); - } + if (printAnnotations(function)) builder.spc(); auto t = function->type; BUG_CHECK(t != nullptr, "Function %1% has no type", function); if (t->returnType != nullptr) { @@ -452,10 +441,7 @@ bool ToP4::preorder(const IR::Function *function) { bool ToP4::preorder(const IR::Type_Extern *t) { dump(2); if (isDeclaration) { - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("extern "); } builder.append(t->name); @@ -499,10 +485,7 @@ bool ToP4::preorder(const IR::Type_Varbits *t) { bool ToP4::preorder(const IR::Type_Package *package) { dump(2); builder.emitIndent(); - if (!package->annotations->annotations.empty()) { - visit(package->annotations); - builder.spc(); - } + if (printAnnotations(package)) builder.spc(); builder.append("package "); builder.append(package->name); visit(package->typeParameters); @@ -515,11 +498,9 @@ bool ToP4::process(const IR::Type_StructLike *t, const char *name) { dump(2); if (isDeclaration) { builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } - builder.appendFormat("%s ", name); + if (printAnnotations(t)) builder.spc(); + builder.append(name); + builder.spc(); } builder.append(t->name); visit(t->typeParameters); @@ -541,12 +522,9 @@ bool ToP4::process(const IR::Type_StructLike *t, const char *name) { for (auto f : t->fields) { dump(4, f, 1); // this will dump annotations - if (f->annotations->size() > 0) { + if (f->hasAnnotations()) { builder.emitIndent(); - if (!f->annotations->annotations.empty()) { - visit(f->annotations); - } - builder.newline(); + if (printAnnotations(f)) builder.newline(); } builder.emitIndent(); cstring t = get(type, f); @@ -564,10 +542,7 @@ bool ToP4::process(const IR::Type_StructLike *t, const char *name) { bool ToP4::preorder(const IR::Type_Parser *t) { dump(2); builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("parser "); builder.append(t->name); visit(t->typeParameters); @@ -579,10 +554,7 @@ bool ToP4::preorder(const IR::Type_Parser *t) { bool ToP4::preorder(const IR::Type_Control *t) { dump(2); builder.emitIndent(); - if (!t->annotations->annotations.empty()) { - visit(t->annotations); - builder.spc(); - } + if (printAnnotations(t)) builder.spc(); builder.append("control "); builder.append(t->name); visit(t->typeParameters); @@ -621,10 +593,7 @@ bool ToP4::preorder(const IR::StringLiteral *s) { bool ToP4::preorder(const IR::Declaration_Constant *cst) { dump(2); - if (!cst->annotations->annotations.empty()) { - visit(cst->annotations); - builder.spc(); - } + if (printAnnotations(cst)) builder.spc(); builder.append("const "); auto type = cst->type->getP4Type(); CHECK_NULL(type); @@ -643,10 +612,7 @@ bool ToP4::preorder(const IR::Declaration_Constant *cst) { bool ToP4::preorder(const IR::Declaration_Instance *i) { dump(3); - if (!i->annotations->annotations.empty()) { - visit(i->annotations); - builder.spc(); - } + if (printAnnotations(i)) builder.spc(); auto type = i->type->getP4Type(); CHECK_NULL(type); visit(type); @@ -667,10 +633,7 @@ bool ToP4::preorder(const IR::Declaration_Instance *i) { bool ToP4::preorder(const IR::Declaration_Variable *v) { dump(2); - if (!v->annotations->annotations.empty()) { - visit(v->annotations); - builder.spc(); - } + if (printAnnotations(v)) builder.spc(); auto type = v->type->getP4Type(); CHECK_NULL(type); visit(type); @@ -1121,10 +1084,7 @@ bool ToP4::preorder(const IR::AssignmentStatement *a) { bool ToP4::preorder(const IR::BlockStatement *s) { dump(1); - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.blockStart(); setVecSep("\n", "\n"); preorder(&s->components); @@ -1210,10 +1170,7 @@ bool ToP4::preorder(const IR::IfStatement *s) { bool ToP4::preorder(const IR::ForStatement *s) { dump(2); - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("for ("); bool first = true; for (auto *d : s->init) { @@ -1252,10 +1209,7 @@ bool ToP4::preorder(const IR::ForStatement *s) { bool ToP4::preorder(const IR::ForInStatement *s) { dump(2); - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("for ("); if (s->decl) { builder.supressStatementSemi(); @@ -1317,19 +1271,6 @@ bool ToP4::preorder(const IR::SwitchStatement *s) { //////////////////////////////////// -bool ToP4::preorder(const IR::Annotations *a) { - bool first = true; - for (const auto *anno : a->annotations) { - if (!first) { - builder.spc(); - } else { - first = false; - } - visit(anno); - } - return false; -} - bool ToP4::preorder(const IR::Annotation *a) { builder.append("@"); builder.append(a->name); @@ -1379,10 +1320,7 @@ bool ToP4::preorder(const IR::Annotation *a) { bool ToP4::preorder(const IR::Parameter *p) { dump(2); - if (!p->annotations->annotations.empty()) { - visit(p->annotations); - builder.spc(); - } + if (printAnnotations(p)) builder.spc(); switch (p->direction) { case IR::Direction::None: break; @@ -1448,10 +1386,7 @@ bool ToP4::preorder(const IR::ParameterList *p) { bool ToP4::preorder(const IR::P4Action *c) { dump(2); - if (!c->annotations->annotations.empty()) { - visit(c->annotations); - builder.spc(); - } + if (printAnnotations(c)) builder.spc(); builder.append("action "); builder.append(c->name); visit(c->parameters); @@ -1464,10 +1399,7 @@ bool ToP4::preorder(const IR::ParserState *s) { dump(1); if (s->isBuiltin()) return false; - if (!s->annotations->annotations.empty()) { - visit(s->annotations); - builder.spc(); - } + if (printAnnotations(s)) builder.spc(); builder.append("state "); builder.append(s->name); builder.spc(); @@ -1522,10 +1454,7 @@ bool ToP4::preorder(const IR::ExpressionValue *v) { bool ToP4::preorder(const IR::ActionListElement *ale) { dump(3); - if (!ale->annotations->annotations.empty()) { - visit(ale->annotations); - builder.spc(); - } + if (printAnnotations(ale)) builder.spc(); visit(ale->expression); return false; } @@ -1565,9 +1494,9 @@ bool ToP4::preorder(const IR::Key *v) { builder.append(std::string(spaces, ' ')); builder.append(": "); visit(f->matchType); - if (!f->annotations->annotations.empty()) { - builder.append(" "); - visit(f->annotations); + if (f->hasAnnotations()) { + builder.spc(); + printAnnotations(f); } builder.endOfStatement(true); } @@ -1577,10 +1506,7 @@ bool ToP4::preorder(const IR::Key *v) { bool ToP4::preorder(const IR::Property *p) { dump(1); - if (!p->annotations->annotations.empty()) { - visit(p->annotations); - builder.spc(); - } + if (printAnnotations(p)) builder.spc(); if (p->isConstant) builder.append("const "); builder.append(p->name); builder.append(" = "); @@ -1626,19 +1552,14 @@ bool ToP4::preorder(const IR::Entry *e) { doneList(); builder.append(" : "); visit(e->action); - if (!e->annotations->annotations.empty()) { - visit(e->annotations); - } + if (printAnnotations(e)) builder.spc(); builder.append(";"); return false; } bool ToP4::preorder(const IR::P4Table *c) { dump(2); - if (!c->annotations->annotations.empty()) { - visit(c->annotations); - builder.spc(); - } + if (printAnnotations(c)) builder.spc(); builder.append("table "); builder.append(c->name); builder.spc(); diff --git a/frontends/p4/toP4/toP4.h b/frontends/p4/toP4/toP4.h index 312ee68c3d2..6ae480ee1e1 100644 --- a/frontends/p4/toP4/toP4.h +++ b/frontends/p4/toP4/toP4.h @@ -84,6 +84,7 @@ class ToP4 : public Inspector, ResolutionContext { /// dump node IR tree up to depth - in the form of a comment void dump(unsigned depth, const IR::Node *node = nullptr, unsigned adjDepth = 0); unsigned curDepth() const; + bool printAnnotations(const IR::IAnnotated *ann); public: // Output is constructed here @@ -237,7 +238,6 @@ class ToP4 : public Inspector, ResolutionContext { bool preorder(const IR::Argument *arg) override; bool preorder(const IR::Path *p) override; bool preorder(const IR::Parameter *p) override; - bool preorder(const IR::Annotations *a) override; bool preorder(const IR::Annotation *a) override; bool preorder(const IR::P4Program *program) override; bool preorder(const IR::P4Control *c) override; diff --git a/frontends/p4/typeChecking/typeCheckDecl.cpp b/frontends/p4/typeChecking/typeCheckDecl.cpp index 96190ac8f09..2472da36d5a 100644 --- a/frontends/p4/typeChecking/typeCheckDecl.cpp +++ b/frontends/p4/typeChecking/typeCheckDecl.cpp @@ -213,7 +213,7 @@ bool TypeInferenceBase::checkAbstractMethods(const IR::Declaration_Instance *ins } bool rv = true; for (const auto &vm : virt) { - if (!vm.second->getAnnotation("optional"_cs)) { + if (!vm.second->hasAnnotation(IR::Annotation::optionalAnnotation)) { typeError("%1%: %2% abstract method not implemented", inst, vm.second); rv = false; } diff --git a/frontends/p4/typeChecking/typeCheckExpr.cpp b/frontends/p4/typeChecking/typeCheckExpr.cpp index 6bef4b9d2f8..fa00c9e0136 100644 --- a/frontends/p4/typeChecking/typeCheckExpr.cpp +++ b/frontends/p4/typeChecking/typeCheckExpr.cpp @@ -480,11 +480,8 @@ const IR::Node *TypeInferenceBase::postorder(const IR::Entry *entry) { entry = new IR::Entry(entry->srcInfo, entry->annotations, entry->isConst, entry->priority, ks->to(), entry->action, entry->singleton); - auto actionRef = entry->getAction(); - auto ale = validateActionInitializer(actionRef); - if (ale != nullptr) { - auto anno = ale->getAnnotation(IR::Annotation::defaultOnlyAnnotation); - if (anno != nullptr) { + if (auto ale = validateActionInitializer(entry->getAction())) { + if (ale->hasAnnotation(IR::Annotation::defaultOnlyAnnotation)) { typeError("%1%: Action marked with %2% used in table", entry, IR::Annotation::defaultOnlyAnnotation); return entry; @@ -2159,7 +2156,7 @@ const IR::Node *TypeInferenceBase::postorder(const IR::MethodCallExpression *exp baseReturnType = sc->baseType; const bool factoryOrStaticAssertOrPureAnnot = baseReturnType->is() || ef->method->name == "static_assert" || - ef->method->getAnnotation(IR::Annotation::pureAnnotation); + ef->method->hasAnnotation(IR::Annotation::pureAnnotation); if (constArgs && factoryOrStaticAssertOrPureAnnot) { // factory extern function calls (those that return extern objects) with constant // args are compile-time constants. diff --git a/frontends/p4/typeChecking/typeCheckStmt.cpp b/frontends/p4/typeChecking/typeCheckStmt.cpp index 0a439570391..e2d771278f9 100644 --- a/frontends/p4/typeChecking/typeCheckStmt.cpp +++ b/frontends/p4/typeChecking/typeCheckStmt.cpp @@ -330,10 +330,8 @@ const IR::Node *TypeInferenceBase::postorder(const IR::Property *prop) { // Check that the default action appears in the list of actions. BUG_CHECK(prop->value->is(), "%1% not an expression", prop); auto def = prop->value->to()->expression; - auto ale = validateActionInitializer(def); - if (ale != nullptr) { - auto anno = ale->getAnnotation(IR::Annotation::tableOnlyAnnotation); - if (anno != nullptr) { + if (auto ale = validateActionInitializer(def)) { + if (ale->hasAnnotation(IR::Annotation::tableOnlyAnnotation)) { typeError("%1%: Action marked with %2% used as default action", prop, IR::Annotation::tableOnlyAnnotation); return prop; diff --git a/frontends/p4/uniqueNames.cpp b/frontends/p4/uniqueNames.cpp index 3a97aeb3cbb..8990eb2af0b 100644 --- a/frontends/p4/uniqueNames.cpp +++ b/frontends/p4/uniqueNames.cpp @@ -98,13 +98,6 @@ IR::ID *RenameSymbols::getName(const IR::IDeclaration *decl) const { return name; } -const IR::Annotations *RenameSymbols::addNameAnnotation(cstring name, - const IR::Annotations *annos) { - if (annos == nullptr) annos = IR::Annotations::empty; - return annos->addAnnotationIfNew(IR::Annotation::nameAnnotation, new IR::StringLiteral(name), - false); -} - const IR::Node *RenameSymbols::postorder(IR::Declaration_Variable *decl) { return renameDeclWithNameAnnotation(decl); } diff --git a/frontends/p4/uniqueNames.h b/frontends/p4/uniqueNames.h index 3c78aefae19..13a8b8ca72f 100644 --- a/frontends/p4/uniqueNames.h +++ b/frontends/p4/uniqueNames.h @@ -130,17 +130,14 @@ class RenameSymbols : public Transform, public ResolutionContext { /// @param decl Declaration *in the original/non-transformed* P4 IR. IR::ID *getName(const IR::IDeclaration *decl) const; - /// Add a @name annotation ONLY if it does not already exist. - /// Otherwise do nothing. - static const IR::Annotations *addNameAnnotation(cstring name, const IR::Annotations *annos); - /// Rename any declaration where we want to add @name annotation with the original name. /// Has to be a template as there is no common base for declarations with annotations member. template const IR::Node *renameDeclWithNameAnnotation(D *decl) { auto name = getName(); if (name != nullptr && *name != decl->name) { - decl->annotations = addNameAnnotation(decl->name, decl->annotations); + decl->addAnnotationIfNew(IR::Annotation::nameAnnotation, + new IR::StringLiteral(decl->name)); decl->name = *name; } return decl; diff --git a/frontends/p4/validateParsedProgram.cpp b/frontends/p4/validateParsedProgram.cpp index a05df83add2..d19c0baf3c9 100644 --- a/frontends/p4/validateParsedProgram.cpp +++ b/frontends/p4/validateParsedProgram.cpp @@ -50,16 +50,12 @@ void ValidateParsedProgram::postorder(const IR::Method *m) { } /// Structured annotations cannot reuse names -void ValidateParsedProgram::postorder(const IR::Annotations *annotations) { - std::multiset namesUsed; - for (auto a : annotations->annotations) namesUsed.emplace(a->name); - - for (auto a : annotations->annotations) { - if (!a->structured) continue; - if (namesUsed.count(a->name) > 1) - ::P4::error(ErrorType::ERR_DUPLICATE, "%1%: duplicate name for structured annotation", - a); - } +void ValidateParsedProgram::postorder(const IR::Annotation *annotation) { + auto [it, inserted] = + annNames.emplace(std::pair(getContext()->node, annotation->name), annotation->structured); + if (!inserted && (it->second || annotation->structured)) + ::P4::error(ErrorType::ERR_DUPLICATE, "%1%: duplicate name for structured annotation", + annotation); } /// Struct field names cannot be underscore diff --git a/frontends/p4/validateParsedProgram.h b/frontends/p4/validateParsedProgram.h index 7eb0b23d527..7ce4330a7b9 100644 --- a/frontends/p4/validateParsedProgram.h +++ b/frontends/p4/validateParsedProgram.h @@ -52,6 +52,8 @@ using namespace literals; - continue and break statements are only used in the context of a for statement */ class ValidateParsedProgram final : public Inspector { + std::unordered_map, bool> annNames; + void container(const IR::IContainer *type); // Make sure that type, apply and constructor parameters are distinct void distinctParameters(const IR::TypeParameters *typeParams, const IR::ParameterList *apply, @@ -59,7 +61,8 @@ class ValidateParsedProgram final : public Inspector { public: ValidateParsedProgram() { setName("ValidateParsedProgram"); } - void postorder(const IR::Annotations *annotations) override; + void end_apply(const IR::Node *) override { annNames.clear(); } + void postorder(const IR::Annotation *annotations) override; void postorder(const IR::P4Program *program) override; void postorder(const IR::Constant *c) override; void postorder(const IR::SwitchStatement *statement) override; diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index eda9d1fe6de..4a514faa2e1 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -267,8 +267,7 @@ using namespace P4; %type*> argumentList nonEmptyArgList %type parameter %type optCONST -%type optAnnotations -%type*> annotations +%type*> optAnnotations annotations %type annotation %type*> annotationBody %type annotationToken @@ -513,8 +512,8 @@ optCONST ; optAnnotations - : %empty { $$ = IR::Annotations::empty; } - | annotations { $$ = new IR::Annotations(@1, *$1); } + : %empty { $$ = new IR::Vector(); } + | annotations { $$ = $1; } ; annotations @@ -746,8 +745,8 @@ nonEmptyParameterList ; parameter - : optAnnotations direction typeRef name { $$ = new IR::Parameter(@4, *$4, $1, $2, $3, nullptr); } - | optAnnotations direction typeRef name "=" expression { $$ = new IR::Parameter(@4, *$4, $1, $2, $3, $6); } + : optAnnotations direction typeRef name { $$ = new IR::Parameter(@4, *$4, *$1, $2, $3, nullptr); } + | optAnnotations direction typeRef name "=" expression { $$ = new IR::Parameter(@4, *$4, *$1, $2, $3, $6); } ; direction @@ -765,19 +764,19 @@ packageTypeDeclaration "(" parameterList ")" { driver.structure->declareParameters($8); auto pl = new IR::ParameterList(@8, *$8); - $$ = new IR::Type_Package(@3, *$3, $1, $5, pl); } + $$ = new IR::Type_Package(@3, *$3, *$1, $5, pl); } ; instantiation : annotations typeRef "(" argumentList ")" name ";" - { $$ = new IR::Declaration_Instance(@6, *$6, new IR::Annotations(*$1), + { $$ = new IR::Declaration_Instance(@6, *$6, *$1, $2, $4); driver.structure->declareObject(*$6, $2->toString()); } | typeRef "(" argumentList ")" name ";" { $$ = new IR::Declaration_Instance(@5, *$5, $1, $3); driver.structure->declareObject(*$5, $1->toString()); } | annotations typeRef "(" argumentList ")" name "=" objInitializer ";" - { $$ = new IR::Declaration_Instance(@6, *$6, new IR::Annotations(*$1), + { $$ = new IR::Declaration_Instance(@6, *$6, *$1, $2, $4, $8); driver.structure->declareObject(*$6, $2->toString()); } | typeRef "(" argumentList ")" name "=" objInitializer ";" @@ -840,7 +839,7 @@ parserTypeDeclaration driver.structure->declareTypes(&$5->parameters); } "(" parameterList ")" { driver.structure->declareParameters($8); auto pl = new IR::ParameterList(@8, *$8); - $$ = new IR::Type_Parser(@3, *$3, $1, $5, pl); } + $$ = new IR::Type_Parser(@3, *$3, *$1, $5, pl); } ; parserStates @@ -853,7 +852,7 @@ parserState : optAnnotations STATE name { driver.structure->pushContainerType(*$3, false); } "{" parserStatements transitionStatement "}" { driver.structure->pop(); - $$ = new IR::ParserState(@3, *$3, $1, *$6, $7); } + $$ = new IR::ParserState(@3, *$3, *$1, *$6, $7); } ; parserStatements @@ -873,7 +872,7 @@ parserStatement parserBlockStatement : optAnnotations "{" { driver.structure->pushNamespace(@2, false); } - parserStatements "}" { driver.structure->pop(); $$ = new IR::BlockStatement(@1+@5, $1, *$4); } + parserStatements "}" { driver.structure->pop(); $$ = new IR::BlockStatement(@1+@5, *$1, *$4); } ; transitionStatement @@ -943,13 +942,13 @@ simpleKeysetExpression valueSetDeclaration : optAnnotations VALUESET l_angle baseType r_angle "(" expression ")" name ";" - { $$ = new IR::P4ValueSet(@9, *$9, $1, $4, $7); } + { $$ = new IR::P4ValueSet(@9, *$9, *$1, $4, $7); } | optAnnotations VALUESET l_angle tupleType r_angle "(" expression ")" name ";" - { $$ = new IR::P4ValueSet(@9, *$9, $1, $4, $7); } + { $$ = new IR::P4ValueSet(@9, *$9, *$1, $4, $7); } | optAnnotations VALUESET l_angle typeName r_angle "(" expression ")" name ";" - { $$ = new IR::P4ValueSet(@9, *$9, $1, $4, $7); } + { $$ = new IR::P4ValueSet(@9, *$9, *$1, $4, $7); } ; /*************************** CONTROL ************************/ @@ -969,7 +968,7 @@ controlTypeDeclaration driver.structure->declareTypes(&$5->parameters); } "(" parameterList ")" { driver.structure->declareParameters($8); auto pl = new IR::ParameterList(@8, *$8); - $$ = new IR::Type_Control(@3, *$3, $1, $5, pl); } + $$ = new IR::Type_Control(@3, *$3, *$1, $5, pl); } ; controlLocalDeclarations @@ -997,11 +996,11 @@ externDeclaration optTypeParameters { if (!$5->empty()) driver.structure->markAsTemplate(*$3); driver.structure->declareTypes(&$5->parameters); } "{" methodPrototypes "}" { driver.structure->pop(); - $$ = new IR::Type_Extern(@3, *$3, $5, *$8, $1); } + $$ = new IR::Type_Extern(@3, *$3, $5, *$8, *$1); } | optAnnotations EXTERN functionPrototype ";" { driver.structure->pop(); $$ = $3; - $3->annotations = $1; } + $3->annotations = *$1; } | optAnnotations EXTERN name ";" { // forward declaration; driver.structure->pushContainerType(*$3, true); @@ -1030,15 +1029,15 @@ functionPrototype methodPrototype : optAnnotations functionPrototype ";" { driver.structure->pop(); - $$ = $2; $2->annotations = $1; } + $$ = $2; $2->annotations = *$1; } | optAnnotations ABSTRACT functionPrototype ";" { driver.structure->pop(); $$ = $3; $$->setAbstract(); - $3->annotations = $1; } + $3->annotations = *$1; } | optAnnotations TYPE_IDENTIFIER "(" parameterList ")" ";" // constructor { auto par = new IR::ParameterList(@4, *$4); auto mt = new IR::Type_Method(@2, par, $2); - $$ = new IR::Method(@2, IR::ID(@2, $2), mt, $1); } + $$ = new IR::Method(@2, IR::ID(@2, $2), mt, *$1); } ; /************************** TYPES ****************************/ @@ -1174,7 +1173,7 @@ headerTypeDeclaration : optAnnotations HEADER name { driver.structure->pushContainerType(*$3, true); } optTypeParameters { driver.structure->markAsTemplate(*$3); driver.structure->declareTypes(&$5->parameters); } - "{" structFieldList "}" { $$ = new IR::Type_Header(@3, *$3, $1, $5, *$8); + "{" structFieldList "}" { $$ = new IR::Type_Header(@3, *$3, *$1, $5, *$8); driver.structure->pop(); } ; @@ -1182,7 +1181,7 @@ structTypeDeclaration : optAnnotations STRUCT name { driver.structure->pushContainerType(*$3, true); } optTypeParameters { driver.structure->markAsTemplate(*$3); driver.structure->declareTypes(&$5->parameters); } - "{" structFieldList "}" { $$ = new IR::Type_Struct(@3, *$3, $1, $5, *$8); + "{" structFieldList "}" { $$ = new IR::Type_Struct(@3, *$3, *$1, $5, *$8); driver.structure->pop(); } ; @@ -1190,7 +1189,7 @@ headerUnionDeclaration : optAnnotations HEADER_UNION name { driver.structure->pushContainerType(*$3, true); } optTypeParameters { driver.structure->markAsTemplate(*$3); driver.structure->declareTypes(&$5->parameters); } - "{" structFieldList "}" { $$ = new IR::Type_HeaderUnion(@3, *$3, $1, $5, *$8); + "{" structFieldList "}" { $$ = new IR::Type_HeaderUnion(@3, *$3, *$1, $5, *$8); driver.structure->pop(); } ; @@ -1200,17 +1199,17 @@ structFieldList ; structField - : optAnnotations typeRef name ";" { $$ = new IR::StructField(@3, *$3, $1, $2); } + : optAnnotations typeRef name ";" { $$ = new IR::StructField(@3, *$3, *$1, $2); } ; enumDeclaration : optAnnotations ENUM name { driver.structure->declareType(*$3); } - "{" identifierList optTrailingComma "}" { $$ = new IR::Type_Enum(@3, *$3, *$6); } + "{" identifierList optTrailingComma "}" { $$ = new IR::Type_Enum(@3, *$3, *$1, *$6); } | optAnnotations ENUM typeRef name { driver.structure->declareType(*$4); } "{" specifiedIdentifierList optTrailingComma "}" { auto type = $typeRef; - $$ = new IR::Type_SerEnum(@4, *$4, type, *$7); + $$ = new IR::Type_SerEnum(@4, *$4, *$1, type, *$7); } ; @@ -1243,11 +1242,11 @@ identifierList typedefDeclaration : optAnnotations TYPEDEF typeRef name { driver.structure->declareType(*$4); - $$ = new IR::Type_Typedef(@4, *$4, new IR::Annotations(*$1), $3); } + $$ = new IR::Type_Typedef(@4, *$4, *$1, $3); } | optAnnotations TYPEDEF derivedTypeDeclaration name { driver.structure->declareType(*$4); - $$ = new IR::Type_Typedef(@4, *$4, new IR::Annotations(*$1), $3); } + $$ = new IR::Type_Typedef(@4, *$4, *$1, $3); } | optAnnotations TYPE typeRef name { driver.structure->declareType(*$4); - $$ = new IR::Type_Newtype(@4, *$4, new IR::Annotations(*$1), $3); } + $$ = new IR::Type_Newtype(@4, *$4, *$1, $3); } ; /*************************** STATEMENTS *************************/ @@ -1332,7 +1331,7 @@ statement blockStatement : optAnnotations "{" { driver.structure->pushNamespace(@2, false); } statOrDeclList "}" { driver.structure->pop(); - $$ = new IR::BlockStatement(@1 + @5, $1, *$4); } + $$ = new IR::BlockStatement(@1 + @5, *$1, *$4); } ; statOrDeclList @@ -1376,13 +1375,13 @@ forStatement expression ";" forUpdateStatements ")" statement - { $$ = new IR::ForStatement(@2+@9, $1, *$4, $6, *$8, $10); } + { $$ = new IR::ForStatement(@2+@9, *$1, *$4, $6, *$8, $10); } | optAnnotations FOR "(" typeRef name IN forCollectionExpr ")" statement { auto decl = new IR::Declaration_Variable(@4+@5, *$5, $4); - $$ = new IR::ForInStatement(@2+@7, $1, decl, $7, $9); } + $$ = new IR::ForInStatement(@2+@7, *$1, decl, $7, $9); } | optAnnotations FOR "(" annotations typeRef name IN forCollectionExpr ")" statement - { auto decl = new IR::Declaration_Variable(@5+@6, *$6, new IR::Annotations(@4, *$4), $5); - $$ = new IR::ForInStatement(@2+@8, $1, decl, $8, $10); } + { auto decl = new IR::Declaration_Variable(@5+@6, *$6, *$4, $5); + $$ = new IR::ForInStatement(@2+@8, *$1, decl, $8, $10); } ; forInitStatements @@ -1424,7 +1423,7 @@ forCollectionExpr tableDeclaration : optAnnotations TABLE name "{" tablePropertyList "}" - { $$ = new IR::P4Table(@3, *$3, $1, new IR::TableProperties(@5, *$5)); } + { $$ = new IR::P4Table(@3, *$3, *$1, new IR::TableProperties(@5, *$5)); } ; tablePropertyList @@ -1445,11 +1444,11 @@ tableProperty | optAnnotations optCONST ENTRIES "=" "{" entriesList "}" { auto l = new IR::EntriesList(@3, *$6); auto id = IR::ID(@3+@7, "entries"_cs); - $$ = new IR::Property(@3, id, $1, l, $2.isConst); } + $$ = new IR::Property(@3, id, *$1, l, $2.isConst); } | optAnnotations optCONST nonTableKwName "=" initializer ";" { auto v = new IR::ExpressionValue(@5, $5); auto id = *$3; - $$ = new IR::Property($3->srcInfo, id, $1, v, $2.isConst); } + $$ = new IR::Property($3->srcInfo, id, *$1, v, $2.isConst); } ; keyElementList @@ -1460,13 +1459,13 @@ keyElementList keyElement : expression ":" name optAnnotations ";" { auto expr = new IR::PathExpression(*$3); - $$ = new IR::KeyElement(@1, $4, $1, expr); } + $$ = new IR::KeyElement(@1, $1, expr, *$4); } ; actionList : %empty { $$ = new IR::IndexedVector(); } | actionList optAnnotations actionRef ";" - { $$ = $1; $$->push_back(new IR::ActionListElement(@3, $2, $3)); $$->srcInfo = @1 + @3; } + { $$ = $1; $$->push_back(new IR::ActionListElement(@3, *$2, $3)); $$->srcInfo = @1 + @3; } ; actionRef @@ -1481,10 +1480,10 @@ entry // below we set the position starting at @3 because optional // fields generate weird position information. { if (auto l = $3->to()) - $$ = new IR::Entry(@3+@6, $6, $1.isConst, $2, l, $5, false); + $$ = new IR::Entry(@3+@6, *$6, $1.isConst, $2, l, $5, false); else { // if not a tuple, make it a list of 1 IR::Vector le($3); - $$ = new IR::Entry(@3+@6, $6, $1.isConst, $2, + $$ = new IR::Entry(@3+@6, *$6, $1.isConst, $2, new IR::ListExpression(@3, le), $5, true); } } @@ -1492,10 +1491,10 @@ entry // below we set the position starting at @2 because optional // fields generate weird position information. { if (auto l = $2->to()) - $$ = new IR::Entry(@2+@5, $5, $1.isConst, nullptr, l, $4, false); + $$ = new IR::Entry(@2+@5, *$5, $1.isConst, nullptr, l, $4, false); else { // if not a tuple, make it a list of 1 IR::Vector le($2); - $$ = new IR::Entry(@2+@5, $5, $1.isConst, nullptr, + $$ = new IR::Entry(@2+@5, *$5, $1.isConst, nullptr, new IR::ListExpression(@2, le), $4, true); } } @@ -1516,7 +1515,7 @@ entriesList actionDeclaration : optAnnotations ACTION name "(" parameterList ")" blockStatement { auto pl = new IR::ParameterList(@5, *$5); - $$ = new IR::P4Action(@3, *$3, $1, pl, $7); } + $$ = new IR::P4Action(@3, *$3, *$1, pl, $7); } ; /************************* VARIABLES *****************************/ @@ -1527,8 +1526,7 @@ variableDeclaration variableDeclarationWithoutSemicolon : annotations typeRef name optInitializer - { auto ann = new IR::Annotations(@1, *$1); - $$ = new IR::Declaration_Variable(@1+@4, *$3, ann, $2, $4); + { $$ = new IR::Declaration_Variable(@1+@4, *$3, *$1, $2, $4); driver.structure->declareObject(*$3, $2->toString()); } | typeRef name optInitializer { $$ = new IR::Declaration_Variable(@1+@3, *$2, $1, $3); @@ -1537,7 +1535,7 @@ variableDeclarationWithoutSemicolon constantDeclaration : optAnnotations CONST typeRef name "=" initializer ";" - { $$ = new IR::Declaration_Constant(@4, *$4, $1, $3, $6); + { $$ = new IR::Declaration_Constant(@4, *$4, *$1, $3, $6); driver.structure->declareObject(*$4, $3->toString()); } ; @@ -1554,9 +1552,8 @@ initializer functionDeclaration : annotations functionPrototype blockStatement { - auto ann = new IR::Annotations(@1, *$1); driver.structure->pop(); - $$ = new IR::Function($2->srcInfo, $2->name, ann, $2->type, $3); } + $$ = new IR::Function($2->srcInfo, $2->name, *$1, $2->type, $3); } | functionPrototype blockStatement { driver.structure->pop(); $$ = new IR::Function($1->srcInfo, $1->name, $1->type, $2); } diff --git a/frontends/parsers/parserDriver.cpp b/frontends/parsers/parserDriver.cpp index da0ff243491..3e26d3f04b4 100644 --- a/frontends/parsers/parserDriver.cpp +++ b/frontends/parsers/parserDriver.cpp @@ -362,11 +362,4 @@ IR::Vector V1ParserDriver::takePragmasAsVector() { return pragmas; } -const IR::Annotations *V1ParserDriver::takePragmasAsAnnotations() { - if (currentPragmas.empty()) return IR::Annotations::empty; - auto *rv = new IR::Annotations(currentPragmas); - currentPragmas.clear(); - return rv; -} - } // namespace P4::V1 diff --git a/frontends/parsers/parserDriver.h b/frontends/parsers/parserDriver.h index 53d41bd8d52..92d8041502f 100644 --- a/frontends/parsers/parserDriver.h +++ b/frontends/parsers/parserDriver.h @@ -281,10 +281,6 @@ class V1ParserDriver final : public P4::AbstractParserDriver { /// @return a IR::Vector containing the active pragmas, and clear the list. IR::Vector takePragmasAsVector(); - /// @return an IR::Annotations object containing the active pragmas, and - /// clear the list. - const IR::Annotations *takePragmasAsAnnotations(); - //////////////////////////////////////////////////////////////////////////// // Shared state manipulated directly by the lexer and parser. //////////////////////////////////////////////////////////////////////////// diff --git a/frontends/parsers/v1/v1parser.ypp b/frontends/parsers/v1/v1parser.ypp index 140a687332b..f640d1ffbb8 100644 --- a/frontends/parsers/v1/v1parser.ypp +++ b/frontends/parsers/v1/v1parser.ypp @@ -230,7 +230,7 @@ static const IR::Expression *removeRedundantValid(const IR::Expression *e); %type action_function_body action_statement_list %type action_profile_body %type action_selector_body -%type blackbox_method +%type*> blackbox_method %type apply_case_list %type blackbox_attribute %type local_var @@ -301,9 +301,9 @@ header_type_declaration: HEADER_TYPE name "{" header_dec_body "}" { $4.annotations->append(driver.takePragmasAsVector()); driver.global->add($2, new IR::v1HeaderType(@1+@5, $2, new IR::Type_Struct(@1+@5, IR::ID(@2, $2), - new IR::Annotations(*$4.annotations), *$4.fields), + *$4.annotations, *$4.fields), new IR::Type_Header(@1+@5, IR::ID(@2, $2), - new IR::Annotations(*$4.annotations), *$4.fields))); } + *$4.annotations, *$4.fields))); } | HEADER_TYPE name "{" header_dec_body error END { driver.clearPragmas(); } ; @@ -321,7 +321,7 @@ field_declarations: /* epsilon */ if ($5.signed_ && type->is()) type = IR::Type::Bits::get(type->to()->size, true); ($$=$1).fields->push_back(new IR::StructField(@2+@4, IR::ID(@2, $2), - new IR::Annotations($5.annotations), type)); } + $5.annotations, type)); } | field_declarations type name ";" { ($$=$1).fields->push_back(new IR::StructField(@2+@4, IR::ID(@3, $3), $2)); } ; @@ -387,10 +387,10 @@ type: BIT { $$ = IR::Type::Bits::get(@1, 1); } header_instance: HEADER name name ";" { driver.global->add($3, new IR::Header(@1+@4, IR::ID(@2, $2), IR::ID(@3, $3), - driver.takePragmasAsAnnotations())); } + driver.takePragmasAsVector())); } | HEADER name name "[" const_expression "]" ";" { driver.global->add($3, new IR::HeaderStack(@1+@7, IR::ID(@2, $2), IR::ID(@3, $3), - driver.takePragmasAsAnnotations(), + driver.takePragmasAsVector(), $5 ? $5->asLong() : 0)); $5 = nullptr; } ; @@ -398,7 +398,7 @@ header_instance: metadata_instance: METADATA name name opt_metadata_initializer ";" { driver.global->add($3, new IR::Metadata(@1+@5, IR::ID(@2, $2), IR::ID(@3, $3), - driver.takePragmasAsAnnotations())); } + driver.takePragmasAsVector())); } ; opt_metadata_initializer: /* epsilon */ @@ -422,7 +422,7 @@ field_list_declaration: ; field_list_entries: - /* epsilon */ { $$ = new IR::FieldList(driver.takePragmasAsAnnotations()); } + /* epsilon */ { $$ = new IR::FieldList(driver.takePragmasAsVector()); } | field_list_entries expression ";" /* const_expression or field_ref or name */ { ($$=$1)->fields.push_back($2); } | field_list_entries PAYLOAD ";" @@ -440,7 +440,7 @@ field_list_calculation_declaration: ; field_list_calculation_body: /* epsilon */ - { $$ = new IR::FieldListCalculation(driver.takePragmasAsAnnotations()); } + { $$ = new IR::FieldListCalculation(driver.takePragmasAsVector()); } | field_list_calculation_body INPUT "{" field_list_list "}" { if ($1->input) ::P4::error(ErrorType::ERR_INVALID, "%s: multiple 'input' in field_list_calculation", @2); @@ -477,7 +477,7 @@ calculated_field_declaration: ; update_verify_spec_list: /* epsilon */ - { $$ = new IR::CalculatedField(driver.takePragmasAsAnnotations()); } + { $$ = new IR::CalculatedField(driver.takePragmasAsVector()); } | update_verify_spec_list UPDATE name opt_condition ";" { ($$=$1)->specs.emplace_back(@1+@3, true, IR::ID(@3, $3), $4); } | update_verify_spec_list VERIFY name opt_condition ";" @@ -496,7 +496,7 @@ opt_condition: /* epsilon */ { $$ = nullptr; } value_set_declaration: PARSER_VALUE_SET name ";" - { driver.global->add($2, new IR::ParserValueSet(@1, IR::ID(@2, $2), driver.takePragmasAsAnnotations())); } + { driver.global->add($2, new IR::ParserValueSet(@1, IR::ID(@2, $2), driver.takePragmasAsVector())); } /************************/ /* 4.4 Parser Functions */ @@ -509,7 +509,7 @@ parser_function_declaration: ; parser_statement_list: /* epsilon */ - { $$ = new IR::V1Parser(driver.takePragmasAsAnnotations()); } + { $$ = new IR::V1Parser(driver.takePragmasAsVector()); } | parser_statement_list EXTRACT "(" header_ref ")" ";" { ($$=$1)->stmts.push_back(new IR::Primitive(@2+@5, $2, $4)); } | parser_statement_list SET_METADATA "(" expression "," expression ")" ";" @@ -575,7 +575,7 @@ counter_declaration: COUNTER name "{" counter_spec_list "}" counter_spec_list: TYPE ":" name ";" - { ($$ = new IR::Counter(driver.takePragmasAsAnnotations()))->settype($3); } + { ($$ = new IR::Counter(driver.takePragmasAsVector()))->settype($3); } | counter_spec_list DIRECT ":" name ";" { if (($$=$1)->table) ::P4::error(ErrorType::ERR_INVALID, "%s: Can't attach counter to two tables", @2+@4); @@ -610,7 +610,7 @@ meter_declaration : METER name "{" meter_spec_list "}" meter_spec_list: TYPE ":" name ";" - { ($$ = new IR::Meter(driver.takePragmasAsAnnotations()))->settype($3); } + { ($$ = new IR::Meter(driver.takePragmasAsVector()))->settype($3); } | meter_spec_list RESULT ":" field_ref ";" { ($$=$1)->result = $4; } | meter_spec_list PRE_COLOR ":" field_ref ";" @@ -646,11 +646,11 @@ register_declaration: REGISTER name "{" register_spec_list "}" register_spec_list: WIDTH ":" const_expression ";" - { $$ = new IR::Register(driver.takePragmasAsAnnotations()); + { $$ = new IR::Register(driver.takePragmasAsVector()); $$->width = $3 ? $3->asLong() : 0; $3 = nullptr; } | LAYOUT ":" name ";" - { $$ = new IR::Register(driver.takePragmasAsAnnotations()); + { $$ = new IR::Register(driver.takePragmasAsVector()); $$->layout = IR::ID(@3, $3); } | register_spec_list DIRECT ":" name ";" { if (($$=$1)->table) @@ -709,7 +709,7 @@ action_function_body: ; action_statement_list: /* epsilon */ - { $$ = new IR::ActionFunction(driver.takePragmasAsAnnotations()); } + { $$ = new IR::ActionFunction(driver.takePragmasAsVector()); } | action_statement_list name "(" opt_expression_list ")" ";" { ($$ = $1)->action.push_back(new IR::Primitive(@2+@5, $2, $4)); } | action_statement_list field_ref "=" expression ";" @@ -731,7 +731,7 @@ action_profile_declaration: ACTION_PROFILE name "{" action_profile_body "}" ; action_profile_body: /* epsilon */ - { $$ = new IR::ActionProfile(driver.takePragmasAsAnnotations()); } + { $$ = new IR::ActionProfile(driver.takePragmasAsVector()); } | action_profile_body ACTIONS "{" action_list "}" { ($$=$1)->actions = $4->names; $4 = nullptr; } | action_profile_body SIZE ":" const_expression ";" @@ -745,7 +745,7 @@ action_selector_declaration: ACTION_SELECTOR name "{" action_selector_body "}" ; action_selector_body: /* epsilon */ - { $$ = new IR::ActionSelector(driver.takePragmasAsAnnotations()); } + { $$ = new IR::ActionSelector(driver.takePragmasAsVector()); } | action_selector_body SELECTION_KEY ":" name ";" { ($$=$1)->key = IR::ID(@4, $4); } | action_selector_body SELECTION_MODE ":" name ";" { ($$=$1)->mode = IR::ID(@4, $4); } | action_selector_body SELECTION_TYPE ":" name ";" { ($$=$1)->type = IR::ID(@4, $4); } @@ -763,7 +763,7 @@ table_declaration: TABLE name "{" table_body "}" ; table_body: /* epsilon */ - { $$ = new IR::V1Table(driver.takePragmasAsAnnotations()); } + { $$ = new IR::V1Table(driver.takePragmasAsVector()); } | table_body READS "{" field_match_list "}" { ($$=$1)->reads = $4; } | table_body READS "{" field_match_list error END @@ -837,7 +837,7 @@ action_list: /* epsilon */ { $$ = new IR::NameList(); } control_function_declaration: CONTROL name "{" control_statement_list "}" { driver.global->add($2, new IR::V1Control(@1+@5, IR::ID(@2, $2), $4, - driver.takePragmasAsAnnotations())); } + driver.takePragmasAsVector())); } | CONTROL name "{" control_statement_list error END ; @@ -880,7 +880,7 @@ apply_case_list: /* epsilon */ { $$ = new IR::Apply; } blackbox_type_declaration: BLACKBOX_TYPE name "{" blackbox_body "}" { driver.global->add($2, new IR::Type_Extern(@1+@5, IR::ID(@2, $2), *$4.methods, - *$4.attribs, driver.takePragmasAsAnnotations())); } + *$4.attribs, driver.takePragmasAsVector())); } ; blackbox_body: /* epsilon */ { @@ -907,11 +907,11 @@ blackbox_attribute: /* epsilon */ { $$ = new IR::Attribute($-1); } | blackbox_attribute error { $$ = $1; } ; -blackbox_method: { $$ = new IR::Annotations; } +blackbox_method: { $$ = new IR::Vector(); } | blackbox_method READS "{" opt_name_list "}" - { ($$=$1)->add(new IR::Annotation(@2, $2, driver.makeExpressionList($4))); } + { ($$=$1)->push_back(new IR::Annotation(@2, $2, driver.makeExpressionList($4))); } | blackbox_method WRITES "{" opt_name_list "}" - { ($$=$1)->add(new IR::Annotation(@2, $2, driver.makeExpressionList($4))); } + { ($$=$1)->push_back(new IR::Annotation(@2, $2, driver.makeExpressionList($4))); } ; opt_argument_list: @@ -928,7 +928,7 @@ argument: inout type name { $$ = new IR::Parameter(@3, $3, $1, $2); } | OPTIONAL argument - { ($$ = $2)->annotations = $2->annotations->add(new IR::Annotation(@1, $1, {})); } + { ($$ = $2)->annotations.push_back(new IR::Annotation(@1, $1, {})); } ; inout: IN { $$ = IR::Direction::In; } | OUT { $$ = IR::Direction::Out; } ; @@ -946,12 +946,12 @@ local_var: blackbox_instantiation: BLACKBOX name name ";" { driver.global->add($3, - new IR::Declaration_Instance(@3, $3, driver.takePragmasAsAnnotations(), + new IR::Declaration_Instance(@3, $3, driver.takePragmasAsVector(), new IR::Type_Name($2), new IR::Vector)); } | BLACKBOX name name "{" blackbox_config "}" { auto instance = - new IR::Declaration_Instance(@3, $3, driver.takePragmasAsAnnotations(), + new IR::Declaration_Instance(@3, $3, driver.takePragmasAsVector(), new IR::Type_Name($2), new IR::Vector); instance->properties = std::move(*$5); diff --git a/ir/CMakeLists.txt b/ir/CMakeLists.txt index 3767078c904..242f6d104c9 100644 --- a/ir/CMakeLists.txt +++ b/ir/CMakeLists.txt @@ -13,6 +13,7 @@ # limitations under the License. set (IR_SRCS + annotations.cpp base.cpp bitrange.cpp dbprint.cpp @@ -35,6 +36,7 @@ set (IR_SRCS ) set (IR_HDRS + annotations.h configuration.h dbprint.h dump.h diff --git a/ir/annotations.cpp b/ir/annotations.cpp new file mode 100644 index 00000000000..8aa95afa388 --- /dev/null +++ b/ir/annotations.cpp @@ -0,0 +1,85 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "annotations.h" + +#include "ir/ir.h" +#include "lib/algorithm.h" +#include "lib/cstring.h" + +namespace P4::IR { + +const cstring IR::Annotation::nameAnnotation = "name"_cs; +const cstring IR::Annotation::tableOnlyAnnotation = "tableonly"_cs; +const cstring IR::Annotation::defaultOnlyAnnotation = "defaultonly"_cs; +const cstring IR::Annotation::atomicAnnotation = "atomic"_cs; +const cstring IR::Annotation::hiddenAnnotation = "hidden"_cs; +const cstring IR::Annotation::lengthAnnotation = "length"_cs; +const cstring IR::Annotation::maxLengthAnnotation = "max_length"_cs; +const cstring IR::Annotation::optionalAnnotation = "optional"_cs; +const cstring IR::Annotation::pkginfoAnnotation = "pkginfo"_cs; +const cstring IR::Annotation::deprecatedAnnotation = "deprecated"_cs; +const cstring IR::Annotation::synchronousAnnotation = "synchronous"_cs; +const cstring IR::Annotation::pureAnnotation = "pure"_cs; +const cstring IR::Annotation::noSideEffectsAnnotation = "noSideEffects"_cs; +const cstring IR::Annotation::noWarnAnnotation = "noWarn"_cs; +const cstring IR::Annotation::matchAnnotation = "match"_cs; +const cstring IR::Annotation::fieldListAnnotation = "field_list"_cs; +const cstring IR::Annotation::debugLoggingAnnotation = "__debug"_cs; +const cstring IR::Annotation::disableOptimizationAnnotation = "disable_optimization"_cs; + +namespace Annotations { +void addIfNew(Vector &annotations, cstring name, const Expression *expr, + bool structured) { + if (get(annotations, name) != nullptr) return; + + annotations.emplace_back(name, expr, structured); +} + +void addIfNew(Vector &annotations, const IR::Annotation *ann) { + if (get(annotations, ann->name) != nullptr) return; + + annotations.push_back(ann); +} + +void addOrReplace(Vector &annotations, cstring name, const Expression *expr, + bool structured) { + remove_if(annotations, [name](const Annotation *a) -> bool { return a->name == name; }); + annotations.emplace_back(name, expr, structured); +} + +void addOrReplace(Vector &annotations, const IR::Annotation *ann) { + remove_if(annotations, [ann](const Annotation *a) -> bool { return a->name == ann->name; }); + annotations.push_back(ann); +} + +Vector addNameAnnotation(cstring name, const Vector &annos) { + auto result = annos; + Annotations::addIfNew(result, IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); + return result; +} + +Vector setNameAnnotation(cstring name, const Vector &annos) { + auto result = annos; + Annotations::addOrReplace(result, IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); + return result; +} + +Vector withoutNameAnnotation(const Vector &annos) { + return annos.where( + [](const IR::Annotation *a) { return a->name != IR::Annotation::nameAnnotation; }); +} +} // namespace Annotations + +} // namespace P4::IR diff --git a/ir/annotations.h b/ir/annotations.h new file mode 100644 index 00000000000..5a78d2a2dc2 --- /dev/null +++ b/ir/annotations.h @@ -0,0 +1,41 @@ +/* +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef IR_ANNOTATIONS_H_ +#define IR_ANNOTATIONS_H_ + +#include "ir/vector.h" +#include "lib/cstring.h" + +namespace P4::IR { +class Expression; + +namespace Annotations { +/// Add @name annotation if there is no annotation already set +[[nodiscard]] Vector addNameAnnotation(cstring name, const Vector &annos); +/// Replaces @name annotation, if any. Otherwise - add the name annotation +[[nodiscard]] Vector setNameAnnotation(cstring name, const Vector &annos); +[[nodiscard]] Vector withoutNameAnnotation(const Vector &annos); + +void addIfNew(Vector &annotations, cstring name, const Expression *expr, + bool structured = false); +void addIfNew(Vector &annotations, const IR::Annotation *ann); +void addOrReplace(Vector &annotations, cstring name, const Expression *expr, + bool structured = false); +void addOrReplace(Vector &annotations, const IR::Annotation *ann); +} // namespace Annotations + +} // namespace P4::IR + +#endif // IR_ANNOTATIONS_H_ diff --git a/ir/base.cpp b/ir/base.cpp index 69d45f32ee5..26c1aec4b5a 100644 --- a/ir/base.cpp +++ b/ir/base.cpp @@ -48,11 +48,12 @@ cstring Annotation::getSingleString() const { } cstring IDeclaration::externalName(cstring replace /* = cstring() */) const { - if (!is()) return getName().toString(); + if (const auto *annotated = to()) { + if (const auto *anno = annotated->getAnnotation(IR::Annotation::nameAnnotation)) + return anno->getName(); + if (replace) return replace; + } - auto anno = getAnnotation(IR::Annotation::nameAnnotation); - if (anno != nullptr) return anno->getName(); - if (replace) return replace; return getName().toString(); } diff --git a/ir/base.def b/ir/base.def index 3a90915dec8..fd31ef28035 100644 --- a/ir/base.def +++ b/ir/base.def @@ -15,6 +15,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "frontends/common/constantParsing.h" +#include "ir/annotations.h" /// a value that can be evaluated at compile-time interface CompileTimeValue { @@ -67,7 +68,7 @@ interface INamespace { /// Does not allow two declarations with the same name interface ISimpleNamespace : INamespace { virtual IDeclaration getDeclByName(cstring name) const = 0; - virtual IDeclaration getDeclByName(std::string_view name) const = 0; + virtual IDeclaration getDeclByName(std::string_view name) const = 0; } /// A general namespace can have multiple declarations with the same name @@ -236,11 +237,16 @@ class Annotation { Annotation(Util::SourceInfo si, ID n, std::initializer_list a, bool structured = false) : Node(si), name(n), expr(a), needsParsing(false), structured(structured) {} + Annotation(Util::SourceInfo si, ID n, + const Expression *a, bool structured = false) + : Node(si), name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(Util::SourceInfo si, ID n, const IR::Vector &a, bool structured = false) : Node(si), name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(Util::SourceInfo si, ID n, const IndexedVector &kv, bool structured = false) : Node(si), name(n), kv(kv), needsParsing(false), structured(structured) {} + Annotation(ID n, const Expression *a, bool structured = false) + : name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(ID n, std::initializer_list a, bool structured = false) : name(n), expr(a), needsParsing(false), structured(structured) {} Annotation(ID n, const IR::Vector &a, bool structured = false) @@ -263,6 +269,7 @@ class Annotation { static const cstring atomicAnnotation; /// Code should be executed atomically. static const cstring hiddenAnnotation; /// Object should not be exposed to the control-plane. static const cstring lengthAnnotation; /// P4-14 annotation for varbit fields. + static const cstring maxLengthAnnotation; /// P4-14 annotation for varbit fields. static const cstring optionalAnnotation; /// Optional parameter annotation static const cstring pkginfoAnnotation; /// Package documentation annotation. static const cstring deprecatedAnnotation; /// Deprecation annotation. @@ -273,6 +280,7 @@ class Annotation { static const cstring matchAnnotation; /// Match annotation (for value sets). static const cstring fieldListAnnotation; /// Used for recirculate, etc. static const cstring debugLoggingAnnotation; /// Used by compiler implementer to limit debug log to the annotated IR context. + static const cstring disableOptimizationAnnotation; /// annotation to disable certain optimization toString{ return absl::StrCat("@", name); } validate{ BUG_CHECK(!name.name.isNullOrEmpty(), "empty annotation name"); @@ -327,63 +335,58 @@ class Annotation { #end } -/// There can be several annotations with the same "name", so this is a vector. -// FIXME -- get rid of this class -- classes with annotations should have an -// inline Vector instead (remove useless indirection) -class Annotations { - optional inline Vector annotations; - Annotations { if (!srcInfo && !annotations.empty()) srcInfo = annotations[0]->srcInfo; } - static Annotations *empty; // FIXME -- should be const - size_t size() const { return annotations.size(); } - // Get the annotation with the specified name or nullptr. - // There should be at most one annotation with this name. - Annotation getSingle(cstring name) const { return get(annotations, name); } - Annotations add(Annotation annot) { - if (annot->srcInfo) srcInfo += annot->srcInfo; +/// Implemented by all objects that can have annotations +// FIXME: Use CRTP to get access to the fields directly +interface IAnnotated { + virtual const Vector &getAnnotations() const = 0; + virtual Vector &getAnnotations() = 0; + + inline Annotation getAnnotation(cstring name) const { + const auto &annotations = getAnnotations(); + return get(annotations, name); + } + /// Checks if there is annotation @name + inline bool hasAnnotation(cstring name) const { + const auto &annotations = getAnnotations(); + return get(annotations, name) != nullptr; + } + /// Checks if there is annotation @name and it is the only annotation on the + /// node + inline bool hasOnlyAnnotation(cstring name) const { + const auto &annotations = getAnnotations(); + return annotations.size() == 1 && get(annotations, name) != nullptr; + } + /// Check if there are any annotations + inline bool hasAnnotations() const { + const auto &annotations = getAnnotations(); + return !annotations.empty(); + } + inline void addAnnotation(Annotation annot) { + auto &annotations = getAnnotations(); annotations.push_back(annot); - return this; } - Annotations add(Annotation annot) const { return clone()->add(annot); } - Annotations addAnnotation(cstring name, Expression expr, bool structured = false) { - return add(new Annotation(name, Vector(expr), structured)); } - Annotations addAnnotation(cstring name, Expression expr, bool structured = false) const { - return add(new Annotation(name, Vector(expr), structured)); } - // Add annotation if another annotation with the same name is not - // already present. - Annotations addAnnotationIfNew(cstring name, Expression expr, bool structured = false) const { - return getSingle(name) ? this : addAnnotation(name, expr, structured); } - Annotations append(Annotations other) { - if (other == nullptr) - return this; - for (auto a : other->annotations) - add(a); - return this; } - // If annotations with the same name are already present, remove them. - // Add this annotation. - Annotations addOrReplace(cstring name, Expression expr, bool structured = false) const { - auto rv = clone(); - remove_if(rv->annotations, [name](const Annotation *a)->bool { return a->name == name; }); - rv->annotations.push_back(new Annotation(name, Vector(expr), structured)); - return rv; } -#emit - typedef std::function Filter; -#end - Annotations where(Filter func) const { - auto rv = empty->clone(); - std::copy_if(annotations.begin(), annotations.end(), - std::back_insert_iterator>(rv->annotations), func); - if (rv->annotations.size() == annotations.size()) return this; - return rv; } - validate{ annotations.check_null(); } - dbprint { for (auto a : annotations) out << a << ' '; } -} + inline void addAnnotation(cstring name, Expression expr, bool structured = false) { + addAnnotation(new Annotation(name, { expr }, structured)); + } -/// Implemented by all objects that can have annotations -interface IAnnotated { - virtual Annotations getAnnotations() const = 0; - Annotation getAnnotation(cstring name) const override { - auto annotations = getAnnotations(); - return annotations ? annotations->getSingle(name) : nullptr; + /// Add annotation if another annotation with the same name is not + /// already present. + inline void addAnnotationIfNew(cstring name, Expression expr, bool structured = false) { + Annotations::addIfNew(getAnnotations(), name, expr, structured); + } + + inline void addAnnotationIfNew(Annotation ann) { + Annotations::addIfNew(getAnnotations(), ann); + } + + /// If annotations with the same name are already present, remove them; + /// add this annotation. + inline void addOrReplaceAnnotation(cstring name, Expression expr, bool structured = false) { + Annotations::addOrReplace(getAnnotations(), name, expr, structured); + } + + inline void addOrReplaceAnnotation(Annotation ann) { + Annotations::addOrReplace(getAnnotations(), ann); } } diff --git a/ir/ir.cpp b/ir/ir.cpp index e146075414d..3cca7805ec0 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -213,8 +213,8 @@ void BlockStatement::append(const StatOrDecl *stmt) { srcInfo += stmt->srcInfo; if (auto bs = stmt->to()) { bool merge = true; - for (auto annot : bs->annotations->annotations) { - auto a = annotations->getSingle(annot->name); + for (const auto *annot : bs->getAnnotations()) { + auto a = getAnnotation(annot->name); if (!a || !a->equiv(*annot)) { merge = false; break; diff --git a/ir/ir.def b/ir/ir.def index bdcc01432fc..ec0e2b39a39 100644 --- a/ir/ir.def +++ b/ir/ir.def @@ -55,12 +55,13 @@ */ class ParserState : ISimpleNamespace, Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; optional inline IndexedVector components; // selectExpression can be a SelectExpression, or a PathExpression representing a state NullOK Expression selectExpression; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Util::Enumerator* getDeclarations() const override { return components.getDeclarations(); } const IDeclaration* getDeclByName(cstring name) const override { @@ -88,7 +89,8 @@ class P4Parser : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, I optional inline IndexedVector parserLocals; optional inline IndexedVector states; - Annotations getAnnotations() const override { return type->getAnnotations(); } + const Vector &getAnnotations() const override { return type->getAnnotations(); } + Vector &getAnnotations() override { BUG("cannot modify annotations"); return *new Vector(); } TypeParameters getTypeParameters() const override { return type->getTypeParameters(); } std::vector getNestedNamespaces() const override { return { type->typeParameters, type->applyParams, constructorParams }; } @@ -128,7 +130,8 @@ class P4Control : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, optional inline IndexedVector controlLocals; BlockStatement body; - Annotations getAnnotations() const override { return type->getAnnotations(); } + const Vector &getAnnotations() const override { return type->getAnnotations(); } + Vector &getAnnotations() override { BUG("cannot modify annotations"); return *new Vector(); } TypeParameters getTypeParameters() const override { return type->getTypeParameters(); } std::vector getNestedNamespaces() const override { return { type->typeParameters, type->applyParams, constructorParams }; } @@ -154,7 +157,7 @@ class P4Control : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, /// A P4-16 action class P4Action : Declaration, ISimpleNamespace, IAnnotated, IFunctional { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; ParameterList parameters; BlockStatement body; Util::Enumerator* getDeclarations() const override { @@ -163,7 +166,8 @@ class P4Action : Declaration, ISimpleNamespace, IAnnotated, IFunctional { return parameters->getDeclByName(name); } IDeclaration getDeclByName(std::string_view name) const override { return parameters->getDeclByName(name); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } ParameterList getParameters() const override { return parameters; } } @@ -207,12 +211,13 @@ class ExpressionListValue : PropertyValue { // An element in a table actions list class ActionListElement : IAnnotated, IDeclaration { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Expression expression; // This can be a PathExpression or a MethodCallExpression dbprint { out << annotations << expression; } ID getName() const override { return getPath()->name; } Path getPath() const; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } validate { BUG_CHECK(expression->is() || expression->is(), @@ -232,11 +237,12 @@ class ActionList : PropertyValue { } class KeyElement : IAnnotated { - optional Annotations annotations = Annotations::empty; Expression expression; PathExpression matchType; + optional inline Vector annotations; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } const IR::Node *transform_visit(Transform &v) { // call this from Transform::preorder(KeyElement) if the transform might split // the expression into a Vector @@ -267,7 +273,7 @@ class Key : PropertyValue { /// Pre-defined entry in a table class Entry : IAnnotated { /// annotations are optional (supported annotations: @priority(value)) - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; bool isConst; /// optional const annotation NullOK Expression priority; /// optional entry priority ListExpression keys; /// must be a tuple expression @@ -275,7 +281,8 @@ class Entry : IAnnotated { /// The action must be defined in action list bool singleton; /// True if the entry is not a list. - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } ListExpression getKeys() const { return keys; } Expression getAction() const { return action; } dbprint { out << annotations << keys << action; } @@ -289,10 +296,11 @@ class EntriesList : PropertyValue { } class Property : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; PropertyValue value; bool isConstant; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } dbprint { out << annotations << (isConstant ? "const " : "") << name << " = " << value; } } @@ -321,10 +329,11 @@ class TableProperties : ISimpleNamespace { } class P4Table : Declaration, IAnnotated, IApply { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; TableProperties properties; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Type_Method getApplyMethodType() const override; ParameterList getApplyParameters() const override { return new ParameterList(); } ActionList getActionList() const { @@ -381,29 +390,32 @@ class P4Table : Declaration, IAnnotated, IApply { } class P4ValueSet : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type elementType; Expression size; // number of elements in set. - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } class Declaration_Variable : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; optional NullOK Expression initializer = nullptr; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } dbprint { out << annotations << type << ' ' << name; if (initializer) out << " = " << *initializer; } } class Declaration_Constant : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; Expression initializer; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } toString { return Declaration::toString(); } dbprint { out << annotations << type << ' ' << name << " = " << *initializer; } } @@ -413,14 +425,15 @@ class Declaration_Constant : Declaration, IAnnotated { /// Initializers are an experimental features, used for externs with /// abstract methods. class Declaration_Instance : Declaration, IAnnotated, IInstance { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; // Either Type_Name or Type_Specialized or Type_Extern Vector arguments; inline NameMap properties = {}; // P4_14 externs only, at the moment optional NullOK BlockStatement initializer = nullptr; // experimental only; contains just declarations, no code - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Type getType() const override { return type; } ID Name() const override { return name; } validate{ arguments->check_null(); } @@ -489,7 +502,7 @@ class ContinueStatement : Statement { } class BlockStatement : Statement, ISimpleNamespace, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; optional inline IndexedVector components; IDeclaration getDeclByName(cstring name) const override { return components.getDeclaration(name); } @@ -498,7 +511,8 @@ class BlockStatement : Statement, ISimpleNamespace, IAnnotated { Util::Enumerator* getDeclarations() const override { return components.getDeclarations(); } void push_back(StatOrDecl st) { components.push_back(st); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } bool empty() const { return components.empty(); } void append(StatOrDecl stmt); BlockStatement(std::initializer_list il) { for (auto el : il) append(el); } @@ -540,8 +554,9 @@ class SwitchStatement : Statement { /* abstract base class for all loops */ abstract LoopStatement : Statement, ISimpleNamespace, IAnnotated { - optional Annotations annotations = Annotations::empty; - Annotations getAnnotations() const override { return annotations; } + optional inline Vector annotations; + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } class ForStatement : LoopStatement { @@ -571,8 +586,8 @@ class ForInStatement : LoopStatement { Expression collection; Statement body; ForInStatement { ref = new PathExpression(decl->name); } - ForInStatement(Util::SourceInfo si, Annotations a, PathExpression pe, Expression c, Statement b) - : LoopStatement(si, a), decl(nullptr), ref(pe), collection(c), body(b) {} + ForInStatement(Util::SourceInfo si, Vector a, PathExpression pe, Expression c, Statement b) + : LoopStatement(si, *a), decl(nullptr), ref(pe), collection(c), body(b) {} IDeclaration getDeclByName(cstring name) const override { return decl && decl->name == name ? decl : nullptr; } IDeclaration getDeclByName(std::string_view name) const override { @@ -590,7 +605,7 @@ class ForInStatement : LoopStatement { ///////////////////////////////////////////////////////////// class Function : Declaration, IFunctional, IAnnotated, ISimpleNamespace, INestedNamespace { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type_Method type; BlockStatement body; ParameterList getParameters() const override { @@ -604,7 +619,8 @@ class Function : Declaration, IFunctional, IAnnotated, ISimpleNamespace, INested return type->parameters->getDeclByName(name); } std::vector getNestedNamespaces() const override { return { type->typeParameters }; } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } ///////////////////////////////////////////////////////////// diff --git a/ir/node.h b/ir/node.h index 2eec43aad4f..53e5eab1b10 100644 --- a/ir/node.h +++ b/ir/node.h @@ -71,7 +71,6 @@ class INode : public Util::IHasSourceInfo, public IHasDbPrint, public ICastable virtual void toJSON(JSONGenerator &) const = 0; virtual cstring node_type_name() const = 0; virtual void validate() const {} - virtual const Annotation *getAnnotation(cstring) const { return nullptr; } // default checkedTo implementation for nodes: just fallback to generic ICastable method template diff --git a/ir/type.cpp b/ir/type.cpp index a75cdf49607..cf5b80bcb2f 100644 --- a/ir/type.cpp +++ b/ir/type.cpp @@ -50,29 +50,10 @@ const IR::ID IR::Type_Table::hit = ID("hit"); const IR::ID IR::Type_Table::miss = ID("miss"); const IR::ID IR::Type_Table::action_run = ID("action_run"); -const cstring IR::Annotation::nameAnnotation = "name"_cs; -const cstring IR::Annotation::tableOnlyAnnotation = "tableonly"_cs; -const cstring IR::Annotation::defaultOnlyAnnotation = "defaultonly"_cs; -const cstring IR::Annotation::atomicAnnotation = "atomic"_cs; -const cstring IR::Annotation::hiddenAnnotation = "hidden"_cs; -const cstring IR::Annotation::lengthAnnotation = "length"_cs; -const cstring IR::Annotation::optionalAnnotation = "optional"_cs; -const cstring IR::Annotation::pkginfoAnnotation = "pkginfo"_cs; -const cstring IR::Annotation::deprecatedAnnotation = "deprecated"_cs; -const cstring IR::Annotation::synchronousAnnotation = "synchronous"_cs; -const cstring IR::Annotation::pureAnnotation = "pure"_cs; -const cstring IR::Annotation::noSideEffectsAnnotation = "noSideEffects"_cs; -const cstring IR::Annotation::noWarnAnnotation = "noWarn"_cs; -const cstring IR::Annotation::matchAnnotation = "match"_cs; -const cstring IR::Annotation::fieldListAnnotation = "field_list"_cs; -const cstring IR::Annotation::debugLoggingAnnotation = "__debug"_cs; - long Type_Declaration::nextId = 0; long Type_InfInt::nextId = 0; long Type_Any::nextId = 0; -Annotations *Annotations::empty = new Annotations(Vector()); - const Type *Type_Stack::at(size_t) const { return elementType; } const Type_Bits *Type_Bits::get(int width, bool isSigned) { diff --git a/ir/type.def b/ir/type.def index 6f84595e3cd..bcfaef721a6 100644 --- a/ir/type.def +++ b/ir/type.def @@ -220,11 +220,12 @@ class Type_Varbits : Type_Base { } class Parameter : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Direction direction; Type type; optional NullOK Expression defaultValue; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } bool hasOut() const { return direction == IR::Direction::Out || direction == IR::Direction::InOut; } bool isOptional() const { @@ -386,18 +387,20 @@ class TypeParameters : ISimpleNamespace { } class StructField : Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } } abstract Type_StructLike : Type_Declaration, INestedNamespace, ISimpleNamespace, IAnnotated, IMayBeGenericType { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; optional TypeParameters typeParameters = new TypeParameters(); optional inline IndexedVector fields; TypeParameters getTypeParameters() const override { return typeParameters; } std::vector getNestedNamespaces() const override { return { typeParameters }; } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Util::Enumerator* getDeclarations() const override { return fields.getDeclarations(); } StructField getField(cstring name) const { @@ -556,9 +559,10 @@ class Type_P4List : Type { /// The type of an architectural block. /// Abstract base for Type_Control, Type_Parser and Type_Package abstract Type_ArchBlock : Type_Declaration, IMayBeGenericType, IAnnotated, ISimpleNamespace { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; optional TypeParameters typeParameters = new TypeParameters; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } TypeParameters getTypeParameters() const override { return typeParameters; } Util::Enumerator* getDeclarations() const override { return typeParameters->getDeclarations(); } @@ -704,9 +708,10 @@ class Type_String : Type_Base { } class Type_Enum : Type_Declaration, ISimpleNamespace, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; inline IndexedVector members; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Util::Enumerator* getDeclarations() const override { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { @@ -726,10 +731,11 @@ class SerEnumMember : Declaration, CompileTimeValue { /** A serializable enumeration with a backing type */ class Type_SerEnum : Type_Declaration, ISimpleNamespace, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; inline IndexedVector members; - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } Util::Enumerator* getDeclarations() const override { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { @@ -829,11 +835,12 @@ class Type_Action : Type_MethodBase { class Method : Declaration, IAnnotated, IFunctional, ISimpleNamespace { Type_Method type; optional bool isAbstract = false; - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; size_t maxParameterCount() const { return type->maxParameterCount(); } size_t minParameterCount() const { return type->minParameterCount(); } void setAbstract() { isAbstract = true; } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } ParameterList getParameters() const override { return type->parameters; } // annotations can refer to parameters, so need to look them up in scope IDeclaration getDeclByName(cstring name) const override { @@ -845,10 +852,11 @@ class Method : Declaration, IAnnotated, IFunctional, ISimpleNamespace { } class Type_Typedef : Type_Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; int width_bits() const override { return type->width_bits(); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } #nodbprint } @@ -858,10 +866,11 @@ class Type_Typedef : Type_Declaration, IAnnotated { /// assignment, equality, and casts to/from the original type. /// The keyword for newtype is actually `type'. class Type_Newtype : Type_Declaration, IAnnotated { - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; Type type; int width_bits() const override { return type->width_bits(); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } #nodbprint } @@ -871,15 +880,16 @@ class Type_Extern : Type_Declaration, INestedNamespace, IGeneralNamespace, optional TypeParameters typeParameters = new TypeParameters; optional inline Vector methods; // methods can be overloaded, so this is not NameMap optional inline NameMap attributes; // P4_14 only, currently - optional Annotations annotations = Annotations::empty; + optional inline Vector annotations; std::vector getNestedNamespaces() const override { return { typeParameters }; } Util::Enumerator* getDeclarations() const override { return attributes.valueEnumerator()->as() ->concat(methods.getEnumerator()->as()); } - virtual TypeParameters getTypeParameters() const override { return typeParameters; } + TypeParameters getTypeParameters() const override { return typeParameters; } validate{ methods.check_null(); } - Annotations getAnnotations() const override { return annotations; } + const Vector &getAnnotations() const override { return annotations; } + Vector &getAnnotations() override { return annotations; } /// Returns the method that matches the specified arguments. /// Returns nullptr if no method or more than one method match. /// In the latter case it also reports an error. diff --git a/ir/vector.h b/ir/vector.h index beb0f53d4a7..6e680413d8f 100644 --- a/ir/vector.h +++ b/ir/vector.h @@ -70,6 +70,10 @@ class Vector : public VectorBase { explicit Vector(const T *a) { vec.emplace_back(std::move(a)); } explicit Vector(const safe_vector &a) { vec.insert(vec.end(), a.begin(), a.end()); } Vector(std::initializer_list a) : vec(a) {} + template + Vector(InputIt first, InputIt last) : vec(first, last) {} + Vector(Util::Enumerator *e) // NOLINT(runtime/explicit) + : vec(e->begin(), e->end()) {} static Vector *fromJSON(JSONLoader &json); typedef typename safe_vector::iterator iterator; typedef typename safe_vector::const_iterator const_iterator; @@ -208,6 +212,10 @@ class Vector : public VectorBase { return getEnumerator()->template as()->where( [](const T *d) { return d != nullptr; }); } + template + auto where(Filter f) const { + return getEnumerator()->where(std::move(f)); + } void dbprint(std::ostream &out) const override { out << "{" << IndentCtl::indent; diff --git a/ir/visitor.cpp b/ir/visitor.cpp index d96b5ffac58..4224c25c176 100644 --- a/ir/visitor.cpp +++ b/ir/visitor.cpp @@ -335,12 +335,12 @@ bool Visitor::warning_enabled(const Visitor *visitor, int warning_kind) { while (visitor != nullptr) { auto crt = visitor->ctxt; while (crt != nullptr) { - if (auto annotated = crt->node->to()) { - for (auto a : annotated->getAnnotations()->annotations) { - if (a->name.name == IR::Annotation::noWarnAnnotation) { - auto arg = a->getSingleString(); - if (arg == errorString) return false; - } + if (const auto *annotated = crt->node->to()) { + for (const auto *a : annotated->getAnnotations()) { + if (a->name != IR::Annotation::noWarnAnnotation) continue; + + auto arg = a->getSingleString(); + if (arg == errorString) return false; } } crt = crt->parent; @@ -439,8 +439,10 @@ struct PushContext { bool saved_logging_disable; PushContext(const Visitor::Context *&stck, const IR::Node *node) : stack(stck) { saved_logging_disable = Log::Detail::enableLoggingInContext; - if (node->getAnnotation(IR::Annotation::debugLoggingAnnotation)) - Log::Detail::enableLoggingInContext = true; + if (const auto *annotated = node->to()) { + if (annotated->getAnnotation(IR::Annotation::debugLoggingAnnotation)) + Log::Detail::enableLoggingInContext = true; + } current.parent = stack; current.node = current.original = node; current.child_index = 0; diff --git a/midend/actionSynthesis.cpp b/midend/actionSynthesis.cpp index 1138988ccf2..bad1a658c41 100644 --- a/midend/actionSynthesis.cpp +++ b/midend/actionSynthesis.cpp @@ -70,9 +70,8 @@ const IR::Node *DoMoveActionsToTables::postorder(IR::MethodCallStatement *statem // Synthesize a new table cstring tblName = IR::ID(refMap->newName("tbl_"_cs + ac->action->name.name), nullptr); - auto annos = new IR::Annotations(); - annos->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); - auto tbl = new IR::P4Table(statement->srcInfo, tblName, annos, props); + auto tbl = new IR::P4Table(statement->srcInfo, tblName, + {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}, props); tables.push_back(tbl); // Table invocation statement @@ -196,9 +195,9 @@ const IR::Statement *DoSynthesizeActions::createAction(const IR::Statement *toAd } LOG3("Adding new action " << name << body); - auto annos = new IR::Annotations(); - annos->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); - auto action = new IR::P4Action(toAdd->srcInfo, name, annos, new IR::ParameterList(), body); + auto action = new IR::P4Action(toAdd->srcInfo, name, + {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}, + new IR::ParameterList(), body); actions.push_back(action); auto actpath = new IR::PathExpression(name); auto repl = new IR::MethodCallExpression(toAdd->srcInfo, actpath); diff --git a/midend/def_use.h b/midend/def_use.h index 9230c341fb9..c58416c1630 100644 --- a/midend/def_use.h +++ b/midend/def_use.h @@ -167,7 +167,7 @@ class ComputeDefUse : public Inspector, void loop_revisit(const IR::ParserState *) override; void postorder(const IR::ParserState *) override; bool preorder(const IR::Type *) override { return false; } - bool preorder(const IR::Annotations *) override { return false; } + bool preorder(const IR::Vector *) override { return false; } bool preorder(const IR::KeyElement *) override; bool preorder(const IR::AssignmentStatement *) override; const IR::Expression *do_read(def_info_t &, const IR::Expression *, const Context *); diff --git a/midend/eliminateSwitch.cpp b/midend/eliminateSwitch.cpp index 10f29e52d82..675b1905c5e 100644 --- a/midend/eliminateSwitch.cpp +++ b/midend/eliminateSwitch.cpp @@ -61,9 +61,6 @@ const IR::Node *DoEliminateSwitch::postorder(IR::SwitchStatement *statement) { new IR::AssignmentStatement(src, new IR::PathExpression(key), statement->expression); contents.push_back(assign); - auto hidden = new IR::Annotations(); - hidden->add(new IR::Annotation(IR::Annotation::hiddenAnnotation, {})); - auto tableKeyEl = new IR::KeyElement(src, new IR::PathExpression(key), new IR::PathExpression(P4CoreLibrary::instance().exactMatch.Id())); @@ -94,8 +91,9 @@ const IR::Node *DoEliminateSwitch::postorder(IR::SwitchStatement *statement) { pendingLabels.push_back(sc->label); if (sc->statement != nullptr) { cstring actionName = nameGen.newName(prefix + "_case"); - auto action = new IR::P4Action(src, actionName, hidden, new IR::ParameterList(), - new IR::BlockStatement()); + auto action = new IR::P4Action( + src, actionName, {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}, + new IR::ParameterList(), new IR::BlockStatement()); auto actionCall = new IR::MethodCallExpression(scSrc, new IR::PathExpression(actionName)); toInsert.push_back(action); @@ -127,7 +125,9 @@ const IR::Node *DoEliminateSwitch::postorder(IR::SwitchStatement *statement) { true)); properties.push_back(new IR::Property(src, "entries", new IR::EntriesList(entries), true)); cstring tableName = nameGen.newName(prefix + "_table"); - auto table = new IR::P4Table(src, tableName, hidden, new IR::TableProperties(properties)); + auto table = + new IR::P4Table(src, tableName, {new IR::Annotation(IR::Annotation::hiddenAnnotation, {})}, + new IR::TableProperties(properties)); toInsert.push_back(table); auto apply = new IR::Member( diff --git a/midend/flattenInterfaceStructs.h b/midend/flattenInterfaceStructs.h index f7021d42308..f5ed49cc819 100644 --- a/midend/flattenInterfaceStructs.h +++ b/midend/flattenInterfaceStructs.h @@ -19,6 +19,7 @@ limitations under the License. #include "frontends/common/resolveReferences/resolveReferences.h" #include "frontends/p4/typeChecking/typeChecker.h" +#include "ir/annotations.h" #include "ir/ir.h" #include "lib/cstring.h" @@ -72,10 +73,10 @@ struct StructTypeReplacement : public IHasDbPrint { flatten(typeMap, cstring::empty, type, type->annotations, vec, policy); if (type->is()) { replacementType = - new IR::Type_Struct(type->srcInfo, type->name, IR::Annotations::empty, *vec); + new IR::Type_Struct(type->srcInfo, type->name, IR::Vector(), *vec); } else if (type->is()) { replacementType = - new IR::Type_Header(type->srcInfo, type->name, IR::Annotations::empty, *vec); + new IR::Type_Header(type->srcInfo, type->name, IR::Vector(), *vec); } else { BUG("Unexpected type %1%", type); } @@ -104,30 +105,29 @@ struct StructTypeReplacement : public IHasDbPrint { // Helper for constructor void flatten(const P4::TypeMap *typeMap, cstring prefix, const IR::Type *type, - const IR::Annotations *annotations, IR::IndexedVector *fields, - AnnotationSelectionPolicy *policy) { + const IR::Vector &annotations, + IR::IndexedVector *fields, AnnotationSelectionPolicy *policy) { // Drop name annotations - annotations = annotations->where( - [](const IR::Annotation *a) { return a->name != IR::Annotation::nameAnnotation; }); + auto ann = IR::Annotations::withoutNameAnnotation(annotations); if (auto st = type->to()) { - auto sannotations = st->annotations->where([policy](const IR::Annotation *annot) { - if (!policy) return false; - return policy->keep(annot); - }); + IR::Vector sann = + st->annotations.where([policy](const IR::Annotation *annot) { + if (!policy) return false; + return policy->keep(annot); + }); structFieldMap.emplace(prefix, st); for (auto f : st->fields) { - auto na = new IR::Annotations(); - na->append(sannotations); - na->append(annotations); - na->append(f->annotations); + IR::Vector fann(sann); + fann.append(ann); + fann.append(f->annotations); auto ft = typeMap->getType(f, true); - flatten(typeMap, prefix + "." + f->name, ft, na, fields, policy); + flatten(typeMap, prefix + "." + f->name, ft, fann, fields, policy); } return; } cstring fieldName = prefix.replace('.', '_') + std::to_string(fieldNameRemap.size()); fieldNameRemap.emplace(prefix, fieldName); - fields->push_back(new IR::StructField(IR::ID(fieldName), annotations, type->getP4Type())); + fields->push_back(new IR::StructField(IR::ID(fieldName), ann, type->getP4Type())); LOG3("Flatten: " << type << " | " << prefix); } diff --git a/midend/has_side_effects.h b/midend/has_side_effects.h index 20f61858618..93c592cd347 100644 --- a/midend/has_side_effects.h +++ b/midend/has_side_effects.h @@ -40,10 +40,9 @@ class hasSideEffects : public Inspector, public ResolutionContext { if (typeMap) { auto *mi = P4::MethodInstance::resolve(mc, this, typeMap, true); if (auto *bm = mi->to()) { - if (bm->name == "isValid") return true; - } - if (auto *em = mi->to()) { - if (em->method->getAnnotation(IR::Annotation::noSideEffectsAnnotation)) return true; + if (bm->name == IR::Type_Header::isValid) return true; + } else if (auto *em = mi->to()) { + if (em->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation)) return true; } } result = true; diff --git a/midend/local_copyprop.cpp b/midend/local_copyprop.cpp index dd8191736b3..ea163461c49 100644 --- a/midend/local_copyprop.cpp +++ b/midend/local_copyprop.cpp @@ -165,7 +165,7 @@ class DoLocalCopyPropagation::RewriteTableKeys : public Transform { if (!table) return exp; if (auto name = expr_name(exp)) { const Visitor::Context *ctxt = nullptr; - if (findContext(ctxt) && ctxt->child_index == 1) { + if (findContext(ctxt) && ctxt->child_index == 0) { if (table->key_remap.count(name)) { LOG4(" rewriting key " << name << " : " << table->key_remap.at(name)); return table->key_remap.at(name); @@ -313,7 +313,7 @@ const IR::Expression *DoLocalCopyPropagation::copyprop_name(cstring name, if (!name) return nullptr; if (inferForTable) { const Visitor::Context *ctxt = nullptr; - if (findContext(ctxt) && ctxt->child_index == 1) + if (findContext(ctxt) && ctxt->child_index == 0) inferForTable->keyreads.insert(name); } if (!working) return nullptr; diff --git a/midend/nestedStructs.cpp b/midend/nestedStructs.cpp index 3cdd79fa43e..2755c65463e 100644 --- a/midend/nestedStructs.cpp +++ b/midend/nestedStructs.cpp @@ -47,10 +47,8 @@ const IR::Node *RemoveNestedStructs::postorder(IR::Declaration_Variable *decl) { if (!values.isNestedStruct(type)) return decl; BUG_CHECK(decl->initializer == nullptr, "%1%: did not expect an initializer", decl); - BUG_CHECK( - decl->annotations->size() == 0 || - (decl->annotations->size() == 1 && decl->annotations->getSingle("name"_cs) != nullptr), - "%1%: don't know how to handle variable annotations other than @name", decl); + BUG_CHECK(!decl->hasAnnotations() || decl->hasOnlyAnnotation(IR::Annotation::nameAnnotation), + "%1%: don't know how to handle variable annotations other than @name", decl); auto map = new ComplexValues::FieldsMap(type); values.values.emplace(getOriginal(), map); if (findContext()) { diff --git a/midend/unrollLoops.cpp b/midend/unrollLoops.cpp index 4086bae879e..e9e15b2dca1 100644 --- a/midend/unrollLoops.cpp +++ b/midend/unrollLoops.cpp @@ -299,13 +299,16 @@ const IR::Statement *UnrollLoops::preorder(IR::ForInStatement *fstmt) { UnrollLoops::Policy UnrollLoops::default_unroll(true); UnrollLoops::Policy UnrollLoops::default_nounroll(false); +static const cstring unrollAnnotation = "unroll"_cs; +static const cstring noUnrollAnnotation = "no_unroll"_cs; + bool UnrollLoops::Policy::operator()(const IR::LoopStatement *loop, bool canUnroll, const loop_bounds_t &) { - if (loop->getAnnotation("unroll"_cs)) { + if (loop->hasAnnotation(unrollAnnotation)) { if (!canUnroll) warning(ErrorType::WARN_UNSUPPORTED, "Can't unroll loop: %1%", loop); return true; } - if (loop->getAnnotation("nounroll"_cs)) return false; + if (loop->hasAnnotation(noUnrollAnnotation)) return false; return unroll_default; } diff --git a/testdata/p4_16_errors_outputs/structured-annotation-e1.p4-stderr b/testdata/p4_16_errors_outputs/structured-annotation-e1.p4-stderr index 9f8afc4ee3e..1fdb59928d3 100644 --- a/testdata/p4_16_errors_outputs/structured-annotation-e1.p4-stderr +++ b/testdata/p4_16_errors_outputs/structured-annotation-e1.p4-stderr @@ -1,6 +1,3 @@ -structured-annotation-e1.p4(1): [--Werror=duplicate] error: @dup: duplicate name for structured annotation -@dup[] -^ structured-annotation-e1.p4(2): [--Werror=duplicate] error: @dup: duplicate name for structured annotation @dup[] ^ diff --git a/testdata/p4_16_samples_outputs/pna-action-selector-1.p4.spec b/testdata/p4_16_samples_outputs/pna-action-selector-1.p4.spec index 1748c833028..36a342a5d32 100644 --- a/testdata/p4_16_samples_outputs/pna-action-selector-1.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-action-selector-1.p4.spec @@ -98,7 +98,7 @@ table as { actions { a1 a2 - set_exception + set_exception @defaultonly } default_action set_exception args vport 0x0 size 0x10000 diff --git a/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss0.p4.spec b/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss0.p4.spec index 94eb8f7dfc0..fac526ed778 100644 --- a/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss0.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss0.p4.spec @@ -99,7 +99,7 @@ table ipv4_host { actions { send drop - NoAction + NoAction @defaultonly } default_action drop args none const size 0x10000 diff --git a/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss1.p4.spec b/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss1.p4.spec index ce39829c7a2..bb34a321150 100644 --- a/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss1.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-dpdk-add_on_miss1.p4.spec @@ -127,7 +127,7 @@ table ipv4_host { actions { send drop - NoAction + NoAction @defaultonly } default_action drop args none const size 0x10000 diff --git a/testdata/p4_16_samples_outputs/pna-dpdk-header-stack-assignment.p4.spec b/testdata/p4_16_samples_outputs/pna-dpdk-header-stack-assignment.p4.spec index 449503293e4..6d6365f9967 100644 --- a/testdata/p4_16_samples_outputs/pna-dpdk-header-stack-assignment.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-dpdk-header-stack-assignment.p4.spec @@ -173,8 +173,8 @@ table header_mod { h.mac.da exact } actions { - encap_one_tunnel_layer_ipv4 - decap_one_tunnel_layer_just_before_eth + encap_one_tunnel_layer_ipv4 @tableonly + decap_one_tunnel_layer_just_before_eth @tableonly NoAction } default_action NoAction args none const diff --git a/testdata/p4_16_samples_outputs/pna-example-tunnel.p4.spec b/testdata/p4_16_samples_outputs/pna-example-tunnel.p4.spec index 964f5909cf8..5692de2709e 100644 --- a/testdata/p4_16_samples_outputs/pna-example-tunnel.p4.spec +++ b/testdata/p4_16_samples_outputs/pna-example-tunnel.p4.spec @@ -71,7 +71,7 @@ table tunnel_decap_ipv4_tunnel_term_table { } actions { tunnel_decap_decap_outer_ipv4_0 - NoAction + NoAction @defaultonly } default_action NoAction args none const size 0x10000 @@ -84,7 +84,7 @@ table tunnel_encap_set_tunnel_encap { } actions { tunnel_encap_set_tunnel_0 - NoAction + NoAction @defaultonly } default_action NoAction args none const size 0x100 diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec index 80392bc0cb1..e8b597e4eec 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-128bitCast.p4.spec @@ -102,7 +102,7 @@ action macswp args none { table stub { actions { macswp - NoAction + NoAction @defaultonly } default_action NoAction args none size 0xF4240 diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-hdr-field-non-align.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-hdr-field-non-align.p4.spec index 75af95d7117..121cbeee424 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-hdr-field-non-align.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-hdr-field-non-align.p4.spec @@ -64,7 +64,7 @@ action macswp args none { table stub { actions { macswp - NoAction + NoAction @defaultonly } default_action NoAction args none size 0xF4240 diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-large-header-fields.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-large-header-fields.p4.spec index 640a6418cc8..d962e41cfc2 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-large-header-fields.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-large-header-fields.p4.spec @@ -75,7 +75,7 @@ table stub_0 { } actions { macswp - NoAction_1 + NoAction_1 @defaultonly } default_action NoAction_1 args none size 0xF4240 diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-large-struct-fields.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-large-struct-fields.p4.spec index 9cae7244e4c..4ee46b5cc42 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-large-struct-fields.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-large-struct-fields.p4.spec @@ -74,7 +74,7 @@ table stub_0 { } actions { macswp - NoAction_1 + NoAction_1 @defaultonly } default_action NoAction_1 args none size 0xF4240 diff --git a/testdata/p4_16_samples_outputs/psa-dpdk-struct-field.p4.spec b/testdata/p4_16_samples_outputs/psa-dpdk-struct-field.p4.spec index 3810a780281..a101319de25 100644 --- a/testdata/p4_16_samples_outputs/psa-dpdk-struct-field.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-dpdk-struct-field.p4.spec @@ -51,7 +51,7 @@ action macswp args none { table stub { actions { macswp - NoAction + NoAction @defaultonly } default_action NoAction args none size 0xF4240 diff --git a/testdata/p4_16_samples_outputs/psa-example-incremental-checksum.p4.spec b/testdata/p4_16_samples_outputs/psa-example-incremental-checksum.p4.spec index 36a8506f180..65720882124 100644 --- a/testdata/p4_16_samples_outputs/psa-example-incremental-checksum.p4.spec +++ b/testdata/p4_16_samples_outputs/psa-example-incremental-checksum.p4.spec @@ -106,7 +106,7 @@ table route { actions { forward drop_1 - NoAction + NoAction @defaultonly } default_action NoAction args none size 0x10000 From 78d5ed8bdf07bfbba73ca867b8ece39dbfdece27 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 7 Nov 2024 10:41:53 +0300 Subject: [PATCH 5/5] Address review comments Signed-off-by: Anton Korobeynikov --- backends/bmv2/common/backend.h | 2 +- control-plane/flattenHeader.cpp | 2 +- frontends/p4-14/fromv1.0/programStructure.cpp | 12 +++++++----- frontends/p4/inlining.cpp | 12 +++++++----- frontends/p4/localizeActions.cpp | 4 ++-- frontends/p4/sideEffects.h | 6 ++---- ir/annotations.cpp | 4 ++-- ir/annotations.h | 5 +++-- midend/flattenInterfaceStructs.h | 6 ++---- 9 files changed, 27 insertions(+), 26 deletions(-) diff --git a/backends/bmv2/common/backend.h b/backends/bmv2/common/backend.h index 8c3032e3925..89d93c6a92f 100644 --- a/backends/bmv2/common/backend.h +++ b/backends/bmv2/common/backend.h @@ -170,7 +170,7 @@ class RenameUserMetadata : public Transform { cstring newName = namePrefix + suffix; LOG2("Renaming " << f << " to " << newName); auto field = new IR::StructField( - f->srcInfo, f->name, IR::Annotations::setNameAnnotation(newName, f->annotations), + f->srcInfo, f->name, IR::Annotations::setNameAnnotation(f->annotations, newName), f->type); fields.push_back(field); } diff --git a/control-plane/flattenHeader.cpp b/control-plane/flattenHeader.cpp index e124835842c..b18dbc1f5c3 100644 --- a/control-plane/flattenHeader.cpp +++ b/control-plane/flattenHeader.cpp @@ -43,7 +43,7 @@ void FlattenHeader::doFlatten(const IR::Type *type) { auto originalName = makeName("."); auto annotations = mergeAnnotations(); auto field = new IR::StructField( - IR::ID(newName), IR::Annotations::setNameAnnotation(originalName, annotations), type); + IR::ID(newName), IR::Annotations::setNameAnnotation(annotations, originalName), type); newFields.push_back(field); auto ftype = typeMap->getTypeType(type, true); typeMap->setType(field, ftype); diff --git a/frontends/p4-14/fromv1.0/programStructure.cpp b/frontends/p4-14/fromv1.0/programStructure.cpp index 270f8afacdd..3be20431833 100644 --- a/frontends/p4-14/fromv1.0/programStructure.cpp +++ b/frontends/p4-14/fromv1.0/programStructure.cpp @@ -84,7 +84,7 @@ ProgramStructure::ProgramStructure() IR::Vector ProgramStructure::addGlobalNameAnnotation( cstring name, const IR::Vector &annos) { - return IR::Annotations::addNameAnnotation(absl::StrCat(".", name), annos); + return IR::Annotations::maybeAddNameAnnotation(annos, absl::StrCat(".", name)); } cstring ProgramStructure::makeUniqueName(cstring base) { @@ -175,7 +175,7 @@ cstring ProgramStructure::createType(const IR::Type_StructLike *type, bool heade auto type_name = types.get(type); auto newType = type->apply(TypeConverter(this)); if (newType->name.name != type_name) { - auto annos = IR::Annotations::addNameAnnotation(type->name.name, type->annotations); + auto annos = IR::Annotations::maybeAddNameAnnotation(type->annotations, type->name.name); if (header) { newType = new IR::Type_Header(newType->srcInfo, type_name, std::move(annos), newType->fields); @@ -239,7 +239,8 @@ void ProgramStructure::createTypes() { // Registers always use struct types auto newType = new IR::Type_Struct( type->srcInfo, type_name, - IR::Annotations::addNameAnnotation(layoutTypeName, type->annotations), st->fields); + IR::Annotations::maybeAddNameAnnotation(type->annotations, layoutTypeName), + st->fields); checkHeaderType(newType, false); LOG3("Added type " << dbp(newType) << " named " << type_name << " from " << dbp(type)); declarations->push_back(newType); @@ -277,7 +278,7 @@ const IR::Type_Struct *ProgramStructure::createFieldListType(const IR::Expressio auto name = makeUniqueName(nr->path->name.name); auto result = new IR::Type_Struct(expression->srcInfo, name, - IR::Annotations::addNameAnnotation(nr->path->name, {})); + IR::Annotations::maybeAddNameAnnotation({}, nr->path->name)); std::set fieldNames; int field_id = 0; for (auto f : fl->fields) { @@ -983,7 +984,8 @@ const IR::P4Table *ProgramStructure::convertTable(const IR::V1Table *table, cstr name = bin->right->toString(); else if (bin->right->is()) name = bin->left->toString(); - if (!name.isNullOrEmpty()) annos = IR::Annotations::addNameAnnotation(name, annos); + if (!name.isNullOrEmpty()) + annos = IR::Annotations::maybeAddNameAnnotation(annos, name); } // Here we rely on the fact that the spelling of 'rt' is // the same in P4-14 and core.p4/v1model.p4. diff --git a/frontends/p4/inlining.cpp b/frontends/p4/inlining.cpp index 5f60dde86b7..a190d0d093a 100644 --- a/frontends/p4/inlining.cpp +++ b/frontends/p4/inlining.cpp @@ -244,7 +244,7 @@ class Substitutions : public SubstituteParameters { cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << " (" << extName << ")"); return new IR::P4Table(table->srcInfo, newName, - IR::Annotations::setNameAnnotation(extName, table->annotations), + IR::Annotations::setNameAnnotation(table->annotations, extName), table->properties); } const IR::Node *postorder(IR::P4ValueSet *set) override { @@ -253,7 +253,7 @@ class Substitutions : public SubstituteParameters { cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); return new IR::P4ValueSet(set->srcInfo, newName, - IR::Annotations::setNameAnnotation(extName, set->annotations), + IR::Annotations::setNameAnnotation(set->annotations, extName), set->elementType, set->size); } const IR::Node *postorder(IR::P4Action *action) override { @@ -262,7 +262,7 @@ class Substitutions : public SubstituteParameters { cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); return new IR::P4Action(action->srcInfo, newName, - IR::Annotations::setNameAnnotation(extName, action->annotations), + IR::Annotations::setNameAnnotation(action->annotations, extName), action->parameters, action->body); } const IR::Node *postorder(IR::Declaration_Instance *instance) override { @@ -271,7 +271,8 @@ class Substitutions : public SubstituteParameters { cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); instance->name = newName; - instance->annotations = IR::Annotations::setNameAnnotation(extName, instance->annotations); + IR::Annotations::addOrReplace(instance->annotations, IR::Annotation::nameAnnotation, + new IR::StringLiteral(extName)); return instance; } const IR::Node *postorder(IR::Declaration_Variable *decl) override { @@ -280,7 +281,8 @@ class Substitutions : public SubstituteParameters { cstring extName = renameMap->getExtName(orig); LOG3("Renaming " << dbp(orig) << " to " << newName << "(" << extName << ")"); decl->name = newName; - decl->annotations = IR::Annotations::setNameAnnotation(extName, decl->annotations); + IR::Annotations::addOrReplace(decl->annotations, IR::Annotation::nameAnnotation, + new IR::StringLiteral(extName)); return decl; } const IR::Node *postorder(IR::PathExpression *expression) override { diff --git a/frontends/p4/localizeActions.cpp b/frontends/p4/localizeActions.cpp index e0e8daa7c84..86696355500 100644 --- a/frontends/p4/localizeActions.cpp +++ b/frontends/p4/localizeActions.cpp @@ -78,7 +78,7 @@ bool FindGlobalActionUses::preorder(const IR::PathExpression *path) { auto replacement = new IR::P4Action( action->srcInfo, IR::ID(action->name.srcInfo, newName, action->name.originalName), - IR::Annotations::addNameAnnotation(action->name, action->annotations), params, + IR::Annotations::maybeAddNameAnnotation(action->annotations, action->name), params, replBody); repl->addReplacement(action, control, replacement); } @@ -165,7 +165,7 @@ bool FindRepeatedActionUses::preorder(const IR::PathExpression *expression) { replacement = new IR::P4Action( action->srcInfo, IR::ID(action->name.srcInfo, newName, action->name.originalName), - IR::Annotations::addNameAnnotation(action->name, action->annotations), params, + IR::Annotations::maybeAddNameAnnotation(action->annotations, action->name), params, replBody); repl->createReplacement(action, actionUser, replacement); } diff --git a/frontends/p4/sideEffects.h b/frontends/p4/sideEffects.h index e0445016385..b9eb3940858 100644 --- a/frontends/p4/sideEffects.h +++ b/frontends/p4/sideEffects.h @@ -118,10 +118,8 @@ class SideEffects : public Inspector { // * isValid() // * function, extern function, or extern method with noSideEffects annotation auto mi = MethodInstance::resolve(mce, refMap, typeMap); - if (const auto *em = mi->to()) - return !em->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); - if (const auto *ef = mi->to()) - return !ef->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); + if (const auto *ec = mi->to()) + return !ec->method->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); if (const auto *ef = mi->to()) return !ef->function->hasAnnotation(IR::Annotation::noSideEffectsAnnotation); if (const auto *bim = mi->to()) return bim->name != IR::Type_Header::isValid; diff --git a/ir/annotations.cpp b/ir/annotations.cpp index 8aa95afa388..2401dbdba5a 100644 --- a/ir/annotations.cpp +++ b/ir/annotations.cpp @@ -64,13 +64,13 @@ void addOrReplace(Vector &annotations, const IR::Annotation *ann) { annotations.push_back(ann); } -Vector addNameAnnotation(cstring name, const Vector &annos) { +Vector maybeAddNameAnnotation(const Vector &annos, cstring name) { auto result = annos; Annotations::addIfNew(result, IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); return result; } -Vector setNameAnnotation(cstring name, const Vector &annos) { +Vector setNameAnnotation(const Vector &annos, cstring name) { auto result = annos; Annotations::addOrReplace(result, IR::Annotation::nameAnnotation, new IR::StringLiteral(name)); return result; diff --git a/ir/annotations.h b/ir/annotations.h index 5a78d2a2dc2..f491ec0ccbe 100644 --- a/ir/annotations.h +++ b/ir/annotations.h @@ -23,9 +23,10 @@ class Expression; namespace Annotations { /// Add @name annotation if there is no annotation already set -[[nodiscard]] Vector addNameAnnotation(cstring name, const Vector &annos); +[[nodiscard]] Vector maybeAddNameAnnotation(const Vector &annos, + cstring name); /// Replaces @name annotation, if any. Otherwise - add the name annotation -[[nodiscard]] Vector setNameAnnotation(cstring name, const Vector &annos); +[[nodiscard]] Vector setNameAnnotation(const Vector &annos, cstring name); [[nodiscard]] Vector withoutNameAnnotation(const Vector &annos); void addIfNew(Vector &annotations, cstring name, const Expression *expr, diff --git a/midend/flattenInterfaceStructs.h b/midend/flattenInterfaceStructs.h index f5ed49cc819..87f433534f9 100644 --- a/midend/flattenInterfaceStructs.h +++ b/midend/flattenInterfaceStructs.h @@ -72,11 +72,9 @@ struct StructTypeReplacement : public IHasDbPrint { auto vec = new IR::IndexedVector(); flatten(typeMap, cstring::empty, type, type->annotations, vec, policy); if (type->is()) { - replacementType = - new IR::Type_Struct(type->srcInfo, type->name, IR::Vector(), *vec); + replacementType = new IR::Type_Struct(type->srcInfo, type->name, *vec); } else if (type->is()) { - replacementType = - new IR::Type_Header(type->srcInfo, type->name, IR::Vector(), *vec); + replacementType = new IR::Type_Header(type->srcInfo, type->name, *vec); } else { BUG("Unexpected type %1%", type); }