diff --git a/frontends/p4/specializeGenericTypes.cpp b/frontends/p4/specializeGenericTypes.cpp index d1ab5a8d36..58d2fdc228 100644 --- a/frontends/p4/specializeGenericTypes.cpp +++ b/frontends/p4/specializeGenericTypes.cpp @@ -16,53 +16,80 @@ limitations under the License. #include "specializeGenericTypes.h" +#include "absl/strings/str_replace.h" #include "frontends/p4/typeChecking/typeSubstitutionVisitor.h" namespace P4 { -bool TypeSpecializationMap::same(const TypeSpecialization *spec, - const IR::Type_Specialized *right) const { - if (!spec->specialized->baseType->equiv(*right->baseType)) return false; - BUG_CHECK(spec->argumentTypes->size() == right->arguments->size(), - "Type %1% and %2% specialized with different number of arguments?", spec->specialized, - right); - for (size_t i = 0; i < spec->argumentTypes->size(); i++) { - auto argl = spec->argumentTypes->at(i); - auto argr = typeMap->getType(right->arguments->at(i), true); - if (!typeMap->equivalent(argl, argr)) return false; +const IR::Type_Declaration *TypeSpecializationMap::nextAvailable() { + for (auto &[_, specialization] : map) { + if (specialization.inserted) continue; + auto &insReq = specialization.insertion; + if (insReq.empty()) { + specialization.inserted = true; + return specialization.replacement; + } } - return true; + return nullptr; } -void TypeSpecializationMap::add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl, - const IR::Node *insertion, NameGenerator *nameGen) { - auto it = map.find(t); - if (it != map.end()) return; - - // First check if we have another specialization with the same - // type arguments, in that case reuse it - for (auto it : map) { - if (same(it.second, t)) { - map.emplace(t, it.second); - LOG3("Found to specialize: " << t << " as previous " << it.second->name); - return; - } +void TypeSpecializationMap::markDefined(const IR::Type_Declaration *tdec) { + const auto name = tdec->name.name; + for (auto &[_, specialization] : map) { + if (specialization.inserted) continue; + specialization.insertion.erase(name); } +} - cstring name = nameGen->newName(decl->getName().string_view()); - LOG3("Found to specialize: " << dbp(t) << "(" << t << ") with name " << name - << " insert before " << dbp(insertion)); - auto argTypes = new IR::Vector(); - for (auto a : *t->arguments) argTypes->push_back(typeMap->getType(a, true)); - TypeSpecialization *s = new TypeSpecialization(name, t, decl, insertion, argTypes); - map.emplace(t, s); +void TypeSpecializationMap::fillInsertionSet(const IR::Type_StructLike *decl, + InsertionSet &insertion) { + auto handleName = [&](cstring name) { + LOG4("TSM: " << decl->toString() << " to be inserted after " << name); + insertion.insert(name); + }; + // - not using type map, the struct type could be a fresh one, and even if it is not, struct + // fields will always have known type (unlike e.g. expressions) + // - using visitor to handle type names and type specialization inside types like `list` and + // `tuple`. + forAllMatching( + decl, [&](const IR::Type_Name *tn) { handleName(tn->path->name.name); }); + forAllMatching(decl, [&](const IR::Type_Specialized *ts) { + if (const auto *specialization = get(ts)) { + handleName(specialization->name); + } + }); } -TypeSpecialization *TypeSpecializationMap::get(const IR::Type_Specialized *type) const { - for (auto it : map) { - if (same(it.second, type)) return it.second; +void TypeSpecializationMap::add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl, + NameGenerator *nameGen) { + const auto sig = SpecSignature::get(t); + if (!sig) { + return; } - return nullptr; + if (map.count(*sig)) return; + + cstring name = nameGen->newName(sig->name()); + LOG3("Found to specialize: " << dbp(t) << " with name " << name << " insert after " + << dbp(decl)); + map.emplace(*sig, TypeSpecialization{name, t, decl, {decl->name.name}, t->arguments}); +} + +namespace { + +// depending on constness of Map returns a const or non-const pointer +template +auto *_get(Map &map, const IR::Type_Specialized *type) { + const auto sig = SpecSignature::get(type); + return sig ? getref(map, *sig) : nullptr; +} +} // namespace + +const TypeSpecialization *TypeSpecializationMap::get(const IR::Type_Specialized *type) const { + return _get(map, type); +} + +TypeSpecialization *TypeSpecializationMap::get(const IR::Type_Specialized *type) { + return _get(map, type); } namespace { @@ -92,13 +119,12 @@ class ContainsTypeVariable : public Inspector { Visitor::profile_t FindTypeSpecializations::init_apply(const IR::Node *node) { auto rv = Inspector::init_apply(node); node->apply(nameGen); - return rv; } void FindTypeSpecializations::postorder(const IR::Type_Specialized *type) { - auto baseType = specMap->typeMap->getTypeType(type->baseType, true); - auto st = baseType->to(); + const auto *baseType = getDeclaration(type->baseType->path, true); + const auto *st = baseType->to(); if (st == nullptr || st->typeParameters->size() == 0) // nothing to specialize return; @@ -113,55 +139,52 @@ void FindTypeSpecializations::postorder(const IR::Type_Specialized *type) { // specialized instances of G, e.g., G>. return; } - // Find location where the specialization is to be inserted. - // This can be before a Parser, Control, or a toplevel instance declaration - const IR::Node *insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - if (!insert) insert = findContext(); - CHECK_NULL(insert); - specMap->add(type, st, insert, &nameGen); + specMap->add(type, st, &nameGen); } /////////////////////////////////////////////////////////////////////////////////////// -const IR::Node *CreateSpecializedTypes::postorder(IR::Type_Declaration *type) { - for (auto it : specMap->map) { - if (it.second->declaration->name == type->name) { - auto specialized = it.first; - auto genDecl = type->to(); - TypeVariableSubstitution ts; - ts.setBindings(type, genDecl->getTypeParameters(), specialized->arguments); - TypeSubstitutionVisitor tsv(specMap->typeMap, &ts); - tsv.setCalledBy(this); - auto renamed = type->apply(tsv)->to()->clone(); - cstring name = it.second->name; - auto empty = new IR::TypeParameters(); - renamed->name = name; - renamed->typeParameters = empty; - it.second->replacement = postorder(renamed)->to(); - LOG3("CST Specializing " << dbp(type) << " with " << ts << " as " << dbp(renamed)); - } +void CreateSpecializedTypes::postorder(IR::Type_Specialized *spec) { + if (auto *specialization = specMap->get(spec)) { + const auto *declT = getDeclaration(spec->baseType->path)->to(); + BUG_CHECK(declT, "Could not get declaration for %1%", spec); + auto genDecl = declT->to(); + BUG_CHECK(genDecl, "Not a generic declaration: %1%", declT); + TypeVariableSubstitution ts; + ts.setBindings(declT, genDecl->getTypeParameters(), specialization->argumentTypes); + TypeSubstitutionVisitor tsv(specMap->typeMap, &ts); + tsv.setCalledBy(this); + auto renamed = declT->apply(tsv)->to()->clone(); + cstring name = specialization->name; + renamed->name = name; + renamed->typeParameters = new IR::TypeParameters(); + specialization->replacement = renamed; + // add additional insertion constraints + specMap->fillInsertionSet(renamed, specialization->insertion); + LOG3("CST: Specializing " << dbp(declT) << " with [" << ts << "] as " << dbp(renamed)); } - return insert(type); } -const IR::Node *CreateSpecializedTypes::insert(const IR::Node *before) { - auto specs = specMap->getSpecializations(getOriginal()); - if (specs == nullptr) return before; - LOG2(specs->size() << " instantiations before " << dbp(before)); - specs->push_back(before); - return specs; +void CreateSpecializedTypes::postorder(IR::P4Program *prog) { + IR::Vector newObjects; + for (const auto *obj : prog->objects) { + newObjects.push_back(obj); + if (const auto *tdec = obj->to()) { + specMap->markDefined(tdec); + while (const auto *addTDec = specMap->nextAvailable()) { + newObjects.push_back(addTDec); + specMap->markDefined(addTDec); + LOG2("CST: Will insert " << dbp(addTDec) << " after " << dbp(newObjects.back())); + } + } + } + prog->objects = newObjects; } const IR::Node *ReplaceTypeUses::postorder(IR::Type_Specialized *type) { - auto t = specMap->get(getOriginal()); + auto t = specMap->get(type); if (!t) return type; - CHECK_NULL(t->replacement); + BUG_CHECK(t->replacement, "Missing replacement %1% -> %2%", type, t->name); LOG3("RTU Replacing " << dbp(type) << " with " << dbp(t->replacement)); return t->replacement->getP4Type(); } @@ -189,4 +212,30 @@ const IR::Node *ReplaceTypeUses::postorder(IR::StructExpression *expression) { return expression; } +std::string SpecSignature::name() const { + std::stringstream ss; + ss << baseType; + for (const auto &t : arguments) { + ss << "_" + << absl::StrReplaceAll(t, {{"<", ""}, {">", ""}, {" ", ""}, {",", "_"}, {".", "_"}}); + } + return ss.str(); +} + +std::string toString(const SpecSignature &sig) { + return absl::StrCat(sig.baseType, "<", absl::StrJoin(sig.arguments, ","), ">"); +} + +std::optional SpecSignature::get(const IR::Type_Specialized *spec) { + SpecSignature out; + out.baseType = spec->baseType->path->name; + for (const auto *arg : *spec->arguments) { + if (ContainsTypeVariable::inspect(arg)) { + return {}; + } + out.arguments.push_back(arg->toString()); + } + return out; +} + } // namespace P4 diff --git a/frontends/p4/specializeGenericTypes.h b/frontends/p4/specializeGenericTypes.h index 1c78e9ce12..3d6fa063cc 100644 --- a/frontends/p4/specializeGenericTypes.h +++ b/frontends/p4/specializeGenericTypes.h @@ -22,6 +22,9 @@ limitations under the License. namespace P4 { +/// @brief Set of type declaration names that must be defined before the type can be inserted. +using InsertionSet = absl::flat_hash_set; + struct TypeSpecialization : public IHasDbPrint { /// Name to use for specialized type. cstring name; @@ -31,14 +34,17 @@ struct TypeSpecialization : public IHasDbPrint { const IR::Type_Declaration *declaration; /// New synthesized type (created later) const IR::Type_StructLike *replacement; - /// Insertion point - const IR::Node *insertion; + /// Insertion point, the specialization will be inserted after all the top-level nodes in this + /// set. + InsertionSet insertion; /// Save here the canonical types of the type arguments of 'specialized'. /// The typeMap will be cleared, so we cannot look them up later. const IR::Vector *argumentTypes; + /// was this specialization already inserted? + bool inserted = false; TypeSpecialization(cstring name, const IR::Type_Specialized *specialized, - const IR::Type_Declaration *decl, const IR::Node *insertion, + const IR::Type_Declaration *decl, const InsertionSet &insertion, const IR::Vector *argTypes) : name(name), specialized(specialized), @@ -48,52 +54,78 @@ struct TypeSpecialization : public IHasDbPrint { argumentTypes(argTypes) { CHECK_NULL(specialized); CHECK_NULL(decl); - CHECK_NULL(insertion); CHECK_NULL(argTypes); } void dbprint(std::ostream &out) const override { out << "Specializing:" << dbp(specialized) << " from " << dbp(declaration) << " as " - << dbp(replacement) << " inserted at " << dbp(insertion); + << dbp(replacement) << " inserted at "; + format_container(out, insertion, '(', ')'); } }; -struct TypeSpecializationMap : public IHasDbPrint { +/// @brief A signature of a *concrete* specialization. None of the parameters can be type variables +/// or generic types, therefore the specialization can always be identified globally the the names +/// of types. +struct SpecSignature { + /// @brief Name of the type declaration of the base (unspecialized) type (i.e. the + /// struct/header) + cstring baseType; + /// @brief String representation of the type argument names. + safe_vector arguments; + + /// @brief Get a candidate name for the instantiation. + std::string name() const; + + /// @brief Order for the sake of std::map only, the requirements are: + /// - it is a total order; + /// - all specializations of the same type are grouped together; + /// - no-argument specialization is always ordered immediatelly before any other specializations + /// of the type (for the sake of lower_bound searches); + bool operator<(const SpecSignature &other) const { + // Using pointer comparison to speed up baseType comparation as we don't care about what + // that order is. Note that for pointers we have to use `std::less` to make the comparison + // defined for pointers into different objects. + return std::less<>()(std::forward_as_tuple(baseType.c_str(), arguments), + std::forward_as_tuple(other.baseType.c_str(), other.arguments)); + } + + /// @brief Get a specialization signature if it is valid (i.e. the type is specialized only by + /// concrete non-generic types). + static std::optional get(const IR::Type_Specialized *spec); +}; + +std::string toString(const SpecSignature &); + +struct TypeSpecializationMap : IHasDbPrint { TypeMap *typeMap; - // The map can have multiple keys pointing to the same value - ordered_map map; - // Keep track of the values in the above map which are already - // inserted in the program. - std::set inserted; + ordered_map map; void add(const IR::Type_Specialized *t, const IR::Type_StructLike *decl, - const IR::Node *insertion, NameGenerator *nameGen); - TypeSpecialization *get(const IR::Type_Specialized *t) const; - bool same(const TypeSpecialization *left, const IR::Type_Specialized *right) const; + NameGenerator *nameGen); + const TypeSpecialization *get(const IR::Type_Specialized *t) const; + TypeSpecialization *get(const IR::Type_Specialized *t); void dbprint(std::ostream &out) const override { for (auto it : map) { - out << dbp(it.first) << " => " << it.second << std::endl; - } - } - IR::Vector *getSpecializations(const IR::Node *insertionPoint) { - IR::Vector *result = nullptr; - for (auto s : map) { - if (inserted.find(s.second) != inserted.end()) continue; - if (s.second->insertion == insertionPoint) { - if (result == nullptr) result = new IR::Vector(); - LOG2("Will insert " << dbp(s.second->replacement) << " before " - << dbp(insertionPoint)); - result->push_back(s.second->replacement); - inserted.emplace(s.second); - } + out << toString(it.first) << " => " << it.second << std::endl; } - return result; } + + /// @brief Get a single specialization that is already available (i.e. it does not require any + /// additional definitions) and mark it as inserted. Returns nullptr if none such exists. + [[nodiscard]] const IR::Type_Declaration *nextAvailable(); + /// @brief Mark the @p tdec as already present and therefore remove it from required + /// definitions for specializations. + void markDefined(const IR::Type_Declaration *tdec); + + private: + friend class CreateSpecializedTypes; + void fillInsertionSet(const IR::Type_StructLike *decl, InsertionSet &insertion); }; /** * Find all generic type instantiations and their type arguments. */ -class FindTypeSpecializations : public Inspector { +class FindTypeSpecializations : public Inspector, ResolutionContext { TypeSpecializationMap *specMap; MinimalNameGenerator nameGen; @@ -111,7 +143,7 @@ class FindTypeSpecializations : public Inspector { * For each generic type that is specialized with concrete arguments create a * specialized type version and insert it in the program. */ -class CreateSpecializedTypes : public Transform { +class CreateSpecializedTypes : public Modifier, public ResolutionContext { TypeSpecializationMap *specMap; public: @@ -120,9 +152,8 @@ class CreateSpecializedTypes : public Transform { setName("CreateSpecializedTypes"); } - const IR::Node *insert(const IR::Node *before); - const IR::Node *postorder(IR::Type_Declaration *type) override; - const IR::Node *postorder(IR::Declaration *decl) override { return insert(decl); } + void postorder(IR::Type_Specialized *type) override; + void postorder(IR::P4Program *prog) override; }; /** diff --git a/testdata/p4_16_samples/issue4835-generic-struct.p4 b/testdata/p4_16_samples/issue4835-generic-struct.p4 new file mode 100644 index 0000000000..47211c2231 --- /dev/null +++ b/testdata/p4_16_samples/issue4835-generic-struct.p4 @@ -0,0 +1,39 @@ +#include +#include + +typedef standard_metadata_t std_meta_t; + +header standard_t { + T src; + T dst; +} + +struct headers_t { + standard_t standard; +} + +struct meta_t { } + +parser MyParser(packet_in pkt, out headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + state start { + pkt.extract(hdr.standard); + transition accept; + } +} + +control MyVerifyChecksum(inout headers_t> hdr, inout meta_t meta) { + apply { } +} +control MyComputeChecksum(inout headers_t> hdr, inout meta_t meta) { + apply { } +} +control MyIngress(inout headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { } +} +control MyEgress(inout headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { } +} +control MyDeparser(packet_out pkt, in headers_t> hdr) { + apply { } +} +V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main; diff --git a/testdata/p4_16_samples/type-spec-nested.p4 b/testdata/p4_16_samples/type-spec-nested.p4 new file mode 100644 index 0000000000..ddc358186e --- /dev/null +++ b/testdata/p4_16_samples/type-spec-nested.p4 @@ -0,0 +1,22 @@ +void test(in T val) {} + +struct S2 { + T x; + T y; +} + +struct S1 { + T1 x; + S2 y; +} + +control c(inout bit<8> a) { + apply { + test((S1, int<6>>){x = 0, y = (S2>){x = 0, y = 0}}); + } +} + +control E(inout bit<8> t); +package top(E e); + +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/generic-struct-first.p4 b/testdata/p4_16_samples_outputs/generic-struct-first.p4 index 581bdd927c..7276f8c890 100644 --- a/testdata/p4_16_samples_outputs/generic-struct-first.p4 +++ b/testdata/p4_16_samples_outputs/generic-struct-first.p4 @@ -3,45 +3,49 @@ struct Header { bit<1> valid; } +struct Header_bit16 { + bit<16> data; + bit<1> valid; +} + struct S { bit<32> b; } -struct Header_0 { +struct Header_S { S data; bit<1> valid; } struct U { - Header_0 f; + Header_S f; } -const U u = (U){f = (Header_0){data = (S){b = 32w10},valid = 1w1}}; +const U u = (U){f = (Header_S){data = (S){b = 32w10},valid = 1w1}}; struct H2 { Header g; bit<1> invalid; } -struct H4 { - T x; +struct H2_S { + Header_S g; + bit<1> invalid; } -const Header_0 h2 = (Header_0){data = (S){b = 32w0},valid = 1w0}; -struct Header_1 { - bit<16> data; - bit<1> valid; +struct H4 { + T x; } -const Header_1 bz = (Header_1){data = 16w16,valid = 1w1}; -const Header_0 h = (Header_0){data = (S){b = 32w0},valid = 1w0}; -struct H2_0 { - Header_0 g; - bit<1> invalid; +struct H4_H2_S { + H2_S x; } -const H2_0 h1 = (H2_0){g = (Header_0){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}; -const H2_0 h3 = (H2_0){g = (Header_0){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}; -typedef H2_0 R; +const Header_S h2 = (Header_S){data = (S){b = 32w0},valid = 1w0}; +const Header_bit16 bz = (Header_bit16){data = 16w16,valid = 1w1}; +const Header_S h = (Header_S){data = (S){b = 32w0},valid = 1w0}; +const H2_S h1 = (H2_S){g = (Header_S){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}; +const H2_S h3 = (H2_S){g = (Header_S){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}; +typedef H2_S R; struct H3 { R r; T s; @@ -50,61 +54,57 @@ struct H3 { tuple t; } -header GH { - T data; +struct H3_S { + R r; + S s; + H2_S h2; + H4_H2_S h3; + tuple t; } -header X { - bit<32> b; +header GH { + T data; } -header GH_0 { +header GH_bit32 { bit<32> data; } -const GH_0 g = (GH_0){data = 32w0}; -header GH_1 { +header GH_S { S data; } -const GH_1 g1 = (GH_1){data = (S){b = 32w0}}; -typedef GH_1[3] Stack; -struct H4_0 { - H2_0 x; -} - -struct H3_0 { - R r; - S s; - H2_0 h2; - H4_0 h3; - tuple t; +header X { + bit<32> b; } -const H3_0 h4 = (H3_0){r = (H2_0){g = (Header_0){data = (S){b = 32w10},valid = 1w0},invalid = 1w1},s = (S){b = 32w20},h2 = (H2_0){g = (Header_0){data = (S){b = 32w0},valid = 1w1},invalid = 1w1},h3 = (H4_0){x = (H2_0){g = (Header_0){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}},t = { (S){b = 32w0}, (S){b = 32w1} }}; +const GH_bit32 g = (GH_bit32){data = 32w0}; +const GH_S g1 = (GH_S){data = (S){b = 32w0}}; +typedef GH_S[3] Stack; +const H3_S h4 = (H3_S){r = (H2_S){g = (Header_S){data = (S){b = 32w10},valid = 1w0},invalid = 1w1},s = (S){b = 32w20},h2 = (H2_S){g = (Header_S){data = (S){b = 32w0},valid = 1w1},invalid = 1w1},h3 = (H4_H2_S){x = (H2_S){g = (Header_S){data = (S){b = 32w0},valid = 1w1},invalid = 1w1}},t = { (S){b = 32w0}, (S){b = 32w1} }}; header_union HU { X xu; GH h3u; } -header_union HU_0 { - X xu; - GH_0 h3u; +header_union HU_bit32 { + X xu; + GH_bit32 h3u; } control c(out bit<1> x) { apply { - H3_0 h5; - H4_0 n; - GH_1 gh; + H3_S h5; + H4_H2_S n; + GH_S gh; bool b = gh.isValid(); Stack s; - s[0] = (GH_1){data = (S){b = 32w1}}; + s[0] = (GH_S){data = (S){b = 32w1}}; b = b && s[0].isValid(); X xinst = (X){b = 32w2}; - HU_0 z; + HU_bit32 z; z.xu = xinst; - z.h3u = (GH_0){data = 32w1}; + z.h3u = (GH_bit32){data = 32w1}; x = 1w0; } } diff --git a/testdata/p4_16_samples_outputs/generic-struct-frontend.p4 b/testdata/p4_16_samples_outputs/generic-struct-frontend.p4 index ca61857b3c..62d1ccfda1 100644 --- a/testdata/p4_16_samples_outputs/generic-struct-frontend.p4 +++ b/testdata/p4_16_samples_outputs/generic-struct-frontend.p4 @@ -3,17 +3,22 @@ struct Header { bit<1> valid; } +struct Header_bit16 { + bit<16> data; + bit<1> valid; +} + struct S { bit<32> b; } -struct Header_0 { +struct Header_S { S data; bit<1> valid; } struct U { - Header_0 f; + Header_S f; } struct H2 { @@ -21,21 +26,20 @@ struct H2 { bit<1> invalid; } -struct H4 { - T x; +struct H2_S { + Header_S g; + bit<1> invalid; } -struct Header_1 { - bit<16> data; - bit<1> valid; +struct H4 { + T x; } -struct H2_0 { - Header_0 g; - bit<1> invalid; +struct H4_H2_S { + H2_S x; } -typedef H2_0 R; +typedef H2_S R; struct H3 { R r; T s; @@ -44,49 +48,45 @@ struct H3 { tuple t; } -header GH { - T data; +struct H3_S { + R r; + S s; + H2_S h2; + H4_H2_S h3; + tuple t; } -header X { - bit<32> b; +header GH { + T data; } -header GH_0 { +header GH_bit32 { bit<32> data; } -header GH_1 { +header GH_S { S data; } -typedef GH_1[3] Stack; -struct H4_0 { - H2_0 x; -} - -struct H3_0 { - R r; - S s; - H2_0 h2; - H4_0 h3; - tuple t; +header X { + bit<32> b; } +typedef GH_S[3] Stack; header_union HU { X xu; GH h3u; } -header_union HU_0 { - X xu; - GH_0 h3u; +header_union HU_bit32 { + X xu; + GH_bit32 h3u; } control c(out bit<1> x) { - @name("c.gh") GH_1 gh_0; + @name("c.gh") GH_S gh_0; @name("c.s") Stack s_0; - @name("c.z") HU_0 z_0; + @name("c.z") HU_bit32 z_0; apply { gh_0.setInvalid(); s_0[0].setInvalid(); diff --git a/testdata/p4_16_samples_outputs/generic-struct-midend.p4 b/testdata/p4_16_samples_outputs/generic-struct-midend.p4 index 7d9ac460cb..7dc662d326 100644 --- a/testdata/p4_16_samples_outputs/generic-struct-midend.p4 +++ b/testdata/p4_16_samples_outputs/generic-struct-midend.p4 @@ -3,17 +3,22 @@ struct Header { bit<1> valid; } +struct Header_bit16 { + bit<16> data; + bit<1> valid; +} + struct S { bit<32> b; } -struct Header_0 { +struct Header_S { S data; bit<1> valid; } struct U { - Header_0 f; + Header_S f; } struct H2 { @@ -21,66 +26,61 @@ struct H2 { bit<1> invalid; } -struct H4 { - T x; +struct H2_S { + Header_S g; + bit<1> invalid; } -struct Header_1 { - bit<16> data; - bit<1> valid; +struct H4 { + T x; } -struct H2_0 { - Header_0 g; - bit<1> invalid; +struct H4_H2_S { + H2_S x; } struct H3 { - H2_0 r; + H2_S r; T s; H2 h2; H4> h3; tuple t; } -header GH { - T data; -} - -header X { - bit<32> b; +struct tuple_0 { + S f0; + S f1; } -header GH_0 { - bit<32> data; +struct H3_S { + H2_S r; + S s; + H2_S h2; + H4_H2_S h3; + tuple_0 t; } -header GH_1 { - bit<32> _data_b0; +header GH { + T data; } -struct H4_0 { - H2_0 x; +header GH_bit32 { + bit<32> data; } -struct tuple_0 { - S f0; - S f1; +header GH_S { + bit<32> _data_b0; } -struct H3_0 { - H2_0 r; - S s; - H2_0 h2; - H4_0 h3; - tuple_0 t; +header X { + bit<32> b; } control c(out bit<1> x) { - @name("c.gh") GH_1 gh_0; - @name("c.s") GH_1[3] s_0; + @name("c.gh") GH_S gh_0; + @name("c.s") GH_S[3] s_0; X z_0_xu; - GH_0 z_0_h3u; + GH_bit32 z_0_h3u; @hidden action genericstruct90() { gh_0.setInvalid(); s_0[0].setInvalid(); diff --git a/testdata/p4_16_samples_outputs/generic-struct-tuple-first.p4 b/testdata/p4_16_samples_outputs/generic-struct-tuple-first.p4 index 54d043e530..8d1dd5ec27 100644 --- a/testdata/p4_16_samples_outputs/generic-struct-tuple-first.p4 +++ b/testdata/p4_16_samples_outputs/generic-struct-tuple-first.p4 @@ -2,8 +2,8 @@ struct S { tuple t; } -struct S_0 { +struct S_bit32 { tuple, bit<32>> t; } -const S_0 x = (S_0){t = { 32w0, 32w0 }}; +const S_bit32 x = (S_bit32){t = { 32w0, 32w0 }}; diff --git a/testdata/p4_16_samples_outputs/generic-struct-tuple-frontend.p4 b/testdata/p4_16_samples_outputs/generic-struct-tuple-frontend.p4 index 3cf5e8fa5e..1e02cbeab8 100644 --- a/testdata/p4_16_samples_outputs/generic-struct-tuple-frontend.p4 +++ b/testdata/p4_16_samples_outputs/generic-struct-tuple-frontend.p4 @@ -2,7 +2,7 @@ struct S { tuple t; } -struct S_0 { +struct S_bit32 { tuple, bit<32>> t; } diff --git a/testdata/p4_16_samples_outputs/issue2627-first.p4 b/testdata/p4_16_samples_outputs/issue2627-first.p4 index d7c95f29f6..5bbe1fda53 100644 --- a/testdata/p4_16_samples_outputs/issue2627-first.p4 +++ b/testdata/p4_16_samples_outputs/issue2627-first.p4 @@ -6,8 +6,8 @@ struct S { bit<32> b; } -struct H3_0 { +struct H3_S { tuple t; } -const H3_0 h4 = (H3_0){t = { (S){b = 32w0} }}; +const H3_S h4 = (H3_S){t = { (S){b = 32w0} }}; diff --git a/testdata/p4_16_samples_outputs/issue2627-frontend.p4 b/testdata/p4_16_samples_outputs/issue2627-frontend.p4 index 5baf8a1bbb..1b1f7df0c1 100644 --- a/testdata/p4_16_samples_outputs/issue2627-frontend.p4 +++ b/testdata/p4_16_samples_outputs/issue2627-frontend.p4 @@ -6,7 +6,7 @@ struct S { bit<32> b; } -struct H3_0 { +struct H3_S { tuple t; } diff --git a/testdata/p4_16_samples_outputs/issue2635-first.p4 b/testdata/p4_16_samples_outputs/issue2635-first.p4 index 971a4d275b..ecd235d545 100644 --- a/testdata/p4_16_samples_outputs/issue2635-first.p4 +++ b/testdata/p4_16_samples_outputs/issue2635-first.p4 @@ -3,18 +3,18 @@ struct S { bit<32> otherField; } -struct S_0 { +struct S_bit32_bit32 { bit<32> field; bit<32> otherField; } -const S_0 s = (S_0){field = 32w0,otherField = 32w0}; +const S_bit32_bit32 s = (S_bit32_bit32){field = 32w0,otherField = 32w0}; control _c(out T t); package top(_c c); -control c(out S_0 t) { +control c(out S_bit32_bit32 t) { apply { - t = (S_0){field = 32w0,otherField = 32w0}; + t = (S_bit32_bit32){field = 32w0,otherField = 32w0}; } } -top(c()) main; +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/issue2635-frontend.p4 b/testdata/p4_16_samples_outputs/issue2635-frontend.p4 index d9945fe785..ed470a1d5c 100644 --- a/testdata/p4_16_samples_outputs/issue2635-frontend.p4 +++ b/testdata/p4_16_samples_outputs/issue2635-frontend.p4 @@ -3,17 +3,17 @@ struct S { bit<32> otherField; } -struct S_0 { +struct S_bit32_bit32 { bit<32> field; bit<32> otherField; } control _c(out T t); package top(_c c); -control c(out S_0 t) { +control c(out S_bit32_bit32 t) { apply { - t = (S_0){field = 32w0,otherField = 32w0}; + t = (S_bit32_bit32){field = 32w0,otherField = 32w0}; } } -top(c()) main; +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/issue2635-midend.p4 b/testdata/p4_16_samples_outputs/issue2635-midend.p4 index dce0bf29a3..322cde4501 100644 --- a/testdata/p4_16_samples_outputs/issue2635-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue2635-midend.p4 @@ -3,14 +3,14 @@ struct S { bit<32> otherField; } -struct S_0 { +struct S_bit32_bit32 { bit<32> field; bit<32> otherField; } control _c(out T t); package top(_c c); -control c(out S_0 t) { +control c(out S_bit32_bit32 t) { @hidden action issue2635l13() { t.field = 32w0; t.otherField = 32w0; @@ -26,4 +26,4 @@ control c(out S_0 t) { } } -top(c()) main; +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/issue3203-first.p4 b/testdata/p4_16_samples_outputs/issue3203-first.p4 index 18522d4cad..8af1434906 100644 --- a/testdata/p4_16_samples_outputs/issue3203-first.p4 +++ b/testdata/p4_16_samples_outputs/issue3203-first.p4 @@ -2,10 +2,10 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } -bit<1> func(h_0 a) { +bit<1> func(h_bit1 a) { return a.f; } diff --git a/testdata/p4_16_samples_outputs/issue3203-frontend.p4 b/testdata/p4_16_samples_outputs/issue3203-frontend.p4 index 90bd8cd509..273be5ba91 100644 --- a/testdata/p4_16_samples_outputs/issue3203-frontend.p4 +++ b/testdata/p4_16_samples_outputs/issue3203-frontend.p4 @@ -2,7 +2,7 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } diff --git a/testdata/p4_16_samples_outputs/issue3204-first.p4 b/testdata/p4_16_samples_outputs/issue3204-first.p4 index f33d132d44..6836181da0 100644 --- a/testdata/p4_16_samples_outputs/issue3204-first.p4 +++ b/testdata/p4_16_samples_outputs/issue3204-first.p4 @@ -2,12 +2,12 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } bit<1> func() { - h_0 a; + h_bit1 a; a.f = 1w1; return a.f; } diff --git a/testdata/p4_16_samples_outputs/issue3204-frontend.p4 b/testdata/p4_16_samples_outputs/issue3204-frontend.p4 index 90bd8cd509..273be5ba91 100644 --- a/testdata/p4_16_samples_outputs/issue3204-frontend.p4 +++ b/testdata/p4_16_samples_outputs/issue3204-frontend.p4 @@ -2,7 +2,7 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } diff --git a/testdata/p4_16_samples_outputs/issue3291-1-first.p4 b/testdata/p4_16_samples_outputs/issue3291-1-first.p4 index 48c7e3e9d6..53c2ed9cdf 100644 --- a/testdata/p4_16_samples_outputs/issue3291-1-first.p4 +++ b/testdata/p4_16_samples_outputs/issue3291-1-first.p4 @@ -2,26 +2,26 @@ struct h { t f; } -bool g(in t a) { - h v; - v.f = a; - return v.f == a; -} -struct h_0 { +struct h_bit1 { bit<1> f; } -struct h_1 { - h_0 f; +struct h_h_bit1 { + h_bit1 f; } -bool g_0(in h_0 a) { - h_1 v; +bool g(in t a) { + h v; + v.f = a; + return v.f == a; +} +bool g_0(in h_bit1 a) { + h_h_bit1 v; v.f = a; return v.f == a; } bool gg() { - h_0 a = (h_0){f = 1w0}; + h_bit1 a = (h_bit1){f = 1w0}; return g_0(a); } control c(out bool x) { diff --git a/testdata/p4_16_samples_outputs/issue3291-1-frontend.p4 b/testdata/p4_16_samples_outputs/issue3291-1-frontend.p4 index 24d0181d63..48f742be56 100644 --- a/testdata/p4_16_samples_outputs/issue3291-1-frontend.p4 +++ b/testdata/p4_16_samples_outputs/issue3291-1-frontend.p4 @@ -2,25 +2,25 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } -struct h_1 { - h_0 f; +struct h_h_bit1 { + h_bit1 f; } control c(out bool x) { @name("c.retval_0") bool retval; @name("c.tmp") bool tmp; - @name("c.a") h_0 a; - @name("c.a_0") h_0 a_2; + @name("c.a") h_bit1 a; + @name("c.a_0") h_bit1 a_2; @name("c.retval") bool retval_0; - @name("c.v") h_1 v_0; + @name("c.v") h_h_bit1 v_0; @name("c.inlinedRetval") bool inlinedRetval_1; @name("c.inlinedRetval_0") bool inlinedRetval_2; apply { - a = (h_0){f = 1w0}; + a = (h_bit1){f = 1w0}; a_2 = a; v_0.f = a_2; retval_0 = v_0.f == a_2; diff --git a/testdata/p4_16_samples_outputs/issue3291-1-midend.p4 b/testdata/p4_16_samples_outputs/issue3291-1-midend.p4 index dfcdcb6999..26edb8cd0e 100644 --- a/testdata/p4_16_samples_outputs/issue3291-1-midend.p4 +++ b/testdata/p4_16_samples_outputs/issue3291-1-midend.p4 @@ -2,12 +2,12 @@ struct h { t f; } -struct h_0 { +struct h_bit1 { bit<1> f; } -struct h_1 { - h_0 f; +struct h_h_bit1 { + h_bit1 f; } control c(out bool x) { diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct-first.p4 b/testdata/p4_16_samples_outputs/issue4835-generic-struct-first.p4 new file mode 100644 index 0000000000..c78d24aa36 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct-first.p4 @@ -0,0 +1,59 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +typedef standard_metadata_t std_meta_t; +header standard_t { + T src; + T dst; +} + +header standard_t_bit8 { + bit<8> src; + bit<8> dst; +} + +struct headers_t { + standard_t standard; +} + +struct headers_t_bit8 { + standard_t_bit8 standard; +} + +struct meta_t { +} + +parser MyParser(packet_in pkt, out headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + state start { + pkt.extract(hdr.standard); + transition accept; + } +} + +control MyVerifyChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyComputeChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyIngress(inout headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyEgress(inout headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyDeparser(packet_out pkt, in headers_t_bit8 hdr) { + apply { + } +} + +V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main; diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct-frontend.p4 b/testdata/p4_16_samples_outputs/issue4835-generic-struct-frontend.p4 new file mode 100644 index 0000000000..c78d24aa36 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct-frontend.p4 @@ -0,0 +1,59 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +typedef standard_metadata_t std_meta_t; +header standard_t { + T src; + T dst; +} + +header standard_t_bit8 { + bit<8> src; + bit<8> dst; +} + +struct headers_t { + standard_t standard; +} + +struct headers_t_bit8 { + standard_t_bit8 standard; +} + +struct meta_t { +} + +parser MyParser(packet_in pkt, out headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + state start { + pkt.extract(hdr.standard); + transition accept; + } +} + +control MyVerifyChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyComputeChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyIngress(inout headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyEgress(inout headers_t_bit8 hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyDeparser(packet_out pkt, in headers_t_bit8 hdr) { + apply { + } +} + +V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main; diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct-midend.p4 b/testdata/p4_16_samples_outputs/issue4835-generic-struct-midend.p4 new file mode 100644 index 0000000000..bb4fd9b00e --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct-midend.p4 @@ -0,0 +1,58 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +header standard_t { + T src; + T dst; +} + +header standard_t_bit8 { + bit<8> src; + bit<8> dst; +} + +struct headers_t { + standard_t standard; +} + +struct headers_t_bit8 { + standard_t_bit8 standard; +} + +struct meta_t { +} + +parser MyParser(packet_in pkt, out headers_t_bit8 hdr, inout meta_t meta, inout standard_metadata_t std_meta) { + state start { + pkt.extract(hdr.standard); + transition accept; + } +} + +control MyVerifyChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyComputeChecksum(inout headers_t_bit8 hdr, inout meta_t meta) { + apply { + } +} + +control MyIngress(inout headers_t_bit8 hdr, inout meta_t meta, inout standard_metadata_t std_meta) { + apply { + } +} + +control MyEgress(inout headers_t_bit8 hdr, inout meta_t meta, inout standard_metadata_t std_meta) { + apply { + } +} + +control MyDeparser(packet_out pkt, in headers_t_bit8 hdr) { + apply { + } +} + +V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main; diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4 b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4 new file mode 100644 index 0000000000..1661ffcb9f --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4 @@ -0,0 +1,50 @@ +#include +#define V1MODEL_VERSION 20180101 +#include + +typedef standard_metadata_t std_meta_t; +header standard_t { + T src; + T dst; +} + +struct headers_t { + standard_t standard; +} + +struct meta_t { +} + +parser MyParser(packet_in pkt, out headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + state start { + pkt.extract(hdr.standard); + transition accept; + } +} + +control MyVerifyChecksum(inout headers_t> hdr, inout meta_t meta) { + apply { + } +} + +control MyComputeChecksum(inout headers_t> hdr, inout meta_t meta) { + apply { + } +} + +control MyIngress(inout headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyEgress(inout headers_t> hdr, inout meta_t meta, inout std_meta_t std_meta) { + apply { + } +} + +control MyDeparser(packet_out pkt, in headers_t> hdr) { + apply { + } +} + +V1Switch(MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser()) main; diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4-stderr b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4-stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.entries.txtpb b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.entries.txtpb new file mode 100644 index 0000000000..5cb9652623 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.entries.txtpb @@ -0,0 +1,3 @@ +# proto-file: p4/v1/p4runtime.proto +# proto-message: p4.v1.WriteRequest + diff --git a/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.p4info.txtpb b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.p4info.txtpb new file mode 100644 index 0000000000..fdf16790b9 --- /dev/null +++ b/testdata/p4_16_samples_outputs/issue4835-generic-struct.p4.p4info.txtpb @@ -0,0 +1,6 @@ +# proto-file: p4/config/v1/p4info.proto +# proto-message: p4.config.v1.P4Info + +pkg_info { + arch: "v1model" +} diff --git a/testdata/p4_16_samples_outputs/list9-first.p4 b/testdata/p4_16_samples_outputs/list9-first.p4 index be852b7ac0..b9a401b04f 100644 --- a/testdata/p4_16_samples_outputs/list9-first.p4 +++ b/testdata/p4_16_samples_outputs/list9-first.p4 @@ -4,17 +4,17 @@ struct S { T t; } -struct S_0 { +struct S_bit32 { bit<32> t; } extern E { - E(list data); + E(list data); void run(); } control c() { - E((list){(S_0){t = 32w10},(S_0){t = 32w5}}) e; + E((list){(S_bit32){t = 32w10},(S_bit32){t = 32w5}}) e; apply { e.run(); } diff --git a/testdata/p4_16_samples_outputs/list9-frontend.p4 b/testdata/p4_16_samples_outputs/list9-frontend.p4 index 22fd36253c..e3e2dfd503 100644 --- a/testdata/p4_16_samples_outputs/list9-frontend.p4 +++ b/testdata/p4_16_samples_outputs/list9-frontend.p4 @@ -4,17 +4,17 @@ struct S { T t; } -struct S_0 { +struct S_bit32 { bit<32> t; } extern E { - E(list data); + E(list data); void run(); } control c() { - @name("c.e") E((list){(S_0){t = 32w10},(S_0){t = 32w5}}) e_0; + @name("c.e") E((list){(S_bit32){t = 32w10},(S_bit32){t = 32w5}}) e_0; apply { e_0.run(); } diff --git a/testdata/p4_16_samples_outputs/list9-midend.p4 b/testdata/p4_16_samples_outputs/list9-midend.p4 index af56cfeae6..7e880ead9a 100644 --- a/testdata/p4_16_samples_outputs/list9-midend.p4 +++ b/testdata/p4_16_samples_outputs/list9-midend.p4 @@ -4,17 +4,17 @@ struct S { T t; } -struct S_0 { +struct S_bit32 { bit<32> t; } extern E { - E(list data); + E(list data); void run(); } control c() { - @name("c.e") E((list){(S_0){t = 32w10},(S_0){t = 32w5}}) e_0; + @name("c.e") E((list){(S_bit32){t = 32w10},(S_bit32){t = 32w5}}) e_0; @hidden action list9l15() { e_0.run(); } diff --git a/testdata/p4_16_samples_outputs/p4rt_digest_complex-first.p4 b/testdata/p4_16_samples_outputs/p4rt_digest_complex-first.p4 index e2f64c951a..b648c0d9c0 100644 --- a/testdata/p4_16_samples_outputs/p4rt_digest_complex-first.p4 +++ b/testdata/p4_16_samples_outputs/p4rt_digest_complex-first.p4 @@ -14,10 +14,19 @@ struct s2_t { T f; } +struct s2_t_bit32 { + bit<16> f16; + bit<32> f; +} + @name("s3_t") struct s3_t { T f; } +@name("s3_t") struct s3_t_bit64 { + bit<64> f; +} + header h_t { s_t s; bit<32> f32; @@ -51,26 +60,17 @@ control MyEC(inout EMPTY a, inout EMPTY b, in psa_egress_input_metadata_t c, ino } } -struct s2_t_0 { - bit<16> f16; - bit<32> f; -} - -@name("s3_t") struct s3_t_0 { - bit<64> f; -} - struct digest_t { - h_t h; - PortId_t port; - s2_t_0 s2; - s3_t_0 s3; + h_t h; + PortId_t port; + s2_t_bit32 s2; + s3_t_bit64 s3; } control MyID(packet_out buffer, out EMPTY a, out EMPTY b, out EMPTY c, inout headers hdr, in EMPTY e, in psa_ingress_output_metadata_t f) { Digest() digest; apply { - digest.pack((digest_t){h = hdr.h,port = f.egress_port,s2 = (s2_t_0){f16 = 16w10,f = 32w20},s3 = (s3_t_0){f = 64w30}}); + digest.pack((digest_t){h = hdr.h,port = f.egress_port,s2 = (s2_t_bit32){f16 = 16w10,f = 32w20},s3 = (s3_t_bit64){f = 64w30}}); } } diff --git a/testdata/p4_16_samples_outputs/p4rt_digest_complex-frontend.p4 b/testdata/p4_16_samples_outputs/p4rt_digest_complex-frontend.p4 index fabf557f44..13a0ae9a26 100644 --- a/testdata/p4_16_samples_outputs/p4rt_digest_complex-frontend.p4 +++ b/testdata/p4_16_samples_outputs/p4rt_digest_complex-frontend.p4 @@ -14,10 +14,19 @@ struct s2_t { T f; } +struct s2_t_bit32 { + bit<16> f16; + bit<32> f; +} + @name("s3_t") struct s3_t { T f; } +@name("s3_t") struct s3_t_bit64 { + bit<64> f; +} + header h_t { s_t s; bit<32> f32; @@ -51,27 +60,18 @@ control MyEC(inout EMPTY a, inout EMPTY b, in psa_egress_input_metadata_t c, ino } } -struct s2_t_0 { - bit<16> f16; - bit<32> f; -} - -@name("s3_t") struct s3_t_0 { - bit<64> f; -} - struct digest_t { - h_t h; - PortId_t port; - s2_t_0 s2; - s3_t_0 s3; + h_t h; + PortId_t port; + s2_t_bit32 s2; + s3_t_bit64 s3; } control MyID(packet_out buffer, out EMPTY a, out EMPTY b, out EMPTY c, inout headers hdr, in EMPTY e, in psa_ingress_output_metadata_t f) { @name("MyID.tmp") digest_t tmp; @name("MyID.digest") Digest() digest_0; apply { - tmp = (digest_t){h = hdr.h,port = f.egress_port,s2 = (s2_t_0){f16 = 16w10,f = 32w20},s3 = (s3_t_0){f = 64w30}}; + tmp = (digest_t){h = hdr.h,port = f.egress_port,s2 = (s2_t_bit32){f16 = 16w10,f = 32w20},s3 = (s3_t_bit64){f = 64w30}}; digest_0.pack(tmp); } } diff --git a/testdata/p4_16_samples_outputs/p4rt_digest_complex-midend.p4 b/testdata/p4_16_samples_outputs/p4rt_digest_complex-midend.p4 index c5c134f517..20dc9fa1fb 100644 --- a/testdata/p4_16_samples_outputs/p4rt_digest_complex-midend.p4 +++ b/testdata/p4_16_samples_outputs/p4rt_digest_complex-midend.p4 @@ -14,10 +14,19 @@ struct s2_t { T f; } +struct s2_t_bit32 { + bit<16> f16; + bit<32> f; +} + @name("s3_t") struct s3_t { T f; } +@name("s3_t") struct s3_t_bit64 { + bit<64> f; +} + header h_t { bit<8> _s_f80; bit<16> _s_f161; @@ -61,25 +70,16 @@ control MyEC(inout EMPTY a, inout EMPTY b, in psa_egress_input_metadata_t c, ino } } -struct s2_t_0 { - bit<16> f16; - bit<32> f; -} - -@name("s3_t") struct s3_t_0 { - bit<64> f; -} - struct digest_t { - h_t h; - bit<32> port; - s2_t_0 s2; - s3_t_0 s3; + h_t h; + bit<32> port; + s2_t_bit32 s2; + s3_t_bit64 s3; } control MyID(packet_out buffer, out EMPTY a, out EMPTY b, out EMPTY c, inout headers hdr, in EMPTY e, in psa_ingress_output_metadata_t f) { - s2_t_0 tmp_s2; - s3_t_0 tmp_s3; + s2_t_bit32 tmp_s2; + s3_t_bit64 tmp_s3; @name("MyID.digest") Digest() digest_0; @hidden action p4rt_digest_complex92() { tmp_s2.f16 = 16w10; diff --git a/testdata/p4_16_samples_outputs/p4rt_digest_complex.p4.p4info.txtpb b/testdata/p4_16_samples_outputs/p4rt_digest_complex.p4.p4info.txtpb index 69bb01d7c8..b2ccb629ab 100644 --- a/testdata/p4_16_samples_outputs/p4rt_digest_complex.p4.p4info.txtpb +++ b/testdata/p4_16_samples_outputs/p4rt_digest_complex.p4.p4info.txtpb @@ -40,7 +40,7 @@ type_info { name: "s2" type_spec { struct { - name: "s2_t_0" + name: "s2_t_bit32" } } } @@ -55,7 +55,7 @@ type_info { } } structs { - key: "s2_t_0" + key: "s2_t_bit32" value { members { name: "f16" diff --git a/testdata/p4_16_samples_outputs/stack-init-first.p4 b/testdata/p4_16_samples_outputs/stack-init-first.p4 index 13aa469ca6..a5f973f621 100644 --- a/testdata/p4_16_samples_outputs/stack-init-first.p4 +++ b/testdata/p4_16_samples_outputs/stack-init-first.p4 @@ -3,15 +3,15 @@ header H { T t; } -header H_0 { +header H_bit32 { bit<32> b; bit<32> t; } control c(out bit<32> r) { apply { - H_0[3] s; - s = (H_0[3]){(H_0){b = 32w0,t = 32w1},(H_0){b = 32w2,t = 32w3},(H_0){#}}; + H_bit32[3] s; + s = (H_bit32[3]){(H_bit32){b = 32w0,t = 32w1},(H_bit32){b = 32w2,t = 32w3},(H_bit32){#}}; r = s[0].b + s[0].t + s[1].b + s[1].t + s[2].b; } } diff --git a/testdata/p4_16_samples_outputs/stack-init-frontend.p4 b/testdata/p4_16_samples_outputs/stack-init-frontend.p4 index 02f765c369..01f94c8320 100644 --- a/testdata/p4_16_samples_outputs/stack-init-frontend.p4 +++ b/testdata/p4_16_samples_outputs/stack-init-frontend.p4 @@ -3,18 +3,18 @@ header H { T t; } -header H_0 { +header H_bit32 { bit<32> b; bit<32> t; } control c(out bit<32> r) { - @name("c.s") H_0[3] s_0; + @name("c.s") H_bit32[3] s_0; apply { s_0[0].setInvalid(); s_0[1].setInvalid(); s_0[2].setInvalid(); - s_0 = (H_0[3]){(H_0){b = 32w0,t = 32w1},(H_0){b = 32w2,t = 32w3},(H_0){#}}; + s_0 = (H_bit32[3]){(H_bit32){b = 32w0,t = 32w1},(H_bit32){b = 32w2,t = 32w3},(H_bit32){#}}; r = s_0[0].b + s_0[0].t + s_0[1].b + s_0[1].t + s_0[2].b; } } diff --git a/testdata/p4_16_samples_outputs/stack-init-midend.p4 b/testdata/p4_16_samples_outputs/stack-init-midend.p4 index c01ffdb3b2..9f7d0ffbb5 100644 --- a/testdata/p4_16_samples_outputs/stack-init-midend.p4 +++ b/testdata/p4_16_samples_outputs/stack-init-midend.p4 @@ -3,21 +3,21 @@ header H { T t; } -header H_0 { +header H_bit32 { bit<32> b; bit<32> t; } control c(out bit<32> r) { - H_0 ih; - @name("c.s") H_0[3] s_0; + H_bit32 ih; + @name("c.s") H_bit32[3] s_0; @hidden action stackinit8() { ih.setInvalid(); s_0[0].setInvalid(); s_0[1].setInvalid(); s_0[2].setInvalid(); - s_0[0] = (H_0){b = 32w0,t = 32w1}; - s_0[1] = (H_0){b = 32w2,t = 32w3}; + s_0[0] = (H_bit32){b = 32w0,t = 32w1}; + s_0[1] = (H_bit32){b = 32w2,t = 32w3}; s_0[2] = ih; r = s_0[0].b + s_0[0].t + s_0[1].b + s_0[1].t + s_0[2].b; } diff --git a/testdata/p4_16_samples_outputs/type-spec-nested-first.p4 b/testdata/p4_16_samples_outputs/type-spec-nested-first.p4 new file mode 100644 index 0000000000..b28d9a0820 --- /dev/null +++ b/testdata/p4_16_samples_outputs/type-spec-nested-first.p4 @@ -0,0 +1,33 @@ +void test(in T val) { +} +struct S2 { + T x; + T y; +} + +struct S2_int6 { + int<6> x; + int<6> y; +} + +struct S1 { + T1 x; + S2 y; +} + +struct S1_bit4_int6 { + bit<4> x; + S2_int6 y; +} + +void test_0(in S1_bit4_int6 val) { +} +control c(inout bit<8> a) { + apply { + test_0((S1_bit4_int6){x = 4w0,y = (S2_int6){x = 6s0,y = 6s0}}); + } +} + +control E(inout bit<8> t); +package top(E e); +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/type-spec-nested-frontend.p4 b/testdata/p4_16_samples_outputs/type-spec-nested-frontend.p4 new file mode 100644 index 0000000000..694de41ddc --- /dev/null +++ b/testdata/p4_16_samples_outputs/type-spec-nested-frontend.p4 @@ -0,0 +1,28 @@ +struct S2 { + T x; + T y; +} + +struct S2_int6 { + int<6> x; + int<6> y; +} + +struct S1 { + T1 x; + S2 y; +} + +struct S1_bit4_int6 { + bit<4> x; + S2_int6 y; +} + +control c(inout bit<8> a) { + apply { + } +} + +control E(inout bit<8> t); +package top(E e); +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/type-spec-nested-midend.p4 b/testdata/p4_16_samples_outputs/type-spec-nested-midend.p4 new file mode 100644 index 0000000000..694de41ddc --- /dev/null +++ b/testdata/p4_16_samples_outputs/type-spec-nested-midend.p4 @@ -0,0 +1,28 @@ +struct S2 { + T x; + T y; +} + +struct S2_int6 { + int<6> x; + int<6> y; +} + +struct S1 { + T1 x; + S2 y; +} + +struct S1_bit4_int6 { + bit<4> x; + S2_int6 y; +} + +control c(inout bit<8> a) { + apply { + } +} + +control E(inout bit<8> t); +package top(E e); +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/type-spec-nested.p4 b/testdata/p4_16_samples_outputs/type-spec-nested.p4 new file mode 100644 index 0000000000..a28b7d3e71 --- /dev/null +++ b/testdata/p4_16_samples_outputs/type-spec-nested.p4 @@ -0,0 +1,21 @@ +void test(in T val) { +} +struct S2 { + T x; + T y; +} + +struct S1 { + T1 x; + S2 y; +} + +control c(inout bit<8> a) { + apply { + test((S1, int<6>>){x = 0,y = (S2>){x = 0,y = 0}}); + } +} + +control E(inout bit<8> t); +package top(E e); +top(c()) main; diff --git a/testdata/p4_16_samples_outputs/type-spec-nested.p4-stderr b/testdata/p4_16_samples_outputs/type-spec-nested.p4-stderr new file mode 100644 index 0000000000..e69de29bb2