diff --git a/backends/bmv2/common/JsonObjects.cpp b/backends/bmv2/common/JsonObjects.cpp index 9b81a5e6df9..8f0c741e3c2 100644 --- a/backends/bmv2/common/JsonObjects.cpp +++ b/backends/bmv2/common/JsonObjects.cpp @@ -55,9 +55,9 @@ JsonObjects::JsonObjects() { Util::JsonArray *JsonObjects::get_field_list_contents(unsigned id) const { for (auto e : *field_lists) { auto obj = e->to(); - auto val = obj->get("id"_cs)->to(); + auto val = obj->getAs("id"); if (val != nullptr && val->isNumber() && val->getInt() == static_cast(id)) { - return obj->get("elements"_cs)->to(); + return obj->getAs("elements"); } } return nullptr; @@ -66,7 +66,7 @@ Util::JsonArray *JsonObjects::get_field_list_contents(unsigned id) const { Util::JsonObject *JsonObjects::find_object_by_name(Util::JsonArray *array, const cstring &name) { for (auto e : *array) { auto obj = e->to(); - auto val = obj->get("name"_cs)->to(); + auto val = obj->getAs("name"); if (val != nullptr && val->isString() && val->getString() == name) { return obj; } @@ -90,7 +90,7 @@ Util::JsonArray *JsonObjects::create_parameters(Util::JsonObject *object) { return insert_array_field(object, "parameters"_cs); } -void JsonObjects::add_program_info(const cstring &name) { toplevel->emplace("program"_cs, name); } +void JsonObjects::add_program_info(const cstring &name) { toplevel->emplace("program", name); } void JsonObjects::add_meta_info() { static constexpr int version_major = JSON_MAJOR_VERSION; @@ -98,8 +98,8 @@ void JsonObjects::add_meta_info() { auto version = insert_array_field(meta, "version"_cs); version->append(version_major); version->append(version_minor); - meta->emplace("compiler"_cs, "https://github.com/p4lang/p4c"); - toplevel->emplace("__meta__"_cs, meta); + meta->emplace("compiler", "https://github.com/p4lang/p4c"); + toplevel->emplace("__meta__", meta); } /// Create a header type in json. /// @param name header name @@ -117,15 +117,15 @@ unsigned JsonObjects::add_header_type(const cstring &name, Util::JsonArray *&fie auto header_type = new Util::JsonObject(); unsigned id = BMV2::nextId("header_types"_cs); header_type_id[sname] = id; - header_type->emplace("name"_cs, name); - header_type->emplace("id"_cs, id); + header_type->emplace("name", name); + header_type->emplace("id", id); if (fields != nullptr) { header_type->emplace("fields"_cs, fields); } else { auto temp = new Util::JsonArray(); header_type->emplace("fields"_cs, temp); } - if (max_length > 0) header_type->emplace("max_length"_cs, max_length); + if (max_length > 0) header_type->emplace("max_length", max_length); header_types->append(header_type); return id; } @@ -137,8 +137,8 @@ unsigned JsonObjects::add_union_type(const cstring &name, Util::JsonArray *&fiel auto union_type = new Util::JsonObject(); unsigned id = BMV2::nextId("header_union_types"_cs); union_type_id[sname] = id; - union_type->emplace("name"_cs, name); - union_type->emplace("id"_cs, id); + union_type->emplace("name", name); + union_type->emplace("id", id); if (fields != nullptr) { union_type->emplace("headers"_cs, fields); } else { @@ -158,10 +158,10 @@ unsigned JsonObjects::add_header_type(const cstring &name) { auto header_type = new Util::JsonObject(); unsigned id = BMV2::nextId("header_types"_cs); header_type_id[sname] = id; - header_type->emplace("name"_cs, name); - header_type->emplace("id"_cs, id); + header_type->emplace("name", name); + header_type->emplace("id", id); auto temp = new Util::JsonArray(); - header_type->emplace("fields"_cs, temp); + header_type->emplace("fields", temp); header_types->append(header_type); return id; } @@ -169,7 +169,7 @@ unsigned JsonObjects::add_header_type(const cstring &name) { void JsonObjects::add_header_field(const cstring &name, Util::JsonArray *&field) { CHECK_NULL(field); Util::JsonObject *headerType = find_object_by_name(header_types, name); - Util::JsonArray *fields = headerType->get("fields"_cs)->to(); + Util::JsonArray *fields = headerType->getAs("fields"); BUG_CHECK(fields != nullptr, "header '%1%' not found", name); fields->append(field); } @@ -178,11 +178,11 @@ unsigned JsonObjects::add_header(const cstring &type, const cstring &name) { auto header = new Util::JsonObject(); unsigned id = BMV2::nextId("headers"_cs); LOG1("add header id " << id); - header->emplace("name"_cs, name); - header->emplace("id"_cs, id); - header->emplace("header_type"_cs, type); - header->emplace("metadata"_cs, false); - header->emplace("pi_omit"_cs, true); + header->emplace("name", name); + header->emplace("id", id); + header->emplace("header_type", type); + header->emplace("metadata", false); + header->emplace("pi_omit", true); headers->append(header); return id; } @@ -192,11 +192,11 @@ unsigned JsonObjects::add_union(const cstring &type, Util::JsonArray *&headers, auto u = new Util::JsonObject(); unsigned id = BMV2::nextId("header_unions"_cs); LOG3("add header_union id " << id); - u->emplace("name"_cs, name); - u->emplace("id"_cs, id); - u->emplace("union_type"_cs, type); - u->emplace("header_ids"_cs, headers); - u->emplace("pi_omit"_cs, true); + u->emplace("name", name); + u->emplace("id", id); + u->emplace("union_type", type); + u->emplace("header_ids", headers); + u->emplace("pi_omit", true); header_unions->append(u); return id; } @@ -205,11 +205,11 @@ unsigned JsonObjects::add_metadata(const cstring &type, const cstring &name) { auto header = new Util::JsonObject(); unsigned id = BMV2::nextId("headers"_cs); LOG3("add metadata header id " << id); - header->emplace("name"_cs, name); - header->emplace("id"_cs, id); - header->emplace("header_type"_cs, type); - header->emplace("metadata"_cs, true); - header->emplace("pi_omit"_cs, true); // Don't expose in PI. + header->emplace("name", name); + header->emplace("id", id); + header->emplace("header_type", type); + header->emplace("metadata", true); + header->emplace("pi_omit", true); // Don't expose in PI. headers->append(header); return id; } @@ -218,12 +218,12 @@ void JsonObjects::add_header_stack(const cstring &type, const cstring &name, con const std::vector &ids) { auto stack = new Util::JsonObject(); unsigned id = BMV2::nextId("stack"_cs); - stack->emplace("name"_cs, name); - stack->emplace("id"_cs, id); - stack->emplace("header_type"_cs, type); - stack->emplace("size"_cs, size); + stack->emplace("name", name); + stack->emplace("id", id); + stack->emplace("header_type", type); + stack->emplace("size", size); auto members = new Util::JsonArray(); - stack->emplace("header_ids"_cs, members); + stack->emplace("header_ids", members); for (auto id : ids) { members->append(id); } @@ -234,12 +234,12 @@ void JsonObjects::add_header_union_stack(const cstring &type, const cstring &nam const unsigned size, const std::vector &ids) { auto stack = new Util::JsonObject(); unsigned id = BMV2::nextId("union_stack"_cs); - stack->emplace("name"_cs, name); - stack->emplace("id"_cs, id); - stack->emplace("union_type"_cs, type); - stack->emplace("size"_cs, size); + stack->emplace("name", name); + stack->emplace("id", id); + stack->emplace("union_type", type); + stack->emplace("size", size); auto members = new Util::JsonArray(); - stack->emplace("header_union_ids"_cs, members); + stack->emplace("header_union_ids", members); for (auto id : ids) { members->append(id); } @@ -258,7 +258,7 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, Util::JsonObject *enum_json = find_object_by_name(enums, enum_name); if (enum_json == nullptr) { // first entry in a new enum enum_json = new Util::JsonObject(); - enum_json->emplace("name"_cs, enum_name); + enum_json->emplace("name", enum_name); auto entries = insert_array_field(enum_json, "entries"_cs); auto entry = new Util::JsonArray(); entry->append(entry_name); @@ -267,7 +267,7 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, enums->append(enum_json); LOG3("new enum object: " << enum_name << " " << entry_name << " " << entry_value); } else { // add entry to existing enum - auto entries = enum_json->get("entries"_cs)->to(); + auto entries = enum_json->getAs("entries"); auto entry = new Util::JsonArray(); entry->append(entry_name); entry->append(entry_value); @@ -279,11 +279,11 @@ void JsonObjects::add_enum(const cstring &enum_name, const cstring &entry_name, unsigned JsonObjects::add_parser(const cstring &name) { auto parser = new Util::JsonObject(); unsigned id = BMV2::nextId("parser"_cs); - parser->emplace("name"_cs, name); - parser->emplace("id"_cs, id); - parser->emplace("init_state"_cs, IR::ParserState::start); + parser->emplace("name", name); + parser->emplace("id", id); + parser->emplace("init_state", IR::ParserState::start); auto parse_states = new Util::JsonArray(); - parser->emplace("parse_states"_cs, parse_states); + parser->emplace("parse_states", parse_states); parsers->append(parser); map_parser.emplace(id, parser); @@ -293,18 +293,18 @@ unsigned JsonObjects::add_parser(const cstring &name) { unsigned JsonObjects::add_parser_state(const unsigned parser_id, const cstring &state_name) { if (map_parser.find(parser_id) == map_parser.end()) BUG("parser %1% not found.", parser_id); auto parser = map_parser[parser_id]; - auto states = parser->get("parse_states"_cs)->to(); + auto states = parser->getAs("parse_states"); auto state = new Util::JsonObject(); unsigned state_id = BMV2::nextId("parse_states"_cs); - state->emplace("name"_cs, state_name); - state->emplace("id"_cs, state_id); + state->emplace("name", state_name); + state->emplace("id", state_id); auto operations = new Util::JsonArray(); - state->emplace("parser_ops"_cs, operations); + state->emplace("parser_ops", operations); auto transitions = new Util::JsonArray(); - state->emplace("transitions"_cs, transitions); + state->emplace("transitions", transitions); states->append(state); auto key = new Util::JsonArray(); - state->emplace("transition_key"_cs, key); + state->emplace("transition_key", key); map_parser_state.emplace(state_id, state); return state_id; @@ -314,7 +314,7 @@ void JsonObjects::add_parser_transition(const unsigned state_id, Util::IJson *tr if (map_parser_state.find(state_id) == map_parser_state.end()) BUG("parser state %1% not found.", state_id); auto state = map_parser_state[state_id]; - auto transitions = state->get("transitions"_cs)->to(); + auto transitions = state->getAs("transitions"); CHECK_NULL(transitions); auto trans = transition->to(); CHECK_NULL(trans); @@ -325,7 +325,7 @@ void JsonObjects::add_parser_op(const unsigned state_id, Util::IJson *op) { if (map_parser_state.find(state_id) == map_parser_state.end()) BUG("parser state %1% not found.", state_id); auto state = map_parser_state[state_id]; - auto statements = state->get("parser_ops"_cs)->to(); + auto statements = state->getAs("parser_ops"); CHECK_NULL(statements); statements->append(op); } @@ -333,7 +333,7 @@ void JsonObjects::add_parser_op(const unsigned state_id, Util::IJson *op) { void JsonObjects::add_parser_transition_key(const unsigned state_id, Util::IJson *newKey) { if (map_parser_state.find(state_id) != map_parser_state.end()) { auto state = map_parser_state[state_id]; - auto keys = state->get("transition_key"_cs)->to(); + auto keys = state->getAs("transition_key"); CHECK_NULL(keys); auto new_keys = newKey->to(); for (auto k : *new_keys) { @@ -346,10 +346,10 @@ void JsonObjects::add_parse_vset(const cstring &name, const unsigned bitwidth, const big_int &size) { auto parse_vset = new Util::JsonObject(); unsigned id = BMV2::nextId("parse_vsets"_cs); - parse_vset->emplace("name"_cs, name); - parse_vset->emplace("id"_cs, id); - parse_vset->emplace("compressed_bitwidth"_cs, bitwidth); - parse_vset->emplace("max_size"_cs, size); + parse_vset->emplace("name", name); + parse_vset->emplace("id", id); + parse_vset->emplace("compressed_bitwidth", bitwidth); + parse_vset->emplace("max_size", size); parse_vsets->append(parse_vset); } @@ -358,11 +358,11 @@ unsigned JsonObjects::add_action(const cstring &name, Util::JsonArray *¶ms, CHECK_NULL(params); CHECK_NULL(body); auto action = new Util::JsonObject(); - action->emplace("name"_cs, name); + action->emplace("name", name); unsigned id = BMV2::nextId("actions"_cs); - action->emplace("id"_cs, id); - action->emplace("runtime_data"_cs, params); - action->emplace("primitives"_cs, body); + action->emplace("id", id); + action->emplace("runtime_data", params); + action->emplace("primitives", body); actions->append(action); return id; } @@ -370,9 +370,9 @@ unsigned JsonObjects::add_action(const cstring &name, Util::JsonArray *¶ms, void JsonObjects::add_extern_attribute(const cstring &name, const cstring &type, const cstring &value, Util::JsonArray *attributes) { auto attr = new Util::JsonObject(); - attr->emplace("name"_cs, name); - attr->emplace("type"_cs, type); - attr->emplace("value"_cs, value); + attr->emplace("name", name); + attr->emplace("type", type); + attr->emplace("value", value); attributes->append(attr); } @@ -380,10 +380,10 @@ void JsonObjects::add_extern(const cstring &name, const cstring &type, Util::JsonArray *attributes) { auto extn = new Util::JsonObject(); unsigned id = BMV2::nextId("extern_instances"_cs); - extn->emplace("name"_cs, name); - extn->emplace("id"_cs, id); - extn->emplace("type"_cs, type); - extn->emplace("attribute_values"_cs, attributes); + extn->emplace("name", name); + extn->emplace("id", id); + extn->emplace("type", type); + extn->emplace("attribute_values", attributes); externs->append(extn); } diff --git a/backends/bmv2/common/action.cpp b/backends/bmv2/common/action.cpp index 41af3497cc3..fb1d0a3769f 100644 --- a/backends/bmv2/common/action.cpp +++ b/backends/bmv2/common/action.cpp @@ -160,7 +160,7 @@ void ActionConverter::convertActionBody(const IR::Vector *body, BUG("%1%: Unexpected built-in method", s); } auto primitive = mkPrimitive(prim, result); - primitive->emplace("parameters"_cs, parameters); + primitive->emplace("parameters", parameters); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); continue; } else if (mi->is()) { @@ -192,14 +192,14 @@ void ActionConverter::convertActionParams(const IR::ParameterList *parameters, warn(ErrorType::WARN_UNUSED, "Unused action parameter %1%", p); auto param = new Util::JsonObject(); - param->emplace("name"_cs, p->externalName()); + param->emplace("name", p->externalName()); auto type = ctxt->typeMap->getType(p, true); // TODO: added IR::Type_Enum here to support PSA_MeterColor_t // should re-consider how to support action parameters that is neither bit<> nor int<> if (!(type->is() || type->is())) ::error(ErrorType::ERR_INVALID, "%1%: action parameters must be bit<> or int<> on this target", p); - param->emplace("bitwidth"_cs, type->width_bits()); + param->emplace("bitwidth", type->width_bits()); params->append(param); } } diff --git a/backends/bmv2/common/control.h b/backends/bmv2/common/control.h index f43d9ac36a9..ddd4ac008ea 100644 --- a/backends/bmv2/common/control.h +++ b/backends/bmv2/common/control.h @@ -48,8 +48,8 @@ class ControlConverter : public Inspector { LOG3("Processing " << dbp(table)); auto result = new Util::JsonObject(); cstring name = table->controlPlaneName(); - result->emplace("name"_cs, name); - result->emplace("id"_cs, nextId("tables"_cs)); + result->emplace("name", name); + result->emplace("id", nextId("tables"_cs)); result->emplace_non_null("source_info"_cs, table->sourceInfoJsonObj()); cstring table_match_type = corelib.exactMatch.name; auto key = table->getKey(); @@ -115,9 +115,9 @@ class ControlConverter : public Inspector { // represented in the BMv2 JSON file the same as a ternary // field would be. if (match_type == BMV2::MatchImplementation::optionalMatchTypeName) { - keyelement->emplace("match_type"_cs, corelib.ternaryMatch.name); + keyelement->emplace("match_type", corelib.ternaryMatch.name); } else { - keyelement->emplace("match_type"_cs, match_type); + keyelement->emplace("match_type", match_type); } if (auto na = ke->getAnnotation(IR::Annotation::nameAnnotation)) { BUG_CHECK(na->expr.size() == 1, "%1%: expected 1 name", na); @@ -125,21 +125,21 @@ class ControlConverter : public Inspector { BUG_CHECK(name != nullptr, "%1%: expected a string", na); // This is a BMv2 JSON extension: specify a // control-plane name for this key - keyelement->emplace("name"_cs, name->value); + keyelement->emplace("name", name->value); } auto jk = ctxt->conv->convert(expr); - keyelement->emplace("target"_cs, jk->to()->get("value"_cs)); + keyelement->emplace("target", jk->to()->get("value")); if (mask != 0) - keyelement->emplace("mask"_cs, + keyelement->emplace("mask", stringRepr(mask, ROUNDUP(expr->type->width_bits(), 8))); else - keyelement->emplace("mask"_cs, Util::JsonValue::null); + keyelement->emplace("mask", Util::JsonValue::null); tkey->append(keyelement); } } LOG3("table_match_type: " << table_match_type); - result->emplace("match_type"_cs, table_match_type); + result->emplace("match_type", table_match_type); ctxt->conv->simpleExpressionsOnly = false; auto propertyName = Standard::ActionProfileTraits::propertyName(); @@ -147,7 +147,7 @@ class ControlConverter : public Inspector { bool simple = handleTableImplementation(impl, key, result, action_profiles, selector_check); unsigned size = 0; - auto sz = table->properties->getProperty("size"_cs); + auto sz = table->properties->getProperty("size"); if (sz != nullptr) { if (sz->value->is()) { auto expr = sz->value->to()->expression; @@ -166,8 +166,8 @@ class ControlConverter : public Inspector { } if (size == 0) size = BMV2::TableAttributes::defaultTableSize; - result->emplace("max_size"_cs, size); - auto ctrs = table->properties->getProperty("counters"_cs); + result->emplace("max_size", size); + auto ctrs = table->properties->getProperty("counters"); if (ctrs != nullptr) { // The counters attribute should list the counters of the table, accessed in // actions of the table. We should be checking that this attribute and the @@ -194,14 +194,14 @@ class ControlConverter : public Inspector { } auto jctr = new Util::JsonObject(); cstring ctrname = ctrs->controlPlaneName("counter"_cs); - jctr->emplace("name"_cs, ctrname); - jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace("name", ctrname); + jctr->emplace("id", nextId("counter_arrays"_cs)); jctr->emplace_non_null("source_info"_cs, ctrs->sourceInfoJsonObj()); // TODO(jafingerhut) - what kind of P4_16 code causes this // code to run, if any? bool direct = te->name == "direct_counter"; - jctr->emplace("is_direct"_cs, direct); - jctr->emplace("binding"_cs, table->controlPlaneName()); + jctr->emplace("is_direct", direct); + jctr->emplace("binding", table->controlPlaneName()); ctxt->json->counters->append(jctr); } else if (expr->is()) { auto pe = expr->to(); @@ -226,13 +226,13 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a counter", ctrs); } } - result->emplace("with_counters"_cs, true); + result->emplace("with_counters", true); } else { - result->emplace("with_counters"_cs, false); + result->emplace("with_counters", false); } bool sup_to = false; - auto timeout = table->properties->getProperty("support_timeout"_cs); + auto timeout = table->properties->getProperty("support_timeout"); if (timeout != nullptr) { if (timeout->value->is()) { auto expr = timeout->value->to()->expression; @@ -245,9 +245,9 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a Boolean", timeout); } } - result->emplace("support_timeout"_cs, sup_to); + result->emplace("support_timeout", sup_to); - auto dm = table->properties->getProperty("meters"_cs); + auto dm = table->properties->getProperty("meters"); if (dm != nullptr) { if (dm->value->is()) { auto expr = dm->value->to()->expression; @@ -282,13 +282,13 @@ class ControlConverter : public Inspector { BUG_CHECK(decl->is(), "%1%: expected an instance", decl->getNode()); cstring name = decl->controlPlaneName(); - result->emplace("direct_meters"_cs, name); + result->emplace("direct_meters", name); } } else { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a meter", dm); } } else { - result->emplace("direct_meters"_cs, Util::JsonValue::null); + result->emplace("direct_meters", Util::JsonValue::null); } auto action_ids = mkArrayField(result, "action_ids"_cs); @@ -339,12 +339,12 @@ class ControlConverter : public Inspector { BUG_CHECK(nextDestination, "Could not find default destination for %1%", node->invocation); nextLabel = nodeName(nextDestination); - result->emplace("base_default_next"_cs, nextLabel); + result->emplace("base_default_next", nextLabel); // So if a "default:" switch case exists we set the nextLabel // to be the destination of the default: label. if (defaultLabelDestination != nullptr) nextLabel = nodeName(defaultLabelDestination); } else { - result->emplace("base_default_next"_cs, Util::JsonValue::null); + result->emplace("base_default_next", Util::JsonValue::null); } std::set labelsDone; @@ -374,7 +374,7 @@ class ControlConverter : public Inspector { } } - result->emplace("next_tables"_cs, next_tables); + result->emplace("next_tables", next_tables); auto defact = table->properties->getProperty(IR::TableProperties::defaultActionPropertyName); if (defact != nullptr) { @@ -411,8 +411,8 @@ class ControlConverter : public Inspector { unsigned actionid = get(ctxt->structure->ids, action, INVALID_ACTION_ID); BUG_CHECK(actionid != INVALID_ACTION_ID, "Could not find id for %1%", action); auto entry = new Util::JsonObject(); - entry->emplace("action_id"_cs, actionid); - entry->emplace("action_const"_cs, defact->isConstant); + entry->emplace("action_id", actionid); + entry->emplace("action_const", defact->isConstant); auto fields = mkArrayField(entry, "action_data"_cs); if (args != nullptr) { // TODO: use argument names @@ -427,8 +427,8 @@ class ControlConverter : public Inspector { } } } - entry->emplace("action_entry_const"_cs, defact->isConstant); - result->emplace("default_entry"_cs, entry); + entry->emplace("action_entry_const", defact->isConstant); + result->emplace("default_entry", entry); } convertTableEntries(table, result); return result; @@ -456,16 +456,16 @@ class ControlConverter : public Inspector { // represented in the BMv2 JSON file the same as a ternary // field would be. if (matchType == "optional") { - key->emplace("match_type"_cs, "ternary"); + key->emplace("match_type", "ternary"); } else { - key->emplace("match_type"_cs, matchType); + key->emplace("match_type", matchType); } if (matchType == corelib.exactMatch.name) { if (k->is()) - key->emplace("key"_cs, stringRepr(k->to()->value, k8)); + key->emplace("key", stringRepr(k->to()->value, k8)); else if (k->is()) // booleans are converted to ints - key->emplace("key"_cs, + key->emplace("key", stringRepr(k->to()->value ? 1 : 0, k8)); else ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported exact key expression", @@ -473,15 +473,14 @@ class ControlConverter : public Inspector { } else if (matchType == corelib.ternaryMatch.name) { if (k->is()) { auto km = k->to(); - key->emplace("key"_cs, stringRepr(km->left->to()->value, k8)); - key->emplace("mask"_cs, - stringRepr(km->right->to()->value, k8)); + key->emplace("key", stringRepr(km->left->to()->value, k8)); + key->emplace("mask", stringRepr(km->right->to()->value, k8)); } else if (k->is()) { - key->emplace("key"_cs, stringRepr(k->to()->value, k8)); - key->emplace("mask"_cs, stringRepr(Util::mask(keyWidth), k8)); + key->emplace("key", stringRepr(k->to()->value, k8)); + key->emplace("mask", stringRepr(Util::mask(keyWidth), k8)); } else if (k->is()) { - key->emplace("key"_cs, stringRepr(0, k8)); - key->emplace("mask"_cs, stringRepr(0, k8)); + key->emplace("key", stringRepr(0, k8)); + key->emplace("mask", stringRepr(0, k8)); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported ternary key expression", k); @@ -489,7 +488,7 @@ class ControlConverter : public Inspector { } else if (matchType == corelib.lpmMatch.name) { if (k->is()) { auto km = k->to(); - key->emplace("key"_cs, stringRepr(km->left->to()->value, k8)); + key->emplace("key", stringRepr(km->left->to()->value, k8)); auto trailing_zeros = [](unsigned long n, unsigned long keyWidth) { return n ? __builtin_ctzl(n) : static_cast(keyWidth); }; @@ -502,13 +501,13 @@ class ControlConverter : public Inspector { if (len + count_ones(mask) != keyWidth) // any remaining 0s in the prefix? ::error(ErrorType::ERR_INVALID, "%1%: invalid mask for LPM key", k); else - key->emplace("prefix_length"_cs, keyWidth - len); + key->emplace("prefix_length", keyWidth - len); } else if (k->is()) { - key->emplace("key"_cs, stringRepr(k->to()->value, k8)); - key->emplace("prefix_length"_cs, keyWidth); + key->emplace("key", stringRepr(k->to()->value, k8)); + key->emplace("prefix_length", keyWidth); } else if (k->is()) { - key->emplace("key"_cs, stringRepr(0, k8)); - key->emplace("prefix_length"_cs, 0); + key->emplace("key", stringRepr(0, k8)); + key->emplace("prefix_length", 0); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported LPM key expression", k); @@ -516,16 +515,14 @@ class ControlConverter : public Inspector { } else if (matchType == "range") { if (k->is()) { auto kr = k->to(); - key->emplace("start"_cs, - stringRepr(kr->left->to()->value, k8)); - key->emplace("end"_cs, - stringRepr(kr->right->to()->value, k8)); + key->emplace("start", stringRepr(kr->left->to()->value, k8)); + key->emplace("end", stringRepr(kr->right->to()->value, k8)); } else if (k->is()) { - key->emplace("start"_cs, stringRepr(k->to()->value, k8)); - key->emplace("end"_cs, stringRepr(k->to()->value, k8)); + key->emplace("start", stringRepr(k->to()->value, k8)); + key->emplace("end", stringRepr(k->to()->value, k8)); } else if (k->is()) { - key->emplace("start"_cs, stringRepr(0, k8)); - key->emplace("end"_cs, stringRepr((1 << keyWidth) - 1, k8)); // 2^N -1 + key->emplace("start", stringRepr(0, k8)); + key->emplace("end", stringRepr((1 << keyWidth) - 1, k8)); // 2^N -1 } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1% unsupported range key expression", k); @@ -539,11 +536,11 @@ class ControlConverter : public Inspector { // allow exact values or a DefaultExpression (_ or // default), no &&& expression. if (k->is()) { - key->emplace("key"_cs, stringRepr(k->to()->value, k8)); - key->emplace("mask"_cs, stringRepr(Util::mask(keyWidth), k8)); + key->emplace("key", stringRepr(k->to()->value, k8)); + key->emplace("mask", stringRepr(Util::mask(keyWidth), k8)); } else if (k->is()) { - key->emplace("key"_cs, stringRepr(0, k8)); - key->emplace("mask"_cs, stringRepr(0, k8)); + key->emplace("key", stringRepr(0, k8)); + key->emplace("mask", stringRepr(0, k8)); } else { ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupported optional key expression", k); @@ -566,12 +563,12 @@ class ControlConverter : public Inspector { auto actionDecl = decl->to(); unsigned id = get(ctxt->structure->ids, actionDecl, INVALID_ACTION_ID); BUG_CHECK(id != INVALID_ACTION_ID, "Could not find id for %1%", actionDecl); - action->emplace("action_id"_cs, id); + action->emplace("action_id", id); auto actionData = mkArrayField(action, "action_data"_cs); for (auto arg : *actionCall->arguments) { actionData->append(stringRepr(arg->expression->to()->value, 0)); } - entry->emplace("action_entry"_cs, action); + entry->emplace("action_entry", action); auto priorityAnnotation = e->getAnnotation("priority"_cs); if (priorityAnnotation != nullptr) { @@ -582,9 +579,9 @@ class ControlConverter : public Inspector { if (!priValue->is()) ::error(ErrorType::ERR_INVALID, "Invalid priority value %1%; must be constant.", priorityAnnotation->expr); - entry->emplace("priority"_cs, priValue->to()->value); + entry->emplace("priority", priValue->to()->value); } else { - entry->emplace("priority"_cs, entryPriority); + entry->emplace("priority", entryPriority); } entryPriority += 1; @@ -610,7 +607,7 @@ class ControlConverter : public Inspector { Util::JsonObject *table, Util::JsonArray *action_profiles, BMV2::SharedActionSelectorCheck *) { if (implementation == nullptr) { - table->emplace("type"_cs, "simple"); + table->emplace("type", "simple"); return true; } @@ -640,8 +637,8 @@ class ControlConverter : public Inspector { apname = implementation->controlPlaneName(ctxt->refMap->newName("action_profile")); action_profile = new Util::JsonObject(); action_profiles->append(action_profile); - action_profile->emplace("name"_cs, apname); - action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace("name", apname); + action_profile->emplace("id", nextId("action_profiles"_cs)); action_profile->emplace_non_null("source_info"_cs, propv->expression->sourceInfoJsonObj()); // TODO(jafingerhut) - add line/col here? @@ -656,7 +653,7 @@ class ControlConverter : public Inspector { } else { size = size_expr->to()->asInt(); } - action_profile->emplace("max_size"_cs, size); + action_profile->emplace("max_size", size); }; auto actionSelectorName = Standard::ActionSelectorTraits::typeName(); @@ -664,7 +661,7 @@ class ControlConverter : public Inspector { BUG_CHECK(arguments->size() == 3, "%1%: expected 3 arguments", arguments); isSimpleTable = false; auto selector = new Util::JsonObject(); - table->emplace("type"_cs, "indirect_ws"); + table->emplace("type", "indirect_ws"); action_profile->emplace("selector"_cs, selector); add_size(1); auto hash = arguments->at(0)->expression; @@ -674,7 +671,7 @@ class ControlConverter : public Inspector { hash); } else { cstring algo = ei->name; - selector->emplace("algo"_cs, algo); + selector->emplace("algo", algo); } auto input = mkArrayField(selector, "input"_cs); for (auto ke : key->keyElements) { @@ -690,7 +687,7 @@ class ControlConverter : public Inspector { } else if (implementationType->name == Standard::ActionProfileTraits::typeName()) { isSimpleTable = false; - table->emplace("type"_cs, "indirect"); + table->emplace("type", "indirect"); add_size(0); } else { ::error(ErrorType::ERR_UNEXPECTED, "%1%: expected value for property", propv); @@ -713,9 +710,9 @@ class ControlConverter : public Inspector { auto actionProfileName = Standard::ActionProfileTraits::typeName(); auto actionSelectorName = Standard::ActionSelectorTraits::typeName(); if (type_extern_name == actionProfileName) { - table->emplace("type"_cs, "indirect"); + table->emplace("type", "indirect"); } else if (type_extern_name == actionSelectorName) { - table->emplace("type"_cs, "indirect_ws"); + table->emplace("type", "indirect_ws"); } else { ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected type for implementation", dcltype); @@ -732,15 +729,15 @@ class ControlConverter : public Inspector { ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected value for property", propv); return false; } - table->emplace("action_profile"_cs, apname); + table->emplace("action_profile", apname); return isSimpleTable; } Util::IJson *convertIf(const CFG::IfNode *node, cstring prefix) { (void)prefix; auto result = new Util::JsonObject(); - result->emplace("name"_cs, node->name); - result->emplace("id"_cs, nextId("conditionals"_cs)); + result->emplace("name", node->name); + result->emplace("id", nextId("conditionals"_cs)); result->emplace_non_null("source_info"_cs, node->statement->condition->sourceInfoJsonObj()); auto j = ctxt->conv->convert(node->statement->condition, true, false); CHECK_NULL(j); @@ -759,8 +756,8 @@ class ControlConverter : public Inspector { bool preorder(const IR::P4Control *cont) override { auto result = new Util::JsonObject(); - result->emplace("name"_cs, name); - result->emplace("id"_cs, nextId("control"_cs)); + result->emplace("name", name); + result->emplace("id", nextId("control"_cs)); result->emplace_non_null("source_info"_cs, cont->sourceInfoJsonObj()); auto cfg = new CFG(); @@ -769,12 +766,12 @@ class ControlConverter : public Inspector { if (!success) return false; if (cfg->entryPoint->successors.size() == 0) { - result->emplace("init_table"_cs, Util::JsonValue::null); + result->emplace("init_table", Util::JsonValue::null); } else { BUG_CHECK(cfg->entryPoint->successors.size() == 1, "Expected 1 start node for %1%", cont); auto start = (*(cfg->entryPoint->successors.edges.begin()))->endpoint; - result->emplace("init_table"_cs, nodeName(start)); + result->emplace("init_table", nodeName(start)); } auto tables = mkArrayField(result, "tables"_cs); diff --git a/backends/bmv2/common/deparser.cpp b/backends/bmv2/common/deparser.cpp index bbd7b9d75a7..5ecc06482c3 100644 --- a/backends/bmv2/common/deparser.cpp +++ b/backends/bmv2/common/deparser.cpp @@ -61,7 +61,7 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo auto json = new Util::JsonObject(); auto params = mkArrayField(json, "parameters"_cs); auto type = ctxt->typeMap->getType(assign->left, true); - json->emplace("op"_cs, "set"); + json->emplace("op", "set"); auto l = ctxt->conv->convertLeftValue(assign->left); bool convertBool = type->is(); auto r = ctxt->conv->convert(assign->right, true, true, convertBool); @@ -85,7 +85,7 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo auto type = ctxt->typeMap->getType(arg, true); if (type->is()) { auto j = ctxt->conv->convert(arg->expression); - auto val = j->to()->get("value"_cs); + auto val = j->to()->get("value"); order->append(val); } else { // We don't need to handle other types, @@ -132,8 +132,8 @@ void DeparserConverter::convertDeparserBody(const IR::Vector *bo Util::IJson *DeparserConverter::convertDeparser(const IR::P4Control *ctrl) { auto result = new Util::JsonObject(); - result->emplace("name"_cs, name); - result->emplace("id"_cs, nextId("deparser"_cs)); + result->emplace("name", name); + result->emplace("id", nextId("deparser"_cs)); result->emplace_non_null("source_info"_cs, ctrl->sourceInfoJsonObj()); auto order = mkArrayField(result, "order"_cs); auto primitives = mkArrayField(result, "primitives"_cs); diff --git a/backends/bmv2/common/expression.cpp b/backends/bmv2/common/expression.cpp index f7de266ee2e..d1cd1113830 100644 --- a/backends/bmv2/common/expression.cpp +++ b/backends/bmv2/common/expression.cpp @@ -99,8 +99,8 @@ Util::IJson *ExpressionConverter::get(const IR::Expression *expression) const { void ExpressionConverter::postorder(const IR::BoolLiteral *expression) { auto result = new Util::JsonObject(); - result->emplace("type"_cs, "bool"); - result->emplace("value"_cs, expression->value); + result->emplace("type", "bool"); + result->emplace("value", expression->value); mapExpression(expression, result); } @@ -116,7 +116,7 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) int width = typearg->width_bits(); BUG_CHECK(width > 0, "%1%: unknown width", targ); auto j = new Util::JsonObject(); - j->emplace("type"_cs, "lookahead"); + j->emplace("type", "lookahead"); auto v = mkArrayField(j, "value"_cs); v->append(0); v->append(width); @@ -130,18 +130,18 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) auto l = get(bim->appliedTo); if (!l) return; if (type->is()) { - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "valid_union"); - e->emplace("left"_cs, Util::JsonValue::null); - e->emplace("right"_cs, l); + result->emplace("value", e); + e->emplace("op", "valid_union"); + e->emplace("left", Util::JsonValue::null); + e->emplace("right", l); } else { // Treat this as appliedTo.$valid$ - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto e = mkArrayField(result, "value"_cs); if (l->is()) - e->append(l->to()->get("value"_cs)); + e->append(l->to()->get("value")); else e->append(l); e->append(V1ModelProperties::validField); @@ -150,11 +150,11 @@ void ExpressionConverter::postorder(const IR::MethodCallExpression *expression) // for table keys we don't need the casts. auto cast = new Util::JsonObject(); auto value = new Util::JsonObject(); - cast->emplace("type"_cs, "expression"); - cast->emplace("value"_cs, value); - value->emplace("op"_cs, "d2b"); // data to Boolean cast - value->emplace("left"_cs, Util::JsonValue::null); - value->emplace("right"_cs, result); + cast->emplace("type", "expression"); + cast->emplace("value", value); + value->emplace("op", "d2b"); // data to Boolean cast + value->emplace("left", Util::JsonValue::null); + value->emplace("right", result); result = cast; } } @@ -175,11 +175,11 @@ void ExpressionConverter::postorder(const IR::Cast *expression) { void ExpressionConverter::postorder(const IR::Constant *expression) { auto result = new Util::JsonObject(); - result->emplace("type"_cs, "hexstr"); + result->emplace("type", "hexstr"); auto bitwidth = expression->type->width_bits(); cstring repr = stringRepr(expression->value, ROUNDUP(bitwidth, 8)); - result->emplace("value"_cs, repr); - if (withConstantWidths) result->emplace("bitwidth"_cs, bitwidth); + result->emplace("value", repr); + if (withConstantWidths) result->emplace("bitwidth", bitwidth); mapExpression(expression, result); } @@ -213,21 +213,21 @@ void ExpressionConverter::postorder(const IR::ArrayIndex *expression) { } BUG_CHECK(fresult, "%1%: Runtime array index json generation failed", ex); Util::JsonObject *fres = fresult->to(); - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - e->emplace("op"_cs, "dereference_header_stack"); + e->emplace("op", "dereference_header_stack"); auto l = new Util::JsonObject(); - l->emplace("type"_cs, "header_stack"); - l->emplace("value"_cs, elementAccess); - e->emplace("left"_cs, l); - e->emplace("right"_cs, fres); - result->emplace("value"_cs, e); + l->emplace("type", "header_stack"); + l->emplace("value", elementAccess); + e->emplace("left", l); + e->emplace("right", fres); + result->emplace("value", e); } else { - result->emplace("type"_cs, "header"); + result->emplace("type", "header"); int index = expression->right->to()->asInt(); elementAccess += "[" + Util::toString(index) + "]"; - result->emplace("value"_cs, elementAccess); + result->emplace("value", elementAccess); } mapExpression(expression, result); } @@ -266,12 +266,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { // handle error if (type->is() && expression->expr->is()) { // this deals with constants that have type 'error' - result->emplace("type"_cs, "hexstr"); + result->emplace("type", "hexstr"); auto decl = type->to()->getDeclByName(expression->member.name); auto errorValue = structure->errorCodesMap.at(decl); // this generates error constant like hex value auto reprValue = stringRepr(errorValue); - result->emplace("value"_cs, reprValue); + result->emplace("value", reprValue); mapExpression(expression, result); return; } @@ -287,27 +287,27 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (auto st = type->to()) { auto et = typeMap->getTypeType(st->elementType, true); if (et->is()) - result->emplace("type"_cs, "header_union_stack"); + result->emplace("type", "header_union_stack"); else - result->emplace("type"_cs, "header_stack"); - result->emplace("value"_cs, fieldName); + result->emplace("type", "header_stack"); + result->emplace("value", fieldName); } else if (type->is()) { - result->emplace("type"_cs, "header_union"); - result->emplace("value"_cs, fieldName); + result->emplace("type", "header_union"); + result->emplace("value", fieldName); } else if (parentType->is()) { auto l = get(expression->expr); if (!l) return; cstring nestedField = fieldName; if (auto lv = l->to()) { - lv->get("value"_cs); + lv->get("value"); if (lv->is()) { // header in union reference ["u", "f"] => "u.f" cstring prefix = lv->to()->getString(); nestedField = prefix + "." + nestedField; } } - result->emplace("type"_cs, "header"); - result->emplace("value"_cs, nestedField); + result->emplace("type", "header"); + result->emplace("value", nestedField); } else if (parentType->is() && (type->is() || type->is() || type->is())) { @@ -318,7 +318,7 @@ void ExpressionConverter::postorder(const IR::Member *expression) { BUG_CHECK((name != nullptr), "NULL name: %1%", field->name); if (type->is() || type->is() || leftValue || simpleExpressionsOnly) { - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto e = mkArrayField(result, "value"_cs); e->append(scalarsName); e->append(name); @@ -326,15 +326,15 @@ void ExpressionConverter::postorder(const IR::Member *expression) { // Boolean variables are stored as ints, so we // have to insert a conversion when reading such a // variable - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "d2b"); // data to Boolean cast - e->emplace("left"_cs, Util::JsonValue::null); + result->emplace("value", e); + e->emplace("op", "d2b"); // data to Boolean cast + e->emplace("left", Util::JsonValue::null); auto r = new Util::JsonObject(); - e->emplace("right"_cs, r); + e->emplace("right", r); - r->emplace("type"_cs, "field"); + r->emplace("type", "field"); auto a = mkArrayField(r, "value"_cs); a->append(scalarsName); a->append(name); @@ -342,8 +342,8 @@ void ExpressionConverter::postorder(const IR::Member *expression) { } else { // This may be wrong, but the caller will handle it properly // (e.g., this can be a method, such as packet.lookahead) - result->emplace("type"_cs, "header"); - result->emplace("value"_cs, fieldName); + result->emplace("type", "header"); + result->emplace("value", fieldName); } mapExpression(expression, result); return; @@ -359,10 +359,10 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (memtype->is() && mem->member == IR::Type_Stack::last) { auto l = get(mem->expr); if (!l) return; - result->emplace("type"_cs, "stack_field"); + result->emplace("type", "stack_field"); auto e = mkArrayField(result, "value"_cs); if (l->is()) - e->append(l->to()->get("value"_cs)); + e->append(l->to()->get("value")); else e->append(l); e->append(fieldName); @@ -375,18 +375,18 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (!l) return; if (parentType->is()) { BUG_CHECK(l->is(), "Not a JsonObject"); - auto lv = l->to()->get("value"_cs); + auto lv = l->to()->get("value"); if (lv->is()) { fieldName = lv->to()->getString() + "." + fieldName; // Each header in a union is allocated a separate header instance. // Refer to that instance directly. - result->emplace("type"_cs, "header"); - result->emplace("value"_cs, fieldName); + result->emplace("type", "header"); + result->emplace("value", fieldName); } else { // lv must be a reference to a union stack field auto a = lv->to()->clone(); CHECK_NULL(a); - result->emplace("type"_cs, "union_stack_field"); + result->emplace("type", "union_stack_field"); a->append(fieldName); result->emplace("value"_cs, a); } @@ -394,23 +394,23 @@ void ExpressionConverter::postorder(const IR::Member *expression) { expression->member == IR::Type_Stack::lastIndex) { auto l = get(expression->expr); if (!l) return; - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "last_stack_index"); - e->emplace("left"_cs, Util::JsonValue::null); - e->emplace("right"_cs, l); + result->emplace("value", e); + e->emplace("op", "last_stack_index"); + e->emplace("left", Util::JsonValue::null); + e->emplace("right", l); } else { const char *fieldRef = parentType->is() ? "stack_field" : "field"; Util::JsonArray *e = nullptr; bool st = isArrayIndexRuntime(expression); if (!st) { - result->emplace("type"_cs, fieldRef); + result->emplace("type", fieldRef); e = mkArrayField(result, "value"_cs); } if (l->is()) { - auto lv = l->to()->get("value"_cs); + auto lv = l->to()->get("value"); if (lv->is()) { // TODO: is this case still necessary after eliminating nested structs? // nested struct reference [ ["m", "f"], "x" ] => [ "m", "f.x" ] @@ -436,12 +436,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { "for runtime index computation %1%", st); } - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "access_field"); - e->emplace("left"_cs, jo); - e->emplace("right"_cs, index_pos); + result->emplace("value", e); + e->emplace("op", "access_field"); + e->emplace("left", jo); + e->emplace("right", index_pos); } } else { BUG("%1%: Unexpected json", lv); @@ -454,11 +454,11 @@ void ExpressionConverter::postorder(const IR::Member *expression) { if (!simpleExpressionsOnly && !leftValue && type->is()) { auto cast = new Util::JsonObject(); auto value = new Util::JsonObject(); - cast->emplace("type"_cs, "expression"); - cast->emplace("value"_cs, value); - value->emplace("op"_cs, "d2b"); // data to Boolean cast - value->emplace("left"_cs, Util::JsonValue::null); - value->emplace("right"_cs, result); + cast->emplace("type", "expression"); + cast->emplace("value", value); + value->emplace("op", "d2b"); // data to Boolean cast + value->emplace("left", Util::JsonValue::null); + value->emplace("right", result); result = cast; } } @@ -469,12 +469,12 @@ void ExpressionConverter::postorder(const IR::Member *expression) { Util::IJson *ExpressionConverter::fixLocal(Util::IJson *json) { if (!json) return new Util::JsonValue(); // null if (auto jo = json->to()) { - auto to = jo->get("type"_cs); + auto to = jo->get("type"); if (to != nullptr && to->to() != nullptr && (*to->to()) == "runtime_data") { auto result = new Util::JsonObject(); - result->emplace("type"_cs, "local"); - result->emplace("value"_cs, jo->get("value"_cs)); + result->emplace("type", "local"); + result->emplace("value", jo->get("value")); return result; } } @@ -490,10 +490,10 @@ void ExpressionConverter::postorder(const IR::Mux *expression) { return; } - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "?"); + result->emplace("value", e); + e->emplace("op", "?"); auto l = get(expression->e1); if (!l) return; e->emplace("left"_cs, fixLocal(l)); @@ -508,18 +508,18 @@ void ExpressionConverter::postorder(const IR::Mux *expression) { void ExpressionConverter::postorder(const IR::IntMod *expression) { auto result = new Util::JsonObject(); mapExpression(expression, result); - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "two_comp_mod"); + result->emplace("value", e); + e->emplace("op", "two_comp_mod"); auto l = get(expression->expr); if (!l) return; - e->emplace("left"_cs, fixLocal(l)); + e->emplace("left", fixLocal(l)); auto r = new Util::JsonObject(); - r->emplace("type"_cs, "hexstr"); + r->emplace("type", "hexstr"); cstring repr = stringRepr(expression->width); - r->emplace("value"_cs, repr); - e->emplace("right"_cs, r); + r->emplace("value", repr); + e->emplace("right", r); } void ExpressionConverter::postorder(const IR::Operation_Binary *expression) { binary(expression); } @@ -533,21 +533,21 @@ void ExpressionConverter::binary(const IR::Operation_Binary *expression) { return; } - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); + result->emplace("value", e); cstring op = expression->getStringOp(); if (op == "&&") op = "and"_cs; else if (op == "||") op = "or"_cs; - e->emplace("op"_cs, op); + e->emplace("op", op); auto l = get(expression->left); if (!l) return; - e->emplace("left"_cs, fixLocal(l)); + e->emplace("left", fixLocal(l)); auto r = get(expression->right); if (!r) return; - e->emplace("right"_cs, fixLocal(r)); + e->emplace("right", fixLocal(r)); } void ExpressionConverter::saturated_binary(const IR::Operation_Binary *expression) { @@ -556,30 +556,30 @@ void ExpressionConverter::saturated_binary(const IR::Operation_Binary *expressio auto result = new Util::JsonObject(); mapExpression(expression, result); - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); + result->emplace("value", e); auto eType = expression->type->to(); CHECK_NULL(eType); auto opType = eType->isSigned ? "sat_cast" : "usat_cast"; - e->emplace("op"_cs, opType); + e->emplace("op", opType); // the left operand is the binary expression, but as a simple add/sub auto eLeft = new Util::JsonObject(); - eLeft->emplace("type"_cs, "expression"); + eLeft->emplace("type", "expression"); auto e1 = new Util::JsonObject(); - e1->emplace("op"_cs, expression->getStringOp() == "|+|" ? "+" : "-"); - e1->emplace("left"_cs, fixLocal(get(expression->left))); - e1->emplace("right"_cs, fixLocal(get(expression->right))); - eLeft->emplace("value"_cs, e1); - e->emplace("left"_cs, eLeft); + e1->emplace("op", expression->getStringOp() == "|+|" ? "+" : "-"); + e1->emplace("left", fixLocal(get(expression->left))); + e1->emplace("right", fixLocal(get(expression->right))); + eLeft->emplace("value", e1); + e->emplace("left", eLeft); // the right operand is the width of the type auto r = new Util::JsonObject(); - r->emplace("type"_cs, "hexstr"); + r->emplace("type", "hexstr"); cstring repr = stringRepr(eType->width_bits()); - r->emplace("value"_cs, repr); - e->emplace("right"_cs, r); + r->emplace("value", repr); + e->emplace("right", r); } void ExpressionConverter::postorder(const IR::ListExpression *expression) { @@ -624,16 +624,16 @@ void ExpressionConverter::postorder(const IR::Operation_Unary *expression) { return; } - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); + result->emplace("value", e); cstring op = expression->getStringOp(); if (op == "!") op = "not"_cs; - e->emplace("op"_cs, op); - e->emplace("left"_cs, Util::JsonValue::null); + e->emplace("op", op); + e->emplace("left", Util::JsonValue::null); auto r = get(expression->expr); if (!r) return; - e->emplace("right"_cs, fixLocal(r)); + e->emplace("right", fixLocal(r)); } void ExpressionConverter::postorder(const IR::PathExpression *expression) { @@ -646,8 +646,8 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { auto result = convertParam(param, cstring::empty); if (result == nullptr) { auto r = new Util::JsonObject(); - r->emplace("type"_cs, "header"); - r->emplace("value"_cs, param->name.name); + r->emplace("type", "header"); + r->emplace("value", param->name.name); result = r; } mapExpression(expression, result); @@ -657,21 +657,21 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { return; } auto result = new Util::JsonObject(); - result->emplace("type"_cs, "runtime_data"); + result->emplace("type", "runtime_data"); unsigned paramIndex = ::get(&structure->index, param); - result->emplace("value"_cs, paramIndex); + result->emplace("value", paramIndex); mapExpression(expression, result); } else if (auto var = decl->to()) { LOG3("Variable to json " << var); auto result = new Util::JsonObject(); auto type = typeMap->getType(var, true); if (type->is()) { - result->emplace("type"_cs, "header"); - result->emplace("value"_cs, var->name); + result->emplace("type", "header"); + result->emplace("value", var->name); } else if (type->is() || (type->is() && (leftValue || simpleExpressionsOnly))) { // no conversion d2b when writing (leftValue is true) to a boolean - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto e = mkArrayField(result, "value"_cs); e->append(scalarsName); e->append(var->name); @@ -679,33 +679,33 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { // varbits are synthesized in separate metadata instances // with a single field each, where the field is named // "field". - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto e = mkArrayField(result, "value"_cs); e->append(var->name); e->append("field"); } else if (type->is()) { // Boolean variables are stored as ints, so we have to insert a conversion when // reading such a variable - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto e = new Util::JsonObject(); - result->emplace("value"_cs, e); - e->emplace("op"_cs, "d2b"); // data to Boolean cast - e->emplace("left"_cs, Util::JsonValue::null); + result->emplace("value", e); + e->emplace("op", "d2b"); // data to Boolean cast + e->emplace("left", Util::JsonValue::null); auto r = new Util::JsonObject(); - e->emplace("right"_cs, r); - r->emplace("type"_cs, "field"); + e->emplace("right", r); + r->emplace("type", "field"); auto f = mkArrayField(r, "value"_cs); f->append(scalarsName); f->append(var->name); } else if (auto st = type->to()) { auto et = typeMap->getTypeType(st->elementType, true); if (et->is()) - result->emplace("type"_cs, "header_union_stack"); + result->emplace("type", "header_union_stack"); else - result->emplace("type"_cs, "header_stack"); - result->emplace("value"_cs, var->name); + result->emplace("type", "header_stack"); + result->emplace("value", var->name); } else if (type->is()) { - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto f = mkArrayField(result, "value"_cs); f->append(scalarsName); f->append(var->name); @@ -718,8 +718,8 @@ void ExpressionConverter::postorder(const IR::PathExpression *expression) { void ExpressionConverter::postorder(const IR::StringLiteral *expression) { auto result = new Util::JsonObject(); - result->emplace("type"_cs, "string"); - result->emplace("value"_cs, expression->value); + result->emplace("type", "string"); + result->emplace("value", expression->value); mapExpression(expression, result); } @@ -731,14 +731,14 @@ void ExpressionConverter::postorder(const IR::Slice *expression) { int h = expression->getH(); int l = expression->getL(); auto mask = Util::maskFromSlice(h, l); - result->emplace("type"_cs, "expression"); + result->emplace("type", "expression"); auto band = new Util::JsonObject(); - result->emplace("value"_cs, band); - band->emplace("op"_cs, "&"); + result->emplace("value", band); + band->emplace("op", "&"); auto right = new Util::JsonObject(); auto bitwidth = expression->type->width_bits(); - right->emplace("type"_cs, "hexstr"); - right->emplace("value"_cs, stringRepr(mask, ROUNDUP(bitwidth, 8))); + right->emplace("type", "hexstr"); + right->emplace("value", stringRepr(mask, ROUNDUP(bitwidth, 8))); auto le = get(expr); if (!le) return; band->emplace("left"_cs, le); @@ -785,12 +785,12 @@ Util::IJson *ExpressionConverter::convert(const IR::Expression *e, bool doFixup, auto type = typeMap->getType(e, true); if (convertBool && type->is()) { auto obj = new Util::JsonObject(); - obj->emplace("type"_cs, "expression"); + obj->emplace("type", "expression"); auto conv = new Util::JsonObject(); - obj->emplace("value"_cs, conv); - conv->emplace("op"_cs, "b2d"); // boolean to data cast - conv->emplace("left"_cs, Util::JsonValue::null); - conv->emplace("right"_cs, result); + obj->emplace("value", conv); + conv->emplace("op", "b2d"); // boolean to data cast + conv->emplace("left", Util::JsonValue::null); + conv->emplace("right", result); result = obj; } @@ -800,12 +800,12 @@ Util::IJson *ExpressionConverter::convert(const IR::Expression *e, bool doFixup, // anymore as expressions will be treated in a more uniform way. if (wrap) { if (auto ro = result->to()) { - if (auto to = ro->get("type"_cs)) { + if (auto to = ro->get("type")) { if (auto jv = to->to()) { if (jv->isString() && to_wrap.find(jv->getString()) != to_wrap.end()) { auto rwrap = new Util::JsonObject(); - rwrap->emplace("type"_cs, "expression"); - rwrap->emplace("value"_cs, result); + rwrap->emplace("type", "expression"); + rwrap->emplace("value", result); result = rwrap; } } diff --git a/backends/bmv2/common/extern.cpp b/backends/bmv2/common/extern.cpp index f7926b5bab6..a21331cbd03 100644 --- a/backends/bmv2/common/extern.cpp +++ b/backends/bmv2/common/extern.cpp @@ -17,6 +17,7 @@ limitations under the License. #include "extern.h" #include "frontends/p4/fromv1.0/v1model.h" +#include "lib/json.h" namespace BMV2 { @@ -62,8 +63,8 @@ Util::IJson *ExternConverter::convertExternObject(ConversionContext *ctxt, auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, mc->sourceInfoJsonObj()); auto etr = new Util::JsonObject(); - etr->emplace("type"_cs, "extern"); - etr->emplace("value"_cs, em->object->controlPlaneName()); + etr->emplace("type", "extern"); + etr->emplace("value", em->object->controlPlaneName()); parameters->append(etr); for (auto arg : *mc->arguments) { auto args = ctxt->conv->convert(arg->expression); @@ -161,14 +162,14 @@ void ExternConverter::addToFieldList(ConversionContext *ctxt, const IR::Expressi auto j = ctxt->conv->convert(expr); ctxt->conv->simpleExpressionsOnly = simple; // restore state if (auto jo = j->to()) { - if (auto t = jo->get("type"_cs)) { + if (auto t = jo->get("type")) { if (auto type = t->to()) { if (*type == "runtime_data") { // Can't have runtime_data in field lists -- need hexstr instead - auto val = jo->get("value"_cs)->to(); + auto val = jo->getAs("value"); j = jo = new Util::JsonObject(); - jo->emplace("type"_cs, "hexstr"); - jo->emplace("value"_cs, stringRepr(val->getValue())); + jo->emplace("type", "hexstr"); + jo->emplace("value", stringRepr(val->getValue())); } } } @@ -182,8 +183,8 @@ int ExternConverter::createFieldList(ConversionContext *ctxt, const IR::Expressi auto fl = new Util::JsonObject(); field_lists->append(fl); int id = nextId(group); - fl->emplace("id"_cs, id); - fl->emplace("name"_cs, listName); + fl->emplace("id", id); + fl->emplace("name", listName); fl->emplace_non_null("source_info"_cs, expr->sourceInfoJsonObj()); auto elements = mkArrayField(fl, "elements"_cs); addToFieldList(ctxt, expr, elements); @@ -196,11 +197,11 @@ cstring ExternConverter::createCalculation(ConversionContext *ctxt, cstring algo const IR::Node *sourcePositionNode = nullptr) { cstring calcName = ctxt->refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name"_cs, calcName); - calc->emplace("id"_cs, nextId("calculations"_cs)); + calc->emplace("name", calcName); + calc->emplace("id", nextId("calculations"_cs)); if (sourcePositionNode != nullptr) calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo"_cs, algo); + calc->emplace("algo", algo); fields = convertToList(fields, ctxt->typeMap); if (!fields) { modelError("%1%: expected a struct", fields); @@ -211,8 +212,8 @@ cstring ExternConverter::createCalculation(ConversionContext *ctxt, cstring algo auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type"_cs, "payload"); - payload->emplace("value"_cs, (Util::IJson *)nullptr); + payload->emplace("type", "payload"); + payload->emplace("value", (Util::IJson *)nullptr); array->append(payload); } calc->emplace("input"_cs, jright); diff --git a/backends/bmv2/common/helpers.cpp b/backends/bmv2/common/helpers.cpp index 15cc47bbe85..e2e2afd7de1 100644 --- a/backends/bmv2/common/helpers.cpp +++ b/backends/bmv2/common/helpers.cpp @@ -16,6 +16,8 @@ limitations under the License. #include "helpers.h" +#include "lib/json.h" + namespace BMV2 { /// constant definition for bmv2 @@ -45,14 +47,14 @@ Util::JsonArray *mkParameters(Util::JsonObject *object) { Util::JsonObject *mkPrimitive(cstring name, Util::JsonArray *appendTo) { auto result = new Util::JsonObject(); - result->emplace("op"_cs, name); + result->emplace("op", name); appendTo->append(result); return result; } Util::JsonObject *mkPrimitive(cstring name) { auto result = new Util::JsonObject(); - result->emplace("op"_cs, name); + result->emplace("op", name); return result; } @@ -109,14 +111,14 @@ void ConversionContext::addToFieldList(const IR::Expression *expr, Util::JsonArr auto j = conv->convert(expr); conv->simpleExpressionsOnly = simple; // restore state if (auto jo = j->to()) { - if (auto t = jo->get("type"_cs)) { + if (auto t = jo->get("type")) { if (auto type = t->to()) { if (*type == "runtime_data") { // Can't have runtime_data in field lists -- need hexstr instead - auto val = jo->get("value"_cs)->to(); + auto val = jo->getAs("value"); j = jo = new Util::JsonObject(); - jo->emplace("type"_cs, "hexstr"); - jo->emplace("value"_cs, stringRepr(val->getValue())); + jo->emplace("type", "hexstr"); + jo->emplace("value", stringRepr(val->getValue())); } } } @@ -135,8 +137,8 @@ int ConversionContext::createFieldList(const IR::Expression *expr, cstring listN json->field_lists->append(fl); } int id = nextId(group); - fl->emplace("id"_cs, id); - fl->emplace("name"_cs, listName); + fl->emplace("id", id); + fl->emplace("name", listName); fl->emplace_non_null("source_info"_cs, expr->sourceInfoJsonObj()); auto elements = mkArrayField(fl, "elements"_cs); addToFieldList(expr, elements); @@ -153,11 +155,11 @@ cstring ConversionContext::createCalculation(cstring algo, const IR::Expression const IR::Node *sourcePositionNode = nullptr) { cstring calcName = refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name"_cs, calcName); - calc->emplace("id"_cs, nextId("calculations"_cs)); + calc->emplace("name", calcName); + calc->emplace("id", nextId("calculations"_cs)); if (sourcePositionNode != nullptr) calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo"_cs, algo); + calc->emplace("algo", algo); auto listFields = convertToList(fields, typeMap); if (!listFields) { modelError("%1%: expected a struct", fields); @@ -168,11 +170,11 @@ cstring ConversionContext::createCalculation(cstring algo, const IR::Expression auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type"_cs, "payload"_cs); - payload->emplace("value"_cs, (Util::IJson *)nullptr); + payload->emplace("type", "payload"); + payload->emplace("value", (Util::IJson *)nullptr); array->append(payload); } - calc->emplace("input"_cs, jright); + calc->emplace("input", jright); calculations->append(calc); return calcName; } diff --git a/backends/bmv2/common/parser.cpp b/backends/bmv2/common/parser.cpp index 4f105f8c42d..59b85a32958 100644 --- a/backends/bmv2/common/parser.cpp +++ b/backends/bmv2/common/parser.cpp @@ -104,7 +104,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) auto assign = stat->to(); auto type = ctxt->typeMap->getType(assign->left, true); cstring operation = jsonAssignment(type); - result->emplace("op"_cs, operation); + result->emplace("op", operation); auto l = ctxt->conv->convertLeftValue(assign->left); bool convertBool = type->is(); auto r = ctxt->conv->convert(assign->right, true, true, convertBool); @@ -114,7 +114,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) if (operation != "set") { // must wrap into another outer object auto wrap = new Util::JsonObject(); - wrap->emplace("op"_cs, "primitive"); + wrap->emplace("op", "primitive"); auto params = mkParameters(wrap); params->append(result); result = wrap; @@ -135,7 +135,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) } cstring ename = argCount == 1 ? "extract"_cs : "extract_VL"_cs; - result->emplace("op"_cs, ename); + result->emplace("op", ename); auto arg = mce->arguments->at(0); auto argtype = ctxt->typeMap->getType(arg->expression, true); if (!argtype->is()) { @@ -173,13 +173,13 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) a = j->to()->clone(); } else if (j->is()) { a = new Util::JsonArray(); - a->push_back(j->to()->get("value"_cs)); + a->push_back(j->to()->get("value")); } else { BUG("unexpected"); } a->append(mem->member.name); auto j0 = new Util::JsonObject(); - j = j0->emplace("value"_cs, a); + j = j0->emplace("value", a); } else { BUG("%1%: unsupported", mem); } @@ -191,9 +191,9 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) type = "regular"_cs; j = ctxt->conv->convert(arg->expression); } - auto value = j->to()->get("value"_cs); - param->emplace("type"_cs, type); - param->emplace("value"_cs, value); + auto value = j->to()->get("value"); + param->emplace("type", type); + param->emplace("value", value); if (argCount == 2) { auto arg2 = mce->arguments->at(1); @@ -202,8 +202,8 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) // does not do that. auto jexpr = ctxt->conv->convert(arg2->expression, true, false); auto rwrap = new Util::JsonObject(); - rwrap->emplace("type"_cs, "expression"); - rwrap->emplace("value"_cs, jexpr); + rwrap->emplace("type", "expression"); + rwrap->emplace("value", jexpr); params->append(rwrap); } return result; @@ -218,7 +218,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) } auto arg = mce->arguments->at(0); auto jexpr = ctxt->conv->convert(arg->expression, true, false); - result->emplace("op"_cs, "advance"); + result->emplace("op", "advance"); params->append(jexpr); return result; } else if ((extmeth->originalExternType->name == "InternetChecksum" && @@ -236,7 +236,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) json = ExternConverter::cvtExternObject(ctxt, extmeth, mce, stat, true); } if (json) { - result->emplace("op"_cs, "primitive"); + result->emplace("op", "primitive"); params->append(json); } return result; @@ -245,7 +245,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) auto extfn = minst->to(); auto extFuncName = extfn->method->name.name; if (extFuncName == IR::ParserState::verify) { - result->emplace("op"_cs, "verify"); + result->emplace("op", "verify"); BUG_CHECK(mce->arguments->size() == 2, "%1%: Expected 2 arguments", mce); { auto cond = mce->arguments->at(0); @@ -264,19 +264,19 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) return result; } else if (extFuncName == "assert" || extFuncName == "assume") { BUG_CHECK(mce->arguments->size() == 1, "%1%: Expected 1 argument ", mce); - result->emplace("op"_cs, "primitive"); + result->emplace("op", "primitive"); auto paramValue = new Util::JsonObject(); params->append(paramValue); auto paramsArray = mkArrayField(paramValue, "parameters"_cs); auto cond = mce->arguments->at(0); auto expr = ctxt->conv->convert(cond->expression, true, true, true); paramsArray->append(expr); - paramValue->emplace("op"_cs, extFuncName); + paramValue->emplace("op", extFuncName); paramValue->emplace_non_null("source_info"_cs, mce->sourceInfoJsonObj()); } else if (extFuncName == P4V1::V1Model::instance.log_msg.name) { BUG_CHECK(mce->arguments->size() == 2 || mce->arguments->size() == 1, "%1%: Expected 1 or 2 arguments", mce); - result->emplace("op"_cs, "primitive"); + result->emplace("op", "primitive"); auto ef = minst->to(); auto ijson = ExternConverter::cvtExternFunction(ctxt, ef, mce, stat, false); params->append(ijson); @@ -293,7 +293,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) ], "op" : "primitive" } */ - result->emplace("op"_cs, "primitive"); + result->emplace("op", "primitive"); auto bi = minst->to(); cstring primitive; @@ -322,7 +322,7 @@ Util::IJson *ParserConverter::convertParserStatement(const IR::StatOrDecl *stat) BUG("%1%: Unexpected built-in method", bi->name); } - paramsValue->emplace("op"_cs, primitive); + paramsValue->emplace("op", primitive); return result; } } @@ -460,24 +460,24 @@ std::vector ParserConverter::convertSelectExpression( cstring vset_name; unsigned bytes = combine(sc->keyset, se->select, value, mask, is_vset, vset_name); if (is_vset) { - trans->emplace("type"_cs, "parse_vset"); - trans->emplace("value"_cs, vset_name); - trans->emplace("mask"_cs, Util::JsonValue::null); - trans->emplace("next_state"_cs, stateName(sc->state->path->name)); + trans->emplace("type", "parse_vset"); + trans->emplace("value", vset_name); + trans->emplace("mask", Util::JsonValue::null); + trans->emplace("next_state", stateName(sc->state->path->name)); } else { if (mask == 0) { - trans->emplace("type"_cs, "default"); - trans->emplace("value"_cs, Util::JsonValue::null); - trans->emplace("mask"_cs, Util::JsonValue::null); - trans->emplace("next_state"_cs, stateName(sc->state->path->name)); + trans->emplace("type", "default"); + trans->emplace("value", Util::JsonValue::null); + trans->emplace("mask", Util::JsonValue::null); + trans->emplace("next_state", stateName(sc->state->path->name)); } else { - trans->emplace("type"_cs, "hexstr"); - trans->emplace("value"_cs, stringRepr(value, bytes)); + trans->emplace("type", "hexstr"); + trans->emplace("value", stringRepr(value, bytes)); if (mask == -1) - trans->emplace("mask"_cs, Util::JsonValue::null); + trans->emplace("mask", Util::JsonValue::null); else - trans->emplace("mask"_cs, stringRepr(mask, bytes)); - trans->emplace("next_state"_cs, stateName(sc->state->path->name)); + trans->emplace("mask", stringRepr(mask, bytes)); + trans->emplace("next_state", stateName(sc->state->path->name)); } } result.push_back(trans); @@ -494,19 +494,19 @@ Util::IJson *ParserConverter::convertSelectKey(const IR::SelectExpression *expr) Util::IJson *ParserConverter::convertPathExpression(const IR::PathExpression *pe) { auto trans = new Util::JsonObject(); - trans->emplace("type"_cs, "default"); - trans->emplace("value"_cs, Util::JsonValue::null); - trans->emplace("mask"_cs, Util::JsonValue::null); - trans->emplace("next_state"_cs, stateName(pe->path->name)); + trans->emplace("type", "default"); + trans->emplace("value", Util::JsonValue::null); + trans->emplace("mask", Util::JsonValue::null); + trans->emplace("next_state", stateName(pe->path->name)); return trans; } Util::IJson *ParserConverter::createDefaultTransition() { auto trans = new Util::JsonObject(); - trans->emplace("type"_cs, "default"); - trans->emplace("value"_cs, Util::JsonValue::null); - trans->emplace("mask"_cs, Util::JsonValue::null); - trans->emplace("next_state"_cs, Util::JsonValue::null); + trans->emplace("type", "default"); + trans->emplace("value", Util::JsonValue::null); + trans->emplace("mask", Util::JsonValue::null); + trans->emplace("next_state", Util::JsonValue::null); return trans; } diff --git a/backends/bmv2/common/sharedActionSelectorCheck.h b/backends/bmv2/common/sharedActionSelectorCheck.h index ed875ecc9ca..0cb68d570bc 100644 --- a/backends/bmv2/common/sharedActionSelectorCheck.h +++ b/backends/bmv2/common/sharedActionSelectorCheck.h @@ -69,7 +69,7 @@ class SharedActionSelectorCheck : public Inspector { } bool preorder(const IR::P4Table *table) override { - auto implementation = table->properties->getProperty("implementation"_cs); + auto implementation = table->properties->getProperty("implementation"); if (implementation == nullptr) return false; if (!implementation->value->is()) { ::error(ErrorType::ERR_EXPECTED, "%1%: expected expression for property", diff --git a/backends/bmv2/psa_switch/psaSwitch.cpp b/backends/bmv2/psa_switch/psaSwitch.cpp index cdd74f9cd65..384d5362849 100644 --- a/backends/bmv2/psa_switch/psaSwitch.cpp +++ b/backends/bmv2/psa_switch/psaSwitch.cpp @@ -370,24 +370,24 @@ Util::IJson *ExternConverter_Hash::convertExternObject(UNUSED ConversionContext auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto hash = new Util::JsonObject(); - hash->emplace("type"_cs, "extern"); - hash->emplace("value"_cs, em->object->controlPlaneName()); + hash->emplace("type", "extern"); + hash->emplace("value", em->object->controlPlaneName()); parameters->append(hash); if (mc->arguments->size() == 2) { // get_hash auto dst = ctxt->conv->convertLeftValue(mc->arguments->at(0)->expression); auto fieldList = new Util::JsonObject(); - fieldList->emplace("type"_cs, "field_list"); + fieldList->emplace("type", "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(1)->expression, true, false); - fieldList->emplace("value"_cs, fieldsJson); + fieldList->emplace("value", fieldsJson); parameters->append(dst); parameters->append(fieldList); } else { // get_hash with base and mod auto dst = ctxt->conv->convertLeftValue(mc->arguments->at(0)->expression); auto base = ctxt->conv->convert(mc->arguments->at(1)->expression); auto fieldList = new Util::JsonObject(); - fieldList->emplace("type"_cs, "field_list"); + fieldList->emplace("type", "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(2)->expression, true, false); - fieldList->emplace("value"_cs, fieldsJson); + fieldList->emplace("value", fieldsJson); auto max = ctxt->conv->convert(mc->arguments->at(3)->expression); parameters->append(dst); parameters->append(base); @@ -436,14 +436,14 @@ Util::IJson *ExternConverter_InternetChecksum::convertExternObject( auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto cksum = new Util::JsonObject(); - cksum->emplace("type"_cs, "extern"); - cksum->emplace("value"_cs, em->object->controlPlaneName()); + cksum->emplace("type", "extern"); + cksum->emplace("value", em->object->controlPlaneName()); parameters->append(cksum); if (em->method->name == "add" || em->method->name == "subtract") { auto fieldList = new Util::JsonObject(); - fieldList->emplace("type"_cs, "field_list"); + fieldList->emplace("type", "field_list"); auto fieldsJson = ctxt->conv->convert(mc->arguments->at(0)->expression, true, false); - fieldList->emplace("value"_cs, fieldsJson); + fieldList->emplace("value", fieldsJson); parameters->append(fieldList); } else if (em->method->name != "clear") { if (mc->arguments->size() == 2) { // get_verify @@ -472,8 +472,8 @@ Util::IJson *ExternConverter_Counter::convertExternObject(UNUSED ConversionConte auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto ctr = new Util::JsonObject(); - ctr->emplace("type"_cs, "extern"); - ctr->emplace("value"_cs, em->object->controlPlaneName()); + ctr->emplace("type", "extern"); + ctr->emplace("value", em->object->controlPlaneName()); parameters->append(ctr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -505,8 +505,8 @@ Util::IJson *ExternConverter_Meter::convertExternObject(UNUSED ConversionContext auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto mtr = new Util::JsonObject(); - mtr->emplace("type"_cs, "extern"); - mtr->emplace("value"_cs, em->object->controlPlaneName()); + mtr->emplace("type", "extern"); + mtr->emplace("value", em->object->controlPlaneName()); parameters->append(mtr); if (mc->arguments->size() == 2) { auto result = ctxt->conv->convert(mc->arguments->at(1)->expression); @@ -546,9 +546,9 @@ Util::IJson *ExternConverter_Register::convertExternObject( return nullptr; } auto reg = new Util::JsonObject(); - reg->emplace("type"_cs, "register_array"); + reg->emplace("type", "register_array"); cstring name = em->object->controlPlaneName(); - reg->emplace("value"_cs, name); + reg->emplace("value", name); if (em->method->name == "read") { auto primitive = mkPrimitive("register_read"_cs); auto parameters = mkParameters(primitive); @@ -639,9 +639,9 @@ void ExternConverter_Hash::convertExternInstance(ConversionContext *ctxt, const // add hash instance auto jhash = new Util::JsonObject(); - jhash->emplace("name"_cs, name); - jhash->emplace("id"_cs, nextId("extern_instances"_cs)); - jhash->emplace("type"_cs, eb->getName()); + jhash->emplace("name", name); + jhash->emplace("id", nextId("extern_instances"_cs)); + jhash->emplace("type", eb->getName()); jhash->emplace_non_null("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(jhash); @@ -662,9 +662,9 @@ void ExternConverter_Hash::convertExternInstance(ConversionContext *ctxt, const cstring algo_name = algo->to()->name; algo_name = psaStructure->convertHashAlgorithm(algo_name); auto k = new Util::JsonObject(); - k->emplace("name"_cs, "algo"); - k->emplace("type"_cs, "string"); - k->emplace("value"_cs, algo_name); + k->emplace("name", "algo"); + k->emplace("type", "string"); + k->emplace("value", algo_name); arr->append(k); } @@ -692,9 +692,9 @@ void ExternConverter_InternetChecksum::convertExternInstance(UNUSED ConversionCo } // add checksum instance auto jcksum = new Util::JsonObject(); - jcksum->emplace("name"_cs, name); - jcksum->emplace("id"_cs, nextId("extern_instances"_cs)); - jcksum->emplace("type"_cs, eb->getName()); + jcksum->emplace("name", name); + jcksum->emplace("id", nextId("extern_instances"_cs)); + jcksum->emplace("type", eb->getName()); jcksum->emplace_non_null("source_info"_cs, inst->sourceInfoJsonObj()); ctxt->json->externs->append(jcksum); } @@ -714,19 +714,19 @@ void ExternConverter_Counter::convertExternInstance(UNUSED ConversionContext *ct // adding counter instance to counter_arrays[] auto jctr = new Util::JsonObject(); - jctr->emplace("name"_cs, name); - jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace("name", name); + jctr->emplace("id", nextId("counter_arrays"_cs)); jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - jctr->emplace("size"_cs, sz->to()->value); - jctr->emplace("is_direct"_cs, false); + jctr->emplace("size", sz->to()->value); + jctr->emplace("is_direct", false); ctxt->json->counters->append(jctr); // add counter instance to extern_instances auto extern_obj = new Util::JsonObject(); - extern_obj->emplace("name"_cs, name); - extern_obj->emplace("id"_cs, nextId("extern_instances"_cs)); - extern_obj->emplace("type"_cs, eb->getName()); - extern_obj->emplace("source_info"_cs, inst->sourceInfoJsonObj()); + extern_obj->emplace("name", name); + extern_obj->emplace("id", nextId("extern_instances"_cs)); + extern_obj->emplace("type", eb->getName()); + extern_obj->emplace("source_info", inst->sourceInfoJsonObj()); ctxt->json->externs->append(extern_obj); Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"_cs); @@ -741,9 +741,9 @@ void ExternConverter_Counter::convertExternInstance(UNUSED ConversionContext *ct auto param1 = eb->getConstructorParameters()->getParameter(0); auto bitwidth = ctxt->typeMap->widthBits(arg1->type, sz->getNode(), false); cstring repr = BMV2::stringRepr(arg1->value, ROUNDUP(bitwidth, 8)); - attr_obj->emplace("name"_cs, param1->toString()); - attr_obj->emplace("type"_cs, "hexstr"); - attr_obj->emplace("value"_cs, repr); + attr_obj->emplace("name", param1->toString()); + attr_obj->emplace("type", "hexstr"); + attr_obj->emplace("value", repr); arr->append(attr_obj); // second argument is the counter type, this is psa metadata, the converter @@ -772,20 +772,20 @@ void ExternConverter_DirectCounter::convertExternInstance(UNUSED ConversionConte ::warning(ErrorType::WARN_UNUSED, "%1%: Direct counter not used; ignoring", inst); } else { auto jctr = new Util::JsonObject(); - jctr->emplace("name"_cs, name); - jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace("name", name); + jctr->emplace("id", nextId("counter_arrays"_cs)); jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - jctr->emplace("is_direct"_cs, true); - jctr->emplace("binding"_cs, it->second->controlPlaneName()); + jctr->emplace("is_direct", true); + jctr->emplace("binding", it->second->controlPlaneName()); ctxt->json->counters->append(jctr); // Adding direct counter to EXTERN_INSTANCES auto extern_obj = new Util::JsonObject(); - extern_obj->emplace("name"_cs, name); - extern_obj->emplace("id"_cs, nextId("extern_instances"_cs)); - extern_obj->emplace("type"_cs, eb->getName()); - extern_obj->emplace("source_info"_cs, inst->sourceInfoJsonObj()); + extern_obj->emplace("name", name); + extern_obj->emplace("id", nextId("extern_instances"_cs)); + extern_obj->emplace("type", eb->getName()); + extern_obj->emplace("source_info", inst->sourceInfoJsonObj()); ctxt->json->externs->append(extern_obj); Util::JsonArray *arr = ctxt->json->insert_array_field(extern_obj, "attribute_values"_cs); @@ -823,9 +823,9 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt // adding meter instance into extern_instances auto jext_mtr = new Util::JsonObject(); - jext_mtr->emplace("name"_cs, name); - jext_mtr->emplace("id"_cs, nextId("extern_instances"_cs)); - jext_mtr->emplace("type"_cs, eb->getName()); + jext_mtr->emplace("name", name); + jext_mtr->emplace("id", nextId("extern_instances"_cs)); + jext_mtr->emplace("type", eb->getName()); jext_mtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); ctxt->json->externs->append(jext_mtr); @@ -834,9 +834,9 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt // is_direct auto is_direct = new Util::JsonObject(); - is_direct->emplace("name"_cs, "is_direct"); - is_direct->emplace("type"_cs, "hexstr"); - is_direct->emplace("value"_cs, 0); + is_direct->emplace("name", "is_direct"); + is_direct->emplace("type", "hexstr"); + is_direct->emplace("value", 0); arr->append(is_direct); // meter_array size @@ -851,16 +851,16 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt auto bitwidth = ctxt->typeMap->widthBits(s->type, sz->getNode(), false); cstring val = BMV2::stringRepr(s->value, ROUNDUP(bitwidth, 8)); auto msz = new Util::JsonObject(); - msz->emplace("name"_cs, attr_name->toString()); - msz->emplace("type"_cs, "hexstr"); - msz->emplace("value"_cs, val); + msz->emplace("name", attr_name->toString()); + msz->emplace("type", "hexstr"); + msz->emplace("value", val); arr->append(msz); // rate count auto rc = new Util::JsonObject(); - rc->emplace("name"_cs, "rate_count"); - rc->emplace("type"_cs, "hexstr"); - rc->emplace("value"_cs, 2); + rc->emplace("name", "rate_count"); + rc->emplace("type", "hexstr"); + rc->emplace("value", 2); arr->append(rc); // meter kind @@ -879,9 +879,9 @@ void ExternConverter_Meter::convertExternInstance(UNUSED ConversionContext *ctxt else ::error(ErrorType::ERR_UNEXPECTED, "%1%: unexpected meter type", mkind->getNode()); auto k = new Util::JsonObject(); - k->emplace("name"_cs, "type"); - k->emplace("type"_cs, "string"); - k->emplace("value"_cs, type); + k->emplace("name", "type"); + k->emplace("type", "string"); + k->emplace("value", type); arr->append(k); } @@ -897,11 +897,11 @@ void ExternConverter_DirectMeter::convertExternInstance(UNUSED ConversionContext CHECK_NULL(info->destinationField); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name"_cs, name); - jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace("name", name); + jmtr->emplace("id", nextId("meter_arrays"_cs)); jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct"_cs, true); - jmtr->emplace("rate_count"_cs, 2); + jmtr->emplace("is_direct", true); + jmtr->emplace("rate_count", 2); auto mkind = eb->findParameterValue("type"_cs); CHECK_NULL(mkind); if (!mkind->is()) { @@ -918,12 +918,12 @@ void ExternConverter_DirectMeter::convertExternInstance(UNUSED ConversionContext modelError("%1%: unexpected meter type", mkind->getNode()); return; } - jmtr->emplace("type"_cs, type); - jmtr->emplace("size"_cs, info->tableSize); + jmtr->emplace("type", type); + jmtr->emplace("size", info->tableSize); cstring tblname = info->table->controlPlaneName(); - jmtr->emplace("binding"_cs, tblname); + jmtr->emplace("binding", tblname); auto result = ctxt->conv->convert(info->destinationField); - jmtr->emplace("result_target"_cs, result->to()->get("value"_cs)); + jmtr->emplace("result_target", result->to()->get("value")); ctxt->json->meter_arrays->append(jmtr); } @@ -938,8 +938,8 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jreg = new Util::JsonObject(); - jreg->emplace("name"_cs, name); - jreg->emplace("id"_cs, nextId("register_arrays"_cs)); + jreg->emplace("name", name); + jreg->emplace("id", nextId("register_arrays"_cs)); jreg->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue("size"_cs); CHECK_NULL(sz); @@ -949,7 +949,7 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c } if (sz->to()->value == 0) error(ErrorType::ERR_UNSUPPORTED, "%1%: direct registers are not supported", inst); - jreg->emplace("size"_cs, sz->to()->value); + jreg->emplace("size", sz->to()->value); if (!eb->instanceType->is()) { modelError("%1%: Expected a generic specialized type", eb->instanceType); return; @@ -970,7 +970,7 @@ void ExternConverter_Register::convertExternInstance(UNUSED ConversionContext *c ::error(ErrorType::ERR_UNKNOWN, "%1%: unknown width", st->arguments->at(0)); return; } - jreg->emplace("bitwidth"_cs, width); + jreg->emplace("bitwidth", width); ctxt->json->register_arrays->append(jreg); } @@ -989,8 +989,8 @@ void ExternConverter_ActionProfile::convertExternInstance(UNUSED ConversionConte // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name"_cs, name); - action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace("name", name); + action_profile->emplace("id", nextId("action_profiles"_cs)); action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue("size"_cs); @@ -1000,7 +1000,7 @@ void ExternConverter_ActionProfile::convertExternInstance(UNUSED ConversionConte if (!sz->is()) { ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); } - action_profile->emplace("max_size"_cs, sz->to()->value); + action_profile->emplace("max_size", sz->to()->value); ctxt->action_profiles->append(action_profile); } @@ -1015,8 +1015,8 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name"_cs, name); - action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace("name", name); + action_profile->emplace("id", nextId("action_profiles"_cs)); action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue("size"_cs); @@ -1026,7 +1026,7 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size"_cs, sz->to()->value); + action_profile->emplace("max_size", sz->to()->value); auto selector = new Util::JsonObject(); auto hash = eb->findParameterValue("algo"_cs); @@ -1036,7 +1036,7 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo"_cs, algo); + selector->emplace("algo", algo); auto input = ctxt->get_selector_input(c->to()); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -1052,7 +1052,7 @@ void ExternConverter_ActionSelector::convertExternInstance(UNUSED ConversionCont auto jk = ctxt->conv->convert(expr); j_input->append(jk); } - action_profile->emplace("selector"_cs, selector); + action_profile->emplace("selector", selector); ctxt->action_profiles->append(action_profile); } diff --git a/backends/bmv2/psa_switch/psaSwitch.h b/backends/bmv2/psa_switch/psaSwitch.h index cd271f6a2c3..5ce938371c0 100644 --- a/backends/bmv2/psa_switch/psaSwitch.h +++ b/backends/bmv2/psa_switch/psaSwitch.h @@ -58,20 +58,20 @@ class PsaSwitchExpressionConverter : public ExpressionConverter { cstring ptName = param->type->toString(); if (P4::PsaProgramStructure::isCounterMetadata(ptName)) { // check if its counter metadata auto jsn = new Util::JsonObject(); - jsn->emplace("name"_cs, param->toString()); - jsn->emplace("type"_cs, "hexstr"); + jsn->emplace("name", param->toString()); + jsn->emplace("type", "hexstr"); auto bitwidth = param->type->width_bits(); // encode the counter type from enum -> int if (fieldName == "BYTES") { cstring repr = BMV2::stringRepr(0, ROUNDUP(bitwidth, 32)); - jsn->emplace("value"_cs, repr); + jsn->emplace("value", repr); } else if (fieldName == "PACKETS") { cstring repr = BMV2::stringRepr(1, ROUNDUP(bitwidth, 32)); - jsn->emplace("value"_cs, repr); + jsn->emplace("value", repr); } else if (fieldName == "PACKETS_AND_BYTES") { cstring repr = BMV2::stringRepr(2, ROUNDUP(bitwidth, 32)); - jsn->emplace("value"_cs, repr); + jsn->emplace("value", repr); } else { modelError("%1%: Exptected a PSA_CounterType_t", fieldName); return nullptr; @@ -82,7 +82,7 @@ class PsaSwitchExpressionConverter : public ExpressionConverter { auto jsn = new Util::JsonObject(); // encode the metadata type and field in json - jsn->emplace("type"_cs, "field"); + jsn->emplace("type", "field"); auto a = mkArrayField(jsn, "value"_cs); a->append(ptName.exceptLast(2)); a->append(fieldName); diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 2ff83a507f5..6f977ab42c6 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -25,6 +25,7 @@ limitations under the License. #include "backends/bmv2/simple_switch/options.h" #include "frontends/p4/cloner.h" #include "frontends/p4/fromv1.0/v1model.h" +#include "lib/json.h" #include "midend/flattenLogMsg.h" using BMV2::mkArrayField; @@ -172,9 +173,9 @@ static unsigned getFieldListById(ConversionContext *ctxt, unsigned index) { for (auto it : *ctxt->json->field_lists) { auto j = it->to(); CHECK_NULL(j); - auto name = j->get("name"_cs)->to()->getString(); + auto name = j->getAs("name")->getString(); if (name == search) { - id = j->get("id"_cs)->to()->getInt(); + id = j->getAs("id")->getInt(); break; } } @@ -273,8 +274,8 @@ Util::IJson *ExternConverter_hash::convertExternFunction(ConversionContext *ctxt auto fields = mc->arguments->at(3); auto calcName = ctxt->createCalculation(ei->name, fields->expression, ctxt->json->calculations, false, nullptr); - calculation->emplace("type"_cs, "calculation"); - calculation->emplace("value"_cs, calcName); + calculation->emplace("type", "calculation"); + calculation->emplace("value", calcName); parameters->append(calculation); auto max = ctxt->conv->convert(mc->arguments->at(4)->expression); parameters->append(max); @@ -448,8 +449,8 @@ Util::IJson *ExternConverter_counter::convertExternObject(ConversionContext *ctx auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto ctr = new Util::JsonObject(); - ctr->emplace("type"_cs, "counter_array"); - ctr->emplace("value"_cs, em->object->controlPlaneName()); + ctr->emplace("type", "counter_array"); + ctr->emplace("value", em->object->controlPlaneName()); parameters->append(ctr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -463,8 +464,8 @@ void ExternConverter_counter::convertExternInstance(ConversionContext *ctxt, auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jctr = new Util::JsonObject(); - jctr->emplace("name"_cs, name); - jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); + jctr->emplace("name", name); + jctr->emplace("id", nextId("counter_arrays"_cs)); jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue(v1model.counter.sizeParam.name); CHECK_NULL(sz); @@ -472,8 +473,8 @@ void ExternConverter_counter::convertExternInstance(ConversionContext *ctxt, modelError("%1%: expected a constant", sz->getNode()); return; } - jctr->emplace("size"_cs, sz->to()->value); - jctr->emplace("is_direct"_cs, false); + jctr->emplace("size", sz->to()->value); + jctr->emplace("is_direct", false); ctxt->json->counters->append(jctr); } @@ -490,8 +491,8 @@ Util::IJson *ExternConverter_meter::convertExternObject(ConversionContext *ctxt, auto parameters = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto mtr = new Util::JsonObject(); - mtr->emplace("type"_cs, "meter_array"); - mtr->emplace("value"_cs, em->object->controlPlaneName()); + mtr->emplace("type", "meter_array"); + mtr->emplace("value", em->object->controlPlaneName()); parameters->append(mtr); auto index = ctxt->conv->convert(mc->arguments->at(0)->expression); parameters->append(index); @@ -506,18 +507,18 @@ void ExternConverter_meter::convertExternInstance(ConversionContext *ctxt, const auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name"_cs, name); - jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace("name", name); + jmtr->emplace("id", nextId("meter_arrays"_cs)); jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct"_cs, false); + jmtr->emplace("is_direct", false); auto sz = eb->findParameterValue(v1model.meter.sizeParam.name); CHECK_NULL(sz); if (!sz->is()) { modelError("%1%: expected a constant", sz->getNode()); return; } - jmtr->emplace("size"_cs, sz->to()->value); - jmtr->emplace("rate_count"_cs, 2); + jmtr->emplace("size", sz->to()->value); + jmtr->emplace("rate_count", 2); auto mkind = eb->findParameterValue(v1model.meter.typeParam.name); CHECK_NULL(mkind); if (!mkind->is()) { @@ -533,7 +534,7 @@ void ExternConverter_meter::convertExternInstance(ConversionContext *ctxt, const else ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "Unexpected meter type %1%", mkind->getNode()); - jmtr->emplace("type"_cs, type); + jmtr->emplace("type", type); ctxt->json->meter_arrays->append(jmtr); } @@ -547,9 +548,9 @@ Util::IJson *ExternConverter_register::convertExternObject(ConversionContext *ct return nullptr; } auto reg = new Util::JsonObject(); - reg->emplace("type"_cs, "register_array"); + reg->emplace("type", "register_array"); cstring name = em->object->controlPlaneName(); - reg->emplace("value"_cs, name); + reg->emplace("value", name); if (em->method->name == v1model.registers.read.name) { auto primitive = mkPrimitive("register_read"_cs); auto parameters = mkParameters(primitive); @@ -581,8 +582,8 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, auto inst = c->to(); cstring name = inst->controlPlaneName(); auto jreg = new Util::JsonObject(); - jreg->emplace("name"_cs, name); - jreg->emplace("id"_cs, nextId("register_arrays"_cs)); + jreg->emplace("name", name); + jreg->emplace("id", nextId("register_arrays"_cs)); jreg->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto sz = eb->findParameterValue(v1model.registers.sizeParam.name); CHECK_NULL(sz); @@ -593,7 +594,7 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, if (sz->to()->value == 0) error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: direct registers are not supported in bmv2", inst); - jreg->emplace("size"_cs, sz->to()->value); + jreg->emplace("size", sz->to()->value); if (auto st = eb->instanceType->to()) { if (st->arguments->size() < 1 || st->arguments->size() > 2) { modelError("%1%: expected 1 or 2 type arguments", st); @@ -610,7 +611,7 @@ void ExternConverter_register::convertExternInstance(ConversionContext *ctxt, ::error(ErrorType::ERR_EXPRESSION, "%1%: unknown width", st->arguments->at(0)); return; } - jreg->emplace("bitwidth"_cs, width); + jreg->emplace("bitwidth", width); ctxt->json->register_arrays->append(jreg); } else { modelError("%1%: Expected a generic specialized type", eb->instanceType); @@ -641,10 +642,10 @@ void ExternConverter_direct_counter::convertExternInstance(ConversionContext *ct ::warning(ErrorType::WARN_UNUSED, "%1%: Direct counter not used; ignoring", inst); } else { auto jctr = new Util::JsonObject(); - jctr->emplace("name"_cs, name); - jctr->emplace("id"_cs, nextId("counter_arrays"_cs)); - jctr->emplace("is_direct"_cs, true); - jctr->emplace("binding"_cs, it->second->controlPlaneName()); + jctr->emplace("name", name); + jctr->emplace("id", nextId("counter_arrays"_cs)); + jctr->emplace("is_direct", true); + jctr->emplace("binding", it->second->controlPlaneName()); jctr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); ctxt->json->counters->append(jctr); } @@ -696,11 +697,11 @@ void ExternConverter_direct_meter::convertExternInstance(ConversionContext *ctxt CHECK_NULL(info->destinationField); auto jmtr = new Util::JsonObject(); - jmtr->emplace("name"_cs, name); - jmtr->emplace("id"_cs, nextId("meter_arrays"_cs)); + jmtr->emplace("name", name); + jmtr->emplace("id", nextId("meter_arrays"_cs)); jmtr->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); - jmtr->emplace("is_direct"_cs, true); - jmtr->emplace("rate_count"_cs, 2); + jmtr->emplace("is_direct", true); + jmtr->emplace("rate_count", 2); auto mkind = eb->findParameterValue(v1model.directMeter.typeParam.name); CHECK_NULL(mkind); if (!mkind->is()) { @@ -717,12 +718,12 @@ void ExternConverter_direct_meter::convertExternInstance(ConversionContext *ctxt modelError("%1%: unexpected meter type", mkind->getNode()); return; } - jmtr->emplace("type"_cs, type); - jmtr->emplace("size"_cs, info->tableSize); + jmtr->emplace("type", type); + jmtr->emplace("size", info->tableSize); cstring tblname = info->table->controlPlaneName(); - jmtr->emplace("binding"_cs, tblname); + jmtr->emplace("binding", tblname); auto result = ctxt->conv->convert(info->destinationField); - jmtr->emplace("result_target"_cs, result->to()->get("value"_cs)); + jmtr->emplace("result_target", result->to()->get("value")); ctxt->json->meter_arrays->append(jmtr); } @@ -736,8 +737,8 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name"_cs, name); - action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace("name", name); + action_profile->emplace("id", nextId("action_profiles"_cs)); action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto add_size = [&action_profile, &eb](const cstring &pname) { @@ -748,7 +749,7 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size"_cs, sz->to()->value); + action_profile->emplace("max_size", sz->to()->value); }; if (eb->type->name == v1model.action_profile.name) { @@ -762,7 +763,7 @@ void ExternConverter_action_profile::convertExternInstance(ConversionContext *ct return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo"_cs, algo); + selector->emplace("algo", algo); auto input = ctxt->get_selector_input(inst); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -795,8 +796,8 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c // once in a pipeline, so only add it to the action_profiles once if (BMV2::JsonObjects::find_object_by_name(ctxt->action_profiles, name)) return; auto action_profile = new Util::JsonObject(); - action_profile->emplace("name"_cs, name); - action_profile->emplace("id"_cs, nextId("action_profiles"_cs)); + action_profile->emplace("name", name); + action_profile->emplace("id", nextId("action_profiles"_cs)); action_profile->emplace_non_null("source_info"_cs, eb->sourceInfoJsonObj()); auto add_size = [&action_profile, &eb](const cstring &pname) { @@ -807,7 +808,7 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c ::error(ErrorType::ERR_EXPECTED, "%1%: expected a constant", sz); return; } - action_profile->emplace("max_size"_cs, sz->to()->value); + action_profile->emplace("max_size", sz->to()->value); }; if (eb->type->name == v1model.action_profile.name) { @@ -821,7 +822,7 @@ void ExternConverter_action_selector::convertExternInstance(ConversionContext *c return; } auto algo = ExternConverter::convertHashAlgorithm(hash->to()->name); - selector->emplace("algo"_cs, algo); + selector->emplace("algo", algo); auto input = ctxt->get_selector_input(inst); if (input == nullptr) { // the selector is never used by any table, we cannot figure out its @@ -856,7 +857,7 @@ Util::IJson *ExternConverter_log_msg::convertExternFunction(ConversionContext *c auto params = mkParameters(primitive); primitive->emplace_non_null("source_info"_cs, s->sourceInfoJsonObj()); auto paramsValue = new Util::JsonObject(); - paramsValue->emplace("type"_cs, "parameters_vector"); + paramsValue->emplace("type", "parameters_vector"); auto str = ctxt->conv->convert(mc->arguments->at(0)->expression); params->append(str); if (mc->arguments->size() == 2) { @@ -901,11 +902,11 @@ cstring SimpleSwitchBackend::createCalculation(cstring algo, const IR::Expressio const IR::Node *sourcePositionNode = nullptr) { cstring calcName = refMap->newName("calc_"); auto calc = new Util::JsonObject(); - calc->emplace("name"_cs, calcName); - calc->emplace("id"_cs, nextId("calculations"_cs)); + calc->emplace("name", calcName); + calc->emplace("id", nextId("calculations"_cs)); if (sourcePositionNode != nullptr) calc->emplace_non_null("source_info"_cs, sourcePositionNode->sourceInfoJsonObj()); - calc->emplace("algo"_cs, algo); + calc->emplace("algo", algo); fields = convertToList(fields, typeMap); if (!fields) { modelError("%1%: expected a struct", fields); @@ -916,8 +917,8 @@ cstring SimpleSwitchBackend::createCalculation(cstring algo, const IR::Expressio auto array = jright->to(); BUG_CHECK(array, "expected a JSON array"); auto payload = new Util::JsonObject(); - payload->emplace("type"_cs, "payload"); - payload->emplace("value"_cs, (Util::IJson *)nullptr); + payload->emplace("type", "payload"); + payload->emplace("value", (Util::IJson *)nullptr); array->append(payload); } calc->emplace("input"_cs, jright); @@ -978,15 +979,15 @@ void SimpleSwitchBackend::convertChecksum(const IR::BlockStatement *block, (void)calcExpr->apply(eeis); cstring calcName = createCalculation(algo, calcExpr, calculations, usePayload, mc); - cksum->emplace("name"_cs, refMap->newName("cksum_")); - cksum->emplace("id"_cs, nextId("checksums"_cs)); + cksum->emplace("name", refMap->newName("cksum_")); + cksum->emplace("id", nextId("checksums"_cs)); cksum->emplace_non_null("source_info"_cs, stat->sourceInfoJsonObj()); auto jleft = conv->convert(mi->expr->arguments->at(2)->expression); - cksum->emplace("target"_cs, jleft->to()->get("value"_cs)); - cksum->emplace("type"_cs, "generic"); - cksum->emplace("calculation"_cs, calcName); - cksum->emplace("verify"_cs, verify); - cksum->emplace("update"_cs, !verify); + cksum->emplace("target", jleft->to()->get("value")); + cksum->emplace("type", "generic"); + cksum->emplace("calculation", calcName); + cksum->emplace("verify", verify); + cksum->emplace("update", !verify); auto ifcond = conv->convert(mi->expr->arguments->at(0)->expression, true, false); cksum->emplace("if_cond"_cs, ifcond); @@ -1056,17 +1057,17 @@ void SimpleSwitchBackend::createRecirculateFieldsList(ConversionContext *ctxt, ctxt->json->field_lists->append(fl); fieldLists.emplace(index, fl); int id = nextId("field_lists"_cs); - fl->emplace("id"_cs, id); + fl->emplace("id", id); cstring listName = "field_list"_cs + Util::toString(index); - fl->emplace("name"_cs, listName); + fl->emplace("name", listName); elements = mkArrayField(fl, "elements"_cs); } else { - elements = fl->get("elements"_cs)->to(); + elements = fl->getAs("elements"); CHECK_NULL(elements); } auto field = new Util::JsonObject(); - field->emplace("type"_cs, "field"); + field->emplace("type", "field"); auto value = new Util::JsonArray(); value->append(scalarName); auto name = ::get(ctxt->structure->scalarMetadataFields, f); diff --git a/backends/bmv2/simple_switch/simpleSwitch.h b/backends/bmv2/simple_switch/simpleSwitch.h index 7a5985ac72a..3a2e7b541c6 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.h +++ b/backends/bmv2/simple_switch/simpleSwitch.h @@ -112,13 +112,13 @@ class SimpleSwitchExpressionConverter : public ExpressionConverter { if (isStandardMetadataParameter(param)) { auto result = new Util::JsonObject(); if (fieldName != "") { - result->emplace("type"_cs, "field"); + result->emplace("type", "field"); auto e = BMV2::mkArrayField(result, "value"_cs); e->append("standard_metadata"); e->append(fieldName); } else { - result->emplace("type"_cs, "header"); - result->emplace("value"_cs, "standard_metadata"); + result->emplace("type", "header"); + result->emplace("value", "standard_metadata"); } return result; } diff --git a/backends/dpdk/control-plane/bfruntime_arch_handler.h b/backends/dpdk/control-plane/bfruntime_arch_handler.h index ab0b1103db4..d3721f49085 100644 --- a/backends/dpdk/control-plane/bfruntime_arch_handler.h +++ b/backends/dpdk/control-plane/bfruntime_arch_handler.h @@ -318,7 +318,7 @@ class BFRuntimeArchHandler : public P4RuntimeArchHandlerCommon { /// @return true if @table's 'psa_idle_timeout' property exists and is true. This /// indicates that @table supports entry ageing. static bool getSupportsTimeout(const IR::P4Table *table) { - auto timeout = table->properties->getProperty("psa_idle_timeout"_cs); + auto timeout = table->properties->getProperty("psa_idle_timeout"); if (timeout == nullptr) return false; diff --git a/backends/dpdk/control-plane/bfruntime_ext.cpp b/backends/dpdk/control-plane/bfruntime_ext.cpp index 5c5949923e9..809a5be53d1 100644 --- a/backends/dpdk/control-plane/bfruntime_ext.cpp +++ b/backends/dpdk/control-plane/bfruntime_ext.cpp @@ -15,6 +15,8 @@ limitations under the License. #include "bfruntime_ext.h" +#include "lib/json.h" + namespace P4 { namespace BFRT { @@ -60,9 +62,9 @@ void BFRuntimeSchemaGenerator::addMatchActionData(const p4configv1::Table &table Util::JsonObject *tableJson, Util::JsonArray *dataJson, P4Id maxActionParamId) const { - cstring tableType = tableJson->get("table_type"_cs)->to()->getString(); + cstring tableType = tableJson->getAs("table_type")->getString(); if (tableType == "MatchAction_Direct") { - tableJson->emplace("action_specs"_cs, makeActionSpecs(table, &maxActionParamId)); + tableJson->emplace("action_specs", makeActionSpecs(table, &maxActionParamId)); } else if (tableType == "MatchAction_Indirect") { auto *f = makeCommonDataField(BF_RT_DATA_ACTION_MEMBER_ID, "$ACTION_MEMBER_ID"_cs, makeType("uint32"_cs), false /* repeated */); @@ -94,7 +96,7 @@ void BFRuntimeSchemaGenerator::addActionSelectorGetMemberCommon( true /* mandatory */, "Exact"_cs, makeType("uint64"_cs)); addKeyField(keyJson, BF_RT_DATA_HASH_VALUE, "hash_value"_cs, true /* mandatory */, "Exact"_cs, makeType("uint64"_cs)); - tableJson->emplace("key"_cs, keyJson); + tableJson->emplace("key", keyJson); auto *dataJson = new Util::JsonArray(); { @@ -102,10 +104,10 @@ void BFRuntimeSchemaGenerator::addActionSelectorGetMemberCommon( makeType("uint64"_cs), false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } - tableJson->emplace("data"_cs, dataJson); + tableJson->emplace("data", dataJson); - tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); - tableJson->emplace("attributes"_cs, new Util::JsonArray()); + tableJson->emplace("supported_operations", new Util::JsonArray()); + tableJson->emplace("attributes", new Util::JsonArray()); addToDependsOn(tableJson, actionSelector.id); tablesJson->append(tableJson); @@ -122,7 +124,7 @@ void BFRuntimeSchemaGenerator::addActionSelectorCommon(Util::JsonArray *tablesJs auto *keyJson = new Util::JsonArray(); addKeyField(keyJson, BF_RT_DATA_SELECTOR_GROUP_ID, "$SELECTOR_GROUP_ID"_cs, true /* mandatory */, "Exact"_cs, makeType("uint32"_cs)); - tableJson->emplace("key"_cs, keyJson); + tableJson->emplace("key", keyJson); auto *dataJson = new Util::JsonArray(); { @@ -141,10 +143,10 @@ void BFRuntimeSchemaGenerator::addActionSelectorCommon(Util::JsonArray *tablesJs false /* repeated */); addSingleton(dataJson, f, false /* mandatory */, false /* read-only */); } - tableJson->emplace("data"_cs, dataJson); + tableJson->emplace("data", dataJson); - tableJson->emplace("supported_operations"_cs, new Util::JsonArray()); - tableJson->emplace("attributes"_cs, new Util::JsonArray()); + tableJson->emplace("supported_operations", new Util::JsonArray()); + tableJson->emplace("attributes", new Util::JsonArray()); addToDependsOn(tableJson, actionSelector.action_profile_id); auto oneTableId = actionSelector.tableIds.at(0); @@ -177,8 +179,8 @@ bool BFRuntimeSchemaGenerator::addActionProfIds(const p4configv1::Table &table, actProfId = BFRuntimeSchemaGenerator::ActionProf::makeActProfId(implementationId); tableType = "MatchAction_Indirect"_cs; } - tableJson->erase("table_type"_cs); - tableJson->emplace("table_type"_cs, tableType); + tableJson->erase("table_type"); + tableJson->emplace("table_type", tableType); } if (actProfId > 0) addToDependsOn(tableJson, actProfId); @@ -222,14 +224,14 @@ const Util::JsonObject *BFRuntimeSchemaGenerator::genSchema() const { if (isTDI) { auto progName = options.file.stem(); - json->emplace("program_name"_cs, progName); - json->emplace("build_date"_cs, cstring(options.getBuildDate())); - json->emplace("compile_command"_cs, cstring(options.getCompileCommand())); - json->emplace("compiler_version"_cs, cstring(options.compilerVersion)); - json->emplace("schema_version"_cs, tdiSchemaVersion); - json->emplace("target"_cs, "DPDK"); + json->emplace("program_name", progName); + json->emplace("build_date", options.getBuildDate()); + json->emplace("compile_command", options.getCompileCommand()); + json->emplace("compiler_version", options.compilerVersion); + json->emplace("schema_version", tdiSchemaVersion); + json->emplace("target", "DPDK"); } else { - json->emplace("schema_version"_cs, bfrtSchemaVersion); + json->emplace("schema_version", bfrtSchemaVersion); } auto *tablesJson = new Util::JsonArray(); @@ -242,7 +244,7 @@ const Util::JsonObject *BFRuntimeSchemaGenerator::genSchema() const { addRegisters(tablesJson); auto *learnFiltersJson = new Util::JsonArray(); - json->emplace("learn_filters"_cs, learnFiltersJson); + json->emplace("learn_filters", learnFiltersJson); addLearnFilters(learnFiltersJson); addDPDKExterns(tablesJson, learnFiltersJson); diff --git a/backends/dpdk/dpdkArch.cpp b/backends/dpdk/dpdkArch.cpp index 562f5b9c117..a61fd8a7528 100644 --- a/backends/dpdk/dpdkArch.cpp +++ b/backends/dpdk/dpdkArch.cpp @@ -1226,7 +1226,7 @@ const IR::Node *CollectLocalVariables::postorder(IR::P4Parser *p) { /// This function stores the information about parameters of default action /// for each table. void DefActionValue::postorder(const IR::P4Table *t) { - auto default_action = t->properties->getProperty("default_action"_cs); + auto default_action = t->properties->getProperty("default_action"); if (default_action != nullptr && default_action->value->is()) { auto expr = default_action->value->to()->expression; auto mi = @@ -1457,7 +1457,7 @@ const IR::Node *DismantleMuxExpressions::postorder(IR::AssignmentStatement *stat bool CopyMatchKeysToSingleStruct::isLearnerTable(const IR::P4Table *t) { bool use_add_on_miss = false; - auto add_on_miss = t->properties->getProperty("add_on_miss"_cs); + auto add_on_miss = t->properties->getProperty("add_on_miss"); if (add_on_miss == nullptr) return false; if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; @@ -1816,7 +1816,7 @@ std::tuple SplitP4TableCommon::create_mat } } - auto constDefAction = tbl->properties->getProperty("default_action"_cs); + auto constDefAction = tbl->properties->getProperty("default_action"); bool isConstDefAction = constDefAction ? constDefAction->isConstant : false; IR::IndexedVector properties; @@ -1920,15 +1920,13 @@ const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { bool isConstructedInPlace = false; bool isAsInstanceShared = false; cstring externName = cstring::empty; - cstring prefix = "psa_"_cs; - if (structure->isPNA()) { - prefix = "pna_"_cs; - } - - auto property = tbl->properties->getProperty(prefix + "implementation"_cs); - auto counterProperty = tbl->properties->getProperty(prefix + "direct_counter"_cs); - auto meterProperty = tbl->properties->getProperty(prefix + "direct_meter"_cs); + auto property = tbl->properties->getProperty(structure->isPNA() ? "pna_implementation" + : "psa_implementation"); + auto counterProperty = tbl->properties->getProperty(structure->isPNA() ? "pna_direct_counter" + : "psa_direct_counter"); + auto meterProperty = + tbl->properties->getProperty(structure->isPNA() ? "pna_direct_meter" : "psa_direct_meter"); if (property != nullptr && (counterProperty != nullptr || meterProperty != nullptr)) { ::error(ErrorType::ERR_UNEXPECTED, @@ -1939,7 +1937,8 @@ const IR::Node *SplitActionSelectorTable::postorder(IR::P4Table *tbl) { } auto instance = Helpers::getExternInstanceFromProperty( - tbl, prefix + "implementation", refMap, typeMap, &isConstructedInPlace, externName); + tbl, structure->isPNA() ? "pna_implementation"_cs : "psa_implementation"_cs, refMap, + typeMap, &isConstructedInPlace, externName); if (!instance) return tbl; if (instance->type->name != "ActionSelector") return tbl; @@ -2643,7 +2642,7 @@ void ValidateDirectCounterMeter::postorder(const IR::MethodCallStatement *mcs) { void CollectAddOnMissTable::postorder(const IR::P4Table *t) { bool use_add_on_miss = false; - auto add_on_miss = t->properties->getProperty("add_on_miss"_cs); + auto add_on_miss = t->properties->getProperty("add_on_miss"); cstring default_actname = "NoAction"_cs; if (add_on_miss == nullptr) return; if (add_on_miss->value->is()) { @@ -2659,7 +2658,7 @@ void CollectAddOnMissTable::postorder(const IR::P4Table *t) { } // sanity checks - auto default_action = t->properties->getProperty("default_action"_cs); + auto default_action = t->properties->getProperty("default_action"); if (use_add_on_miss && default_action == nullptr) { ::error(ErrorType::ERR_UNEXPECTED, "%1%: add_on_miss property is defined, " @@ -2741,7 +2740,7 @@ void ValidateAddOnMissExterns::postorder(const IR::MethodCallStatement *mcs) { bool use_idle_timeout_with_auto_delete = false; if (tbl) { auto idle_timeout_with_auto_delete = - tbl->properties->getProperty("idle_timeout_with_auto_delete"_cs); + tbl->properties->getProperty("idle_timeout_with_auto_delete"); if (idle_timeout_with_auto_delete != nullptr) { propName = "idle_timeout_with_auto_delete"_cs; if (idle_timeout_with_auto_delete->value->is()) { @@ -2767,7 +2766,7 @@ void ValidateAddOnMissExterns::postorder(const IR::MethodCallStatement *mcs) { auto args = mce->arguments; auto at = args->at(0)->expression; auto an = at->to()->value; - auto add_on_miss = tbl->properties->getProperty("add_on_miss"_cs); + auto add_on_miss = tbl->properties->getProperty("add_on_miss"); if (add_on_miss != nullptr) { propName = "add_on_miss"_cs; if (add_on_miss->value->is()) { diff --git a/backends/dpdk/dpdkContext.cpp b/backends/dpdk/dpdkContext.cpp index 32af245cb70..908d116c8af 100644 --- a/backends/dpdk/dpdkContext.cpp +++ b/backends/dpdk/dpdkContext.cpp @@ -53,10 +53,10 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { tblAttr.size = dpdk_default_table_size; if (size) tblAttr.size = size->asUnsigned(); auto hidden = tbl->annotations->getSingle(IR::Annotation::hiddenAnnotation); - auto selector = tbl->properties->getProperty("selector"_cs); + auto selector = tbl->properties->getProperty("selector"); tblAttr.is_add_on_miss = false; tblAttr.idle_timeout_with_auto_delete = false; - auto add_on_miss = tbl->properties->getProperty("add_on_miss"_cs); + auto add_on_miss = tbl->properties->getProperty("add_on_miss"); if (add_on_miss != nullptr) { if (add_on_miss->value->is()) { auto expr = add_on_miss->value->to()->expression; @@ -71,7 +71,7 @@ void DpdkContextGenerator::CollectTablesAndSetAttributes() { } } auto idle_timeout_with_auto_delete = - tbl->properties->getProperty("idle_timeout_with_auto_delete"_cs); + tbl->properties->getProperty("idle_timeout_with_auto_delete"); if (idle_timeout_with_auto_delete != nullptr) { if (idle_timeout_with_auto_delete->value->is()) { auto expr = idle_timeout_with_auto_delete->value->to() @@ -174,16 +174,16 @@ void DpdkContextGenerator::addKeyField(Util::JsonArray *keyJson, const cstring n // Replace header stack indices hdr[] with hdr$. std::regex hdrStackRegex(R"(\[([0-9]+)\])"); keyName = std::regex_replace(keyName, hdrStackRegex, "$$$1"); - keyField->emplace("name"_cs, keyName); - keyField->emplace("instance_name"_cs, instanceName); - keyField->emplace("field_name"_cs, fieldName); + keyField->emplace("name", keyName); + keyField->emplace("instance_name", instanceName); + keyField->emplace("field_name", fieldName); auto match_kind = toStr(key->matchType); if (match_kind == "optional" || match_kind == "range") match_kind = "ternary"_cs; - keyField->emplace("match_type"_cs, match_kind); - keyField->emplace("start_bit"_cs, 0); - keyField->emplace("bit_width"_cs, key->expression->type->width_bits()); - keyField->emplace("bit_width_full"_cs, key->expression->type->width_bits()); - keyField->emplace("position"_cs, position); + keyField->emplace("match_type", match_kind); + keyField->emplace("start_bit", 0); + keyField->emplace("bit_width", key->expression->type->width_bits()); + keyField->emplace("bit_width_full", key->expression->type->width_bits()); + keyField->emplace("position", position); keyJson->append(keyField); } @@ -192,15 +192,15 @@ Util::JsonObject *DpdkContextGenerator::initTableCommonJson(const cstring name, const struct TableAttributes &attr) { auto *tableJson = new Util::JsonObject(); cstring tableName = name; - tableJson->emplace("name"_cs, attr.externalName); - tableJson->emplace("target_name"_cs, tableName); - tableJson->emplace("direction"_cs, attr.direction); - tableJson->emplace("handle"_cs, attr.tableHandle); - tableJson->emplace("table_type"_cs, attr.tableType); - tableJson->emplace("size"_cs, attr.size); - tableJson->emplace("p4_hidden"_cs, attr.isHidden); - tableJson->emplace("add_on_miss"_cs, attr.is_add_on_miss); - tableJson->emplace("idle_timeout_with_auto_delete"_cs, attr.idle_timeout_with_auto_delete); + tableJson->emplace("name", attr.externalName); + tableJson->emplace("target_name", tableName); + tableJson->emplace("direction", attr.direction); + tableJson->emplace("handle", attr.tableHandle); + tableJson->emplace("table_type", attr.tableType); + tableJson->emplace("size", attr.size); + tableJson->emplace("p4_hidden", attr.isHidden); + tableJson->emplace("add_on_miss", attr.is_add_on_miss); + tableJson->emplace("idle_timeout_with_auto_delete", attr.idle_timeout_with_auto_delete); return tableJson; } @@ -320,9 +320,9 @@ void DpdkContextGenerator::setDefaultActionHandle(const IR::P4Table *table) { void DpdkContextGenerator::addImmediateField(Util::JsonArray *paramJson, const cstring name, int dest_start, int dest_width) { auto *oneParam = new Util::JsonObject(); - oneParam->emplace("param_name"_cs, name); - oneParam->emplace("dest_start"_cs, dest_start); - oneParam->emplace("dest_width"_cs, dest_width); + oneParam->emplace("param_name", name); + oneParam->emplace("dest_start", dest_start); + oneParam->emplace("dest_width", dest_width); paramJson->append(oneParam); } @@ -341,8 +341,8 @@ Util::JsonObject *DpdkContextGenerator::addMatchAttributes(const IR::P4Table *ta if (name != "NoAction") { name = ctrlName + "." + name; } - oneAction->emplace("action_name"_cs, name); - oneAction->emplace("action_handle"_cs, attr.actionHandle); + oneAction->emplace("action_name", name); + oneAction->emplace("action_handle", attr.actionHandle); auto *immFldArray = new Util::JsonArray(); if (attr.params) { int index = 0; @@ -371,11 +371,11 @@ Util::JsonObject *DpdkContextGenerator::addMatchAttributes(const IR::P4Table *ta void DpdkContextGenerator::addActionParam(Util::JsonArray *paramJson, const cstring name, int bitWidth, int position, int byte_array_index) { auto *oneParam = new Util::JsonObject(); - oneParam->emplace("name"_cs, name); - oneParam->emplace("start_bit"_cs, 0); - oneParam->emplace("bit_width"_cs, bitWidth); - oneParam->emplace("position"_cs, position); - oneParam->emplace("byte_array_index"_cs, byte_array_index); + oneParam->emplace("name", name); + oneParam->emplace("start_bit", 0); + oneParam->emplace("bit_width", bitWidth); + oneParam->emplace("position", position); + oneParam->emplace("byte_array_index", byte_array_index); paramJson->append(oneParam); } @@ -395,14 +395,14 @@ Util::JsonArray *DpdkContextGenerator::addActions(const IR::P4Table *table, } else { actName = name; } - act->emplace("name"_cs, attr.externalName); - act->emplace("target_name"_cs, actName); - act->emplace("handle"_cs, attr.actionHandle); + act->emplace("name", attr.externalName); + act->emplace("target_name", actName); + act->emplace("handle", attr.actionHandle); if (isMatch) { - act->emplace("constant_default_action"_cs, attr.constant_default_action); - act->emplace("is_compiler_added_action"_cs, attr.is_compiler_added_action); - act->emplace("allowed_as_hit_action"_cs, attr.allowed_as_hit_action); - act->emplace("allowed_as_default_action"_cs, attr.allowed_as_default_action); + act->emplace("constant_default_action", attr.constant_default_action); + act->emplace("is_compiler_added_action", attr.is_compiler_added_action); + act->emplace("allowed_as_hit_action", attr.allowed_as_hit_action); + act->emplace("allowed_as_default_action", attr.allowed_as_default_action); } auto *paramJson = new Util::JsonArray(); if (attr.params) { @@ -436,9 +436,9 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl // Below empty arrays are currently required by the control plane software. // May be removed in future. - tableJson->emplace("stateful_table_refs"_cs, new Util::JsonArray()); - tableJson->emplace("statistics_table_refs"_cs, new Util::JsonArray()); - tableJson->emplace("meter_table_refs"_cs, new Util::JsonArray()); + tableJson->emplace("stateful_table_refs", new Util::JsonArray()); + tableJson->emplace("statistics_table_refs", new Util::JsonArray()); + tableJson->emplace("meter_table_refs", new Util::JsonArray()); // Reference to compiler generated member table in case of action profile and action selector. if (structure->member_tables.count(tbl_name)) { @@ -448,8 +448,8 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl auto *actionDataField = new Util::JsonObject(); auto tableAttr = ::get(tableAttrmap, (*memberTable)->name.originalName); auto tableName = tableAttr.controlName + "." + (*memberTable)->name.originalName; - actionDataField->emplace("name"_cs, tableName); - actionDataField->emplace("handle"_cs, tableAttr.tableHandle); + actionDataField->emplace("name", tableName); + actionDataField->emplace("handle", tableAttr.tableHandle); actionDataJson->append(actionDataField); tableJson->emplace("action_data_table_refs"_cs, actionDataJson); } @@ -462,14 +462,14 @@ bool DpdkContextGenerator::addRefTables(const cstring tbl_name, const IR::P4Tabl auto *selectField = new Util::JsonObject(); auto tableAttr = ::get(tableAttrmap, groupTable->name.originalName); auto tableName = tableAttr.controlName + "." + groupTable->name.originalName; - selectField->emplace("name"_cs, tableName); - selectField->emplace("handle"_cs, tableAttr.tableHandle); + selectField->emplace("name", tableName); + selectField->emplace("handle", tableAttr.tableHandle); selectionJson->append(selectField); - tableJson->emplace("selection_table_refs"_cs, selectionJson); + tableJson->emplace("selection_table_refs", selectionJson); } if (hasActionProfileSelector) { - tableJson->emplace("action_profile"_cs, (*memberTable)->name.originalName); + tableJson->emplace("action_profile", (*memberTable)->name.originalName); } return hasActionProfileSelector; } @@ -511,19 +511,18 @@ void DpdkContextGenerator::addMatchTables(Util::JsonArray *tablesJson) { setDefaultActionHandle(table); tableAttr = ::get(tableAttrmap, table->name.originalName); - tableJson->emplace("actions"_cs, - addActions(table, tableAttr.controlName, isMatchTable)); + tableJson->emplace("actions", addActions(table, tableAttr.controlName, isMatchTable)); if (isMatchTable) { - tableJson->emplace("match_attributes"_cs, + tableJson->emplace("match_attributes", addMatchAttributes(table, tableAttr.controlName)); } - tableJson->emplace("default_action_handle"_cs, tableAttr.default_action_handle); + tableJson->emplace("default_action_handle", tableAttr.default_action_handle); } else { SelectionTable sel; sel.setAttributes(tbl, tableAttrmap); - tableJson->emplace("max_n_groups"_cs, sel.max_n_groups); - tableJson->emplace("max_n_members_per_group"_cs, sel.max_n_members_per_group); - tableJson->emplace("bound_to_action_data_table_handle"_cs, + tableJson->emplace("max_n_groups", sel.max_n_groups); + tableJson->emplace("max_n_members_per_group", sel.max_n_members_per_group); + tableJson->emplace("bound_to_action_data_table_handle", sel.bound_to_action_data_table_handle); } tablesJson->append(tableJson); @@ -535,17 +534,17 @@ void DpdkContextGenerator::addExternInfo(Util::JsonArray *externsJson) { for (auto t : externs) { auto externAttr = ::get(externAttrMap, t->name.name); auto *externJson = new Util::JsonObject(); - externJson->emplace("name"_cs, externAttr.externalName); - externJson->emplace("target_name"_cs, t->name.name); - externJson->emplace("type"_cs, externAttr.externType); + externJson->emplace("name", externAttr.externalName); + externJson->emplace("target_name", t->name.name); + externJson->emplace("type", externAttr.externType); auto *attrJson = new Util::JsonObject(); if (externAttr.externType == "Counter" || externAttr.externType == "DirectCounter") { - attrJson->emplace("type"_cs, externAttr.counterType); + attrJson->emplace("type", externAttr.counterType); } if (externAttr.externType == "DirectCounter" || externAttr.externType == "DirectMeter") { - attrJson->emplace("table_id"_cs, externAttr.table_id); + attrJson->emplace("table_id", externAttr.table_id); } - externJson->emplace("attributes"_cs, attrJson); + externJson->emplace("attributes", attrJson); externsJson->append(externJson); } } @@ -556,15 +555,15 @@ const Util::JsonObject *DpdkContextGenerator::genContextJsonObject() { auto *externsJson = new Util::JsonArray(); struct TopLevelCtxt tlinfo; tlinfo.initTopLevelCtxt(options); - json->emplace("program_name"_cs, tlinfo.progName); - json->emplace("build_date"_cs, tlinfo.buildDate); - json->emplace("compile_command"_cs, tlinfo.compileCommand); - json->emplace("compiler_version"_cs, tlinfo.compilerVersion); - json->emplace("schema_version"_cs, "0.1"_cs); - json->emplace("target"_cs, "DPDK"_cs); - json->emplace("tables"_cs, tablesJson); + json->emplace("program_name", tlinfo.progName); + json->emplace("build_date", tlinfo.buildDate); + json->emplace("compile_command", tlinfo.compileCommand); + json->emplace("compiler_version", tlinfo.compilerVersion); + json->emplace("schema_version", "0.1"); + json->emplace("target", "DPDK"); + json->emplace("tables", tablesJson); addMatchTables(tablesJson); - json->emplace("externs"_cs, externsJson); + json->emplace("externs", externsJson); addExternInfo(externsJson); return json; } diff --git a/backends/dpdk/dpdkContext.h b/backends/dpdk/dpdkContext.h index b40ac9cad41..6b1fabe799c 100644 --- a/backends/dpdk/dpdkContext.h +++ b/backends/dpdk/dpdkContext.h @@ -103,12 +103,12 @@ struct SelectionTable { const std::map &tableAttrmap) { max_n_groups = 0; max_n_members_per_group = 0; - auto n_groups = tbl->properties->getProperty("n_groups_max"_cs); + auto n_groups = tbl->properties->getProperty("n_groups_max"); if (n_groups) { auto n_groups_expr = n_groups->value->to()->expression; max_n_groups = n_groups_expr->to()->asInt(); } - auto n_members = tbl->properties->getProperty("n_members_per_group_max"_cs); + auto n_members = tbl->properties->getProperty("n_members_per_group_max"); if (n_members) { auto n_members_expr = n_members->value->to()->expression; max_n_members_per_group = n_members_expr->to()->asInt(); diff --git a/backends/dpdk/dpdkProgram.cpp b/backends/dpdk/dpdkProgram.cpp index c4cc7ca15bf..971a13012b3 100644 --- a/backends/dpdk/dpdkProgram.cpp +++ b/backends/dpdk/dpdkProgram.cpp @@ -587,10 +587,10 @@ std::optional ConvertToDpdkControl::getNumberFromProperty(const IR::P4Table bool ConvertToDpdkControl::preorder(const IR::P4Table *t) { if (!checkTableValid(t)) return false; - if (t->properties->getProperty("selector"_cs) != nullptr) { + if (t->properties->getProperty("selector") != nullptr) { auto group_id = getMemExprFromProperty(t, "group_id"_cs); auto member_id = getMemExprFromProperty(t, "member_id"_cs); - auto selector_key = t->properties->getProperty("selector"_cs); + auto selector_key = t->properties->getProperty("selector"); auto n_groups_max = getNumberFromProperty(t, "n_groups_max"_cs); auto n_members_per_group_max = getNumberFromProperty(t, "n_members_per_group_max"_cs); diff --git a/backends/dpdk/spec.cpp b/backends/dpdk/spec.cpp index ea6f6859254..2d531060e3a 100644 --- a/backends/dpdk/spec.cpp +++ b/backends/dpdk/spec.cpp @@ -444,13 +444,13 @@ std::ostream &IR::DpdkTable::toSpec(std::ostream &out) const { } } } - auto def = properties->getProperty("default_action"_cs); + auto def = properties->getProperty("default_action"); if (def->isConstant) out << "const"; out << std::endl; - if (auto psa_implementation = properties->getProperty("psa_implementation"_cs)) { + if (auto psa_implementation = properties->getProperty("psa_implementation")) { out << "\taction_selector " << DPDK::toStr(psa_implementation->value) << std::endl; } - if (auto size = properties->getProperty("size"_cs)) { + if (auto size = properties->getProperty("size")) { out << "\tsize " << DPDK::toStr(size->value) << "" << std::endl; } else { out << "\tsize 0x10000" << std::endl; @@ -502,7 +502,7 @@ std::ostream &IR::DpdkLearner::toSpec(std::ostream &out) const { BUG("non-zero default action arguments not supported yet"); } out << std::endl; - if (auto size = properties->getProperty("size"_cs)) { + if (auto size = properties->getProperty("size")) { out << "\tsize " << DPDK::toStr(size->value) << "" << std::endl; } else { out << "\tsize 0x" << std::hex << std::uppercase << default_learner_table_size << std::endl; diff --git a/backends/ebpf/psa/ebpfPsaTable.cpp b/backends/ebpf/psa/ebpfPsaTable.cpp index de75f6e109b..0044652234e 100644 --- a/backends/ebpf/psa/ebpfPsaTable.cpp +++ b/backends/ebpf/psa/ebpfPsaTable.cpp @@ -395,7 +395,7 @@ cstring ActionTranslationVisitorPSA::getParamName(const IR::PathExpression *expr EBPFTablePSA::EBPFTablePSA(const EBPFProgram *program, const IR::TableBlock *table, CodeGenInspector *codeGen) : EBPFTable(program, table, codeGen), implementation(nullptr) { - auto sizeProperty = table->container->properties->getProperty("size"_cs); + auto sizeProperty = table->container->properties->getProperty("size"); if (keyGenerator == nullptr && sizeProperty != nullptr) { ::warning(ErrorType::WARN_IGNORE_PROPERTY, "%1%: property ignored because table does not have a key", sizeProperty); @@ -459,7 +459,7 @@ void EBPFTablePSA::initImplementation() { "%1%: implementation not found, ActionSelector is required", selectorKey->matchType); } - auto emptyGroupAction = table->container->properties->getProperty("psa_empty_group_action"_cs); + auto emptyGroupAction = table->container->properties->getProperty("psa_empty_group_action"); if (!hasActionSelector && emptyGroupAction != nullptr) { ::warning(ErrorType::WARN_UNUSED, "%1%: unused property (ActionSelector not provided)", emptyGroupAction); diff --git a/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp b/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp index ff906747f3b..72e2d567542 100644 --- a/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp +++ b/backends/ebpf/psa/externs/ebpfPsaTableImplementation.cpp @@ -547,7 +547,7 @@ void EBPFActionSelectorPSA::registerTable(const EBPFTablePSA *instance) { if (table == nullptr) { selectors = getSelectorsFromTable(instance); emptyGroupAction = - instance->table->container->properties->getProperty("psa_empty_group_action"_cs); + instance->table->container->properties->getProperty("psa_empty_group_action"); groupsMapSize = instance->size; } else { verifyTableSelectorKeySet(instance); @@ -587,7 +587,7 @@ void EBPFActionSelectorPSA::verifyTableSelectorKeySet(const EBPFTablePSA *instan } void EBPFActionSelectorPSA::verifyTableEmptyGroupAction(const EBPFTablePSA *instance) { - auto iega = instance->table->container->properties->getProperty("psa_empty_group_action"_cs); + auto iega = instance->table->container->properties->getProperty("psa_empty_group_action"); if (emptyGroupAction == nullptr && iega == nullptr) return; // nothing to do here if (emptyGroupAction == nullptr && iega != nullptr) { diff --git a/backends/graphs/graph_visitor.cpp b/backends/graphs/graph_visitor.cpp index 9ce4970f20d..f36c691524c 100644 --- a/backends/graphs/graph_visitor.cpp +++ b/backends/graphs/graph_visitor.cpp @@ -83,14 +83,14 @@ void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node auto *block = new Util::JsonObject(); programBlocks->emplace_back(block); - block->emplace("type"_cs, getPrevType(node_type)); - block->emplace("name"_cs, boost::get_property(*g, boost::graph_name)); + block->emplace("type", getPrevType(node_type)); + block->emplace("name", boost::get_property(*g, boost::graph_name)); auto *nodesArray = new Util::JsonArray(); - block->emplace("nodes"_cs, nodesArray); + block->emplace("nodes", nodesArray); auto *parserEdges = new Util::JsonArray(); - block->emplace("transitions"_cs, parserEdges); + block->emplace("transitions", parserEdges); auto subg = *g; @@ -98,13 +98,13 @@ void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node for (auto &vit = vertices.first; vit != vertices.second; ++vit) { auto node = new Util::JsonObject(); nodesArray->emplace_back(node); - node->emplace("node_nmb"_cs, *vit); + node->emplace("node_nmb", *vit); const auto &vinfo = subg[*vit]; - node->emplace("name"_cs, vinfo.name.escapeJson()); - node->emplace("type"_cs, getType(vinfo.type)); - node->emplace("type_enum"_cs, (unsigned)vinfo.type); + node->emplace("name", vinfo.name.escapeJson()); + node->emplace("type", getType(vinfo.type)); + node->emplace("type_enum", (unsigned)vinfo.type); } auto edges = boost::edges(subg); @@ -116,10 +116,10 @@ void Graph_visitor::forLoopJson(std::vector &graphsArray, PrevType node auto from = boost::source(*eit, subg); auto to = boost::target(*eit, subg); - edge->emplace("from"_cs, from); - edge->emplace("to"_cs, to); + edge->emplace("from", from); + edge->emplace("to", to); - edge->emplace("cond"_cs, boost::get(boost::edge_name, subg, *eit).escapeJson()); + edge->emplace("cond", boost::get(boost::edge_name, subg, *eit).escapeJson()); } } } @@ -199,9 +199,9 @@ void Graph_visitor::process(std::vector &controlGraphsArray, json = new Util::JsonObject(); // Remove '.p4' and path from program name. - json->emplace("name"_cs, filename.stem()); + json->emplace("name", filename.stem()); programBlocks = new Util::JsonArray(); - json->emplace("nodes"_cs, programBlocks); + json->emplace("nodes", programBlocks); forLoopJson(parserGraphsArray, PrevType::Parser); forLoopJson(controlGraphsArray, PrevType::Control); diff --git a/backends/p4tools/common/lib/table_utils.cpp b/backends/p4tools/common/lib/table_utils.cpp index 73f6e49b220..ccfaaf13536 100644 --- a/backends/p4tools/common/lib/table_utils.cpp +++ b/backends/p4tools/common/lib/table_utils.cpp @@ -8,14 +8,14 @@ using namespace P4::literals; void checkTableImmutability(const IR::P4Table &table, TableProperties &properties) { bool isConstant = false; - const auto *entriesAnnotation = table.properties->getProperty("entries"_cs); + const auto *entriesAnnotation = table.properties->getProperty("entries"); if (entriesAnnotation != nullptr) { isConstant = entriesAnnotation->isConstant; } // 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; - const auto *defaultAction = table.properties->getProperty("default_action"_cs); + const auto *defaultAction = table.properties->getProperty("default_action"); CHECK_NULL(defaultAction); properties.defaultIsImmutable = defaultAction->isConstant; } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp b/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp index c61fb54e3ae..f8f9fa6d64b 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/table_stepper.cpp @@ -270,7 +270,7 @@ void Bmv2V1ModelTableStepper::evalTableActionSelector( } bool Bmv2V1ModelTableStepper::checkForActionProfile() { - const auto *impl = table->properties->getProperty("implementation"_cs); + const auto *impl = table->properties->getProperty("implementation"); if (impl == nullptr) { return false; } @@ -312,7 +312,7 @@ bool Bmv2V1ModelTableStepper::checkForActionProfile() { } bool Bmv2V1ModelTableStepper::checkForActionSelector() { - const auto *impl = table->properties->getProperty("implementation"_cs); + const auto *impl = table->properties->getProperty("implementation"); if (impl == nullptr) { return false; } diff --git a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp index 5dcc6d40bf1..acedb7a72b9 100644 --- a/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp +++ b/backends/p4tools/modules/testgen/targets/bmv2/test/small-step/reachability.cpp @@ -83,8 +83,8 @@ auto getNodeByType(const IR::P4Program *program) { }); } -template -const Node *getSpecificNode(const IR::P4Program *program, cstring name) { +template +const Node *getSpecificNode(const IR::P4Program *program, S name) { auto filter = [name](const IR::IDeclaration *d) { CHECK_NULL(d); if (const auto *element = d->to()) return element->name.name == name; @@ -111,13 +111,13 @@ TEST_F(P4CReachability, testParserStatesAndAnnotations) { const auto *program = std::get<0>(result); ASSERT_TRUE(program); const auto *dcg = std::get<1>(result); - const auto *parser = getSpecificNode(program, "ParserI"_cs); + const auto *parser = getSpecificNode(program, "ParserI"); ASSERT_TRUE(parser); // Parser ParserI is reachable. ASSERT_TRUE(dcg->isReachable(program, parser)); - const auto *ingress = getSpecificNode(program, "IngressI"_cs); + const auto *ingress = getSpecificNode(program, "IngressI"); ASSERT_TRUE(ingress); - const auto *engress = getSpecificNode(program, "EgressI"_cs); + const auto *engress = getSpecificNode(program, "EgressI"); ASSERT_TRUE(engress); // IngressI is reachable. ASSERT_TRUE(dcg->isReachable(program, ingress)); @@ -128,10 +128,10 @@ TEST_F(P4CReachability, testParserStatesAndAnnotations) { // IgressI is not reachable from EngressI. ASSERT_TRUE(!dcg->isReachable(engress, ingress)); const auto *indirect = - ingress->to()->getDeclByName("indirect_0"_cs)->to(); + ingress->to()->getDeclByName("indirect_0")->to(); ASSERT_TRUE(indirect); const auto *indirectWs = - ingress->to()->getDeclByName("indirect_ws_0"_cs)->to(); + ingress->to()->getDeclByName("indirect_ws_0")->to(); ASSERT_TRUE(indirectWs); // Inderect table is reachable from ingress ASSERT_TRUE(dcg->isReachable(ingress, indirect)); diff --git a/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp b/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp index 57f3d7a3008..94834321be6 100644 --- a/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp +++ b/backends/p4tools/modules/testgen/targets/pna/shared_table_stepper.cpp @@ -251,7 +251,7 @@ void SharedPnaTableStepper::evalTableActionSelector( } bool SharedPnaTableStepper::checkForActionProfile() { - const auto *impl = table->properties->getProperty("implementation"_cs); + const auto *impl = table->properties->getProperty("implementation"); if (impl == nullptr) { return false; } @@ -293,7 +293,7 @@ bool SharedPnaTableStepper::checkForActionProfile() { } bool SharedPnaTableStepper::checkForActionSelector() { - const auto *impl = table->properties->getProperty("implementation"_cs); + const auto *impl = table->properties->getProperty("implementation"); if (impl == nullptr) { return false; } diff --git a/backends/tc/introspection.cpp b/backends/tc/introspection.cpp index 329654e4aaf..de240b5e314 100644 --- a/backends/tc/introspection.cpp +++ b/backends/tc/introspection.cpp @@ -180,23 +180,23 @@ void IntrospectionGenerator::collectExternInfo() { Util::JsonObject *IntrospectionGenerator::genExternInfo(struct ExternAttributes *extn) { auto externJson = new Util::JsonObject(); - externJson->emplace("name"_cs, extn->name); - externJson->emplace("id"_cs, extn->id); - externJson->emplace("permissions"_cs, extn->permissions); + externJson->emplace("name", extn->name); + externJson->emplace("id", extn->id); + externJson->emplace("permissions", extn->permissions); auto instanceJson = new Util::JsonArray(); for (auto eInstance : extn->instances) { auto eInstanceJson = new Util::JsonObject(); - eInstanceJson->emplace("inst_name"_cs, eInstance->name); - eInstanceJson->emplace("inst_id"_cs, eInstance->id); + eInstanceJson->emplace("inst_name", eInstance->name); + eInstanceJson->emplace("inst_id", eInstance->id); auto paramArray = new Util::JsonArray(); for (auto param : eInstance->keyFields) { auto keyJson = genKeyInfo(param); paramArray->append(keyJson); } - eInstanceJson->emplace("params"_cs, paramArray); + eInstanceJson->emplace("params", paramArray); instanceJson->append(eInstanceJson); } - externJson->emplace("instances"_cs, instanceJson); + externJson->emplace("instances", instanceJson); return externJson; } @@ -216,8 +216,8 @@ void IntrospectionGenerator::genTableJson(Util::JsonArray *tablesJson) { Util::JsonObject *IntrospectionGenerator::genActionInfo(struct ActionAttributes *action) { auto actionJson = new Util::JsonObject(); - actionJson->emplace("id"_cs, action->id); - actionJson->emplace("name"_cs, action->name); + actionJson->emplace("id", action->id); + actionJson->emplace("name", action->name); cstring actionScope; if (action->scope == TableOnly) { actionScope = "TableOnly"_cs; @@ -226,85 +226,85 @@ Util::JsonObject *IntrospectionGenerator::genActionInfo(struct ActionAttributes } else { actionScope = "TableAndDefault"_cs; } - actionJson->emplace("action_scope"_cs, actionScope); + actionJson->emplace("action_scope", actionScope); auto annoArray = new Util::JsonArray(); for (auto anno : action->annotations) { annoArray->append(anno->name); } - actionJson->emplace("annotations"_cs, annoArray); + actionJson->emplace("annotations", annoArray); auto paramArray = new Util::JsonArray(); for (auto param : action->actionParams) { auto paramJson = new Util::JsonObject(); - paramJson->emplace("id"_cs, param->id); - paramJson->emplace("name"_cs, param->name); + paramJson->emplace("id", param->id); + paramJson->emplace("name", param->name); switch (param->dataType) { case TC::BIT_TYPE: { auto paramtype = "bit" + Util::toString(param->bitwidth); - paramJson->emplace("type"_cs, paramtype); + paramJson->emplace("type", paramtype); break; } case TC::DEV_TYPE: { - paramJson->emplace("type"_cs, "dev"); + paramJson->emplace("type", "dev"); break; } case TC::MACADDR_TYPE: { - paramJson->emplace("type"_cs, "macaddr"); + paramJson->emplace("type", "macaddr"); break; } case TC::IPV4_TYPE: { - paramJson->emplace("type"_cs, "ipv4"); + paramJson->emplace("type", "ipv4"); break; } case TC::IPV6_TYPE: { - paramJson->emplace("type"_cs, "ipv6"); + paramJson->emplace("type", "ipv6"); break; } case TC::BE16_TYPE: { - paramJson->emplace("type"_cs, "be16"); + paramJson->emplace("type", "be16"); break; } case TC::BE32_TYPE: { - paramJson->emplace("type"_cs, "be32"); + paramJson->emplace("type", "be32"); break; } case TC::BE64_TYPE: { - paramJson->emplace("type"_cs, "be64"); + paramJson->emplace("type", "be64"); break; } } - paramJson->emplace("bitwidth"_cs, param->bitwidth); + paramJson->emplace("bitwidth", param->bitwidth); paramArray->append(paramJson); } - actionJson->emplace("params"_cs, paramArray); - actionJson->emplace("default_hit_action"_cs, action->defaultHit); - actionJson->emplace("default_miss_action"_cs, action->defaultMiss); + actionJson->emplace("params", paramArray); + actionJson->emplace("default_hit_action", action->defaultHit); + actionJson->emplace("default_miss_action", action->defaultMiss); return actionJson; } Util::JsonObject *IntrospectionGenerator::genKeyInfo(struct KeyFieldAttributes *keyField) { auto keyJson = new Util::JsonObject(); - keyJson->emplace("id"_cs, keyField->id); - keyJson->emplace("name"_cs, keyField->name); - keyJson->emplace("type"_cs, keyField->type); + keyJson->emplace("id", keyField->id); + keyJson->emplace("name", keyField->name); + keyJson->emplace("type", keyField->type); if (keyField->attribute) { - keyJson->emplace("attr"_cs, keyField->attribute); + keyJson->emplace("attr", keyField->attribute); } if (keyField->matchType) { - keyJson->emplace("match_type"_cs, keyField->matchType); + keyJson->emplace("match_type", keyField->matchType); } - keyJson->emplace("bitwidth"_cs, keyField->bitwidth); + keyJson->emplace("bitwidth", keyField->bitwidth); return keyJson; } Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *tbl) { auto tableJson = new Util::JsonObject(); - tableJson->emplace("name"_cs, tbl->name); - tableJson->emplace("id"_cs, tbl->id); - tableJson->emplace("tentries"_cs, tbl->tentries); - tableJson->emplace("permissions"_cs, tbl->permissions); - tableJson->emplace("nummask"_cs, tbl->numMask); + tableJson->emplace("name", tbl->name); + tableJson->emplace("id", tbl->id); + tableJson->emplace("tentries", tbl->tentries); + tableJson->emplace("permissions", tbl->permissions); + tableJson->emplace("nummask", tbl->numMask); if (tbl->keysize != 0) { - tableJson->emplace("keysize"_cs, tbl->keysize); + tableJson->emplace("keysize", tbl->keysize); } auto keysJson = new Util::JsonArray(); for (auto keyField : tbl->keyFields) { @@ -312,7 +312,7 @@ Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *t keysJson->append(keyJson); } if (keysJson->size() != 0) { - tableJson->emplace("keyfields"_cs, keysJson); + tableJson->emplace("keyfields", keysJson); } auto actionsJson = new Util::JsonArray(); for (auto action : tbl->actions) { @@ -320,7 +320,7 @@ Util::JsonObject *IntrospectionGenerator::genTableInfo(struct TableAttributes *t actionsJson->append(actionJson); } if (actionsJson->size() != 0) { - tableJson->emplace("actions"_cs, actionsJson); + tableJson->emplace("actions", actionsJson); } return tableJson; } @@ -333,12 +333,12 @@ const Util::JsonObject *IntrospectionGenerator::genIntrospectionJson() { collectTableInfo(); collectExternInfo(); introspec.initIntrospectionInfo(tcPipeline); - json->emplace("schema_version"_cs, introspec.schemaVersion); - json->emplace("pipeline_name"_cs, introspec.pipelineName); + json->emplace("schema_version", introspec.schemaVersion); + json->emplace("pipeline_name", introspec.pipelineName); genExternJson(externJson); - json->emplace("externs"_cs, externJson); + json->emplace("externs", externJson); genTableJson(tablesJson); - json->emplace("tables"_cs, tablesJson); + json->emplace("tables", tablesJson); return json; } diff --git a/control-plane/bfruntime.cpp b/control-plane/bfruntime.cpp index ac3de53b126..b919fc26835 100644 --- a/control-plane/bfruntime.cpp +++ b/control-plane/bfruntime.cpp @@ -17,6 +17,7 @@ limitations under the License. #include #include "lib/error.h" +#include "lib/json.h" #include "lib/null.h" namespace P4 { @@ -249,13 +250,13 @@ Util::JsonObject *BFRuntimeGenerator::makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type, bool repeated, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id"_cs, id); - dataField->emplace("name"_cs, name); - dataField->emplace("repeated"_cs, repeated); + dataField->emplace("id", id); + dataField->emplace("name", name); + dataField->emplace("repeated", repeated); if (annotations != nullptr) - dataField->emplace("annotations"_cs, annotations); + dataField->emplace("annotations", annotations); else - dataField->emplace("annotations"_cs, new Util::JsonArray()); + dataField->emplace("annotations", new Util::JsonArray()); dataField->emplace("type"_cs, type); return dataField; } @@ -264,14 +265,14 @@ Util::JsonObject *BFRuntimeGenerator::makeContainerDataField(P4Id id, cstring na Util::JsonArray *items, bool repeated, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id"_cs, id); - dataField->emplace("name"_cs, name); - dataField->emplace("repeated"_cs, repeated); + dataField->emplace("id", id); + dataField->emplace("name", name); + dataField->emplace("repeated", repeated); if (annotations != nullptr) - dataField->emplace("annotations"_cs, annotations); + dataField->emplace("annotations", annotations); else - dataField->emplace("annotations"_cs, new Util::JsonArray()); - dataField->emplace("container"_cs, items); + dataField->emplace("annotations", new Util::JsonArray()); + dataField->emplace("container", items); return dataField; } @@ -279,16 +280,16 @@ void BFRuntimeGenerator::addActionDataField(Util::JsonArray *dataJson, P4Id id, const std::string &name, bool mandatory, bool read_only, Util::JsonObject *type, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id"_cs, id); - dataField->emplace("name"_cs, name); - dataField->emplace("repeated"_cs, false); - dataField->emplace("mandatory"_cs, mandatory); - dataField->emplace("read_only"_cs, read_only); + dataField->emplace("id", id); + dataField->emplace("name", name); + dataField->emplace("repeated", false); + dataField->emplace("mandatory", mandatory); + dataField->emplace("read_only", read_only); if (annotations != nullptr) - dataField->emplace("annotations"_cs, annotations); + dataField->emplace("annotations", annotations); else - dataField->emplace("annotations"_cs, new Util::JsonArray()); - dataField->emplace("type"_cs, type); + dataField->emplace("annotations", new Util::JsonArray()); + dataField->emplace("type", type); dataJson->append(dataField); } @@ -296,16 +297,16 @@ void BFRuntimeGenerator::addKeyField(Util::JsonArray *dataJson, P4Id id, cstring bool mandatory, cstring matchType, Util::JsonObject *type, Util::JsonArray *annotations) { auto *dataField = new Util::JsonObject(); - dataField->emplace("id"_cs, id); - dataField->emplace("name"_cs, name); - dataField->emplace("repeated"_cs, false); + dataField->emplace("id", id); + dataField->emplace("name", name); + dataField->emplace("repeated", false); if (annotations != nullptr) - dataField->emplace("annotations"_cs, annotations); + dataField->emplace("annotations", annotations); else - dataField->emplace("annotations"_cs, new Util::JsonArray()); - dataField->emplace("mandatory"_cs, mandatory); - dataField->emplace("match_type"_cs, matchType); - dataField->emplace("type"_cs, type); + dataField->emplace("annotations", new Util::JsonArray()); + dataField->emplace("mandatory", mandatory); + dataField->emplace("match_type", matchType); + dataField->emplace("type", type); dataJson->append(dataField); } @@ -313,17 +314,17 @@ void BFRuntimeGenerator::addKeyField(Util::JsonArray *dataJson, P4Id id, cstring cstring tableType, int64_t size, Util::JsonArray *annotations) { auto *tableJson = new Util::JsonObject(); - tableJson->emplace("name"_cs, name); - tableJson->emplace("id"_cs, id); - tableJson->emplace("table_type"_cs, tableType); - tableJson->emplace("size"_cs, size); - if (annotations != nullptr) tableJson->emplace("annotations"_cs, annotations); - tableJson->emplace("depends_on"_cs, new Util::JsonArray()); + tableJson->emplace("name", name); + tableJson->emplace("id", id); + tableJson->emplace("table_type", tableType); + tableJson->emplace("size", size); + if (annotations != nullptr) tableJson->emplace("annotations", annotations); + tableJson->emplace("depends_on", new Util::JsonArray()); return tableJson; } /* static */ void BFRuntimeGenerator::addToDependsOn(Util::JsonObject *tableJson, P4Id id) { - auto *dependsOnJson = tableJson->get("depends_on"_cs)->to(); + auto *dependsOnJson = tableJson->getAs("depends_on"); CHECK_NULL(dependsOnJson); // Skip duplicates for (auto *d : *dependsOnJson) { @@ -549,17 +550,17 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta } auto *spec = new Util::JsonObject(); const auto &pre = action->preamble(); - spec->emplace("id"_cs, pre.id()); - spec->emplace("name"_cs, pre.name()); + spec->emplace("id", pre.id()); + spec->emplace("name", pre.name()); switch (action_ref.scope()) { case p4configv1::ActionRef::TABLE_AND_DEFAULT: - spec->emplace("action_scope"_cs, "TableAndDefault"); + spec->emplace("action_scope", "TableAndDefault"); break; case p4configv1::ActionRef::TABLE_ONLY: - spec->emplace("action_scope"_cs, "TableOnly"); + spec->emplace("action_scope", "TableOnly"); break; case p4configv1::ActionRef::DEFAULT_ONLY: - spec->emplace("action_scope"_cs, "DefaultOnly"); + spec->emplace("action_scope", "DefaultOnly"); break; default: ::error(ErrorType::ERR_INVALID, "Invalid action ref scope '%1%' in P4Info", @@ -595,9 +596,9 @@ Util::JsonArray *BFRuntimeGenerator::makeActionSpecs(const p4configv1::Table &ta void BFRuntimeGenerator::addLearnFilterCommon(Util::JsonArray *learnFiltersJson, const BFRuntimeGenerator::Digest &digest) const { auto *learnFilterJson = new Util::JsonObject(); - learnFilterJson->emplace("name"_cs, digest.name); - learnFilterJson->emplace("id"_cs, digest.id); - learnFilterJson->emplace("annotations"_cs, digest.annotations); + learnFilterJson->emplace("name", digest.name); + learnFilterJson->emplace("id", digest.id); + learnFilterJson->emplace("annotations", digest.annotations); auto *fieldsJson = new Util::JsonArray(); transformTypeSpecToDataFields(fieldsJson, digest.typeSpec, "Digest"_cs, digest.name); @@ -667,7 +668,7 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { if (!addActionProfIds(table, tableJson)) continue; - tableJson->emplace("has_const_default_action"_cs, table.const_default_action_id() != 0); + tableJson->emplace("has_const_default_action", table.const_default_action_id() != 0); // will be set to true by the for loop if the match key includes a // ternary, range or optional match @@ -704,8 +705,8 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { std::regex_search(s, sm, sliceRegex); if (sm.size() == 3) { auto *isFieldSliceAnnot = new Util::JsonObject(); - isFieldSliceAnnot->emplace("name"_cs, "isFieldSlice"); - isFieldSliceAnnot->emplace("value"_cs, "true"); + isFieldSliceAnnot->emplace("name", "isFieldSlice"); + isFieldSliceAnnot->emplace("value", "true"); annotations->append(isFieldSliceAnnot); } @@ -751,7 +752,7 @@ void BFRuntimeGenerator::addMatchTables(Util::JsonArray *tablesJson) const { // will be used as an offset for other P4-dependent fields (e.g. direct // register fields). P4Id maxActionParamId = 0; - cstring tableType = tableJson->get("table_type"_cs)->to()->getString(); + cstring tableType = tableJson->getAs("table_type")->getString(); if (tableType == "MatchAction_Direct") { tableJson->emplace("action_specs"_cs, makeActionSpecs(table, &maxActionParamId)); } else if (tableType == "MatchAction_Indirect") { @@ -851,10 +852,10 @@ void BFRuntimeGenerator::addRegisters(Util::JsonArray *tablesJson) const { const Util::JsonObject *BFRuntimeGenerator::genSchema() const { auto *json = new Util::JsonObject(); - json->emplace("schema_version"_cs, "1.0.0"_cs); + json->emplace("schema_version", "1.0.0"_cs); auto *tablesJson = new Util::JsonArray(); - json->emplace("tables"_cs, tablesJson); + json->emplace("tables", tablesJson); addMatchTables(tablesJson); addActionProfs(tablesJson); diff --git a/control-plane/bfruntime.h b/control-plane/bfruntime.h index 79935e9b24b..892f29f5b80 100644 --- a/control-plane/bfruntime.h +++ b/control-plane/bfruntime.h @@ -55,7 +55,7 @@ static inline constexpr P4Id getIdPrefix(P4Id id) { return ((id >> 24) & 0xff); static inline Util::JsonObject *findJsonTable(Util::JsonArray *tablesJson, cstring tblName) { for (auto *t : *tablesJson) { auto *tblObj = t->to(); - auto tName = tblObj->get("name"_cs)->to()->getString(); + auto tName = tblObj->getAs("name")->getString(); if (tName == tblName) { return tblObj; } @@ -67,7 +67,7 @@ static inline Util::JsonObject *transformAnnotation(const cstring &annotation) { auto *annotationJson = new Util::JsonObject(); // TODO(antonin): annotation string will need to be parsed so we can have it // in key/value format here. - annotationJson->emplace("name"_cs, annotation.escapeJson()); + annotationJson->emplace("name", annotation.escapeJson()); return annotationJson; } @@ -133,63 +133,64 @@ static inline const p4configv1::DirectMeter *findDirectMeter(const p4configv1::P static inline Util::JsonObject *makeType(cstring type) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type"_cs, type); + typeObj->emplace("type", type); return typeObj; } template ::value, int>::type = 0> static inline Util::JsonObject *makeType(cstring type, T defaultValue) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type"_cs, type); - typeObj->emplace("default_value"_cs, defaultValue); + typeObj->emplace("type", type); + typeObj->emplace("default_value", defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeBool(std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type"_cs, "bool"); - if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); + typeObj->emplace("type", "bool"); + if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeBytes(int width, std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type"_cs, "bytes"); - typeObj->emplace("width"_cs, width); - if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); + typeObj->emplace("type", "bytes"); + typeObj->emplace("width", width); + if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); return typeObj; } static inline Util::JsonObject *makeTypeEnum(const std::vector &choices, std::optional defaultValue = std::nullopt) { auto *typeObj = new Util::JsonObject(); - typeObj->emplace("type"_cs, "string"); + typeObj->emplace("type", "string"); auto *choicesArray = new Util::JsonArray(); for (auto choice : choices) choicesArray->append(choice); - typeObj->emplace("choices"_cs, choicesArray); - if (defaultValue != std::nullopt) typeObj->emplace("default_value"_cs, *defaultValue); + typeObj->emplace("choices", choicesArray); + if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue); return typeObj; } static inline void addSingleton(Util::JsonArray *dataJson, Util::JsonObject *dataField, bool mandatory, bool readOnly) { auto *singletonJson = new Util::JsonObject(); - singletonJson->emplace("mandatory"_cs, mandatory); - singletonJson->emplace("read_only"_cs, readOnly); - singletonJson->emplace("singleton"_cs, dataField); + singletonJson->emplace("mandatory", mandatory); + singletonJson->emplace("read_only", readOnly); + singletonJson->emplace("singleton", dataField); dataJson->append(singletonJson); } static inline void addOneOf(Util::JsonArray *dataJson, Util::JsonArray *choicesJson, bool mandatory, bool readOnly) { auto *oneOfJson = new Util::JsonObject(); - oneOfJson->emplace("mandatory"_cs, mandatory); - oneOfJson->emplace("read_only"_cs, readOnly); - oneOfJson->emplace("oneof"_cs, choicesJson); + oneOfJson->emplace("mandatory", mandatory); + oneOfJson->emplace("read_only", readOnly); + oneOfJson->emplace("oneof", choicesJson); dataJson->append(oneOfJson); } +// FIXME: Switch to std::string_view static inline std::optional transformMatchType( p4configv1::MatchField_MatchType matchType) { switch (matchType) { @@ -210,6 +211,7 @@ static inline std::optional transformMatchType( } } +// FIXME: Switch to std::string_view static inline std::optional transformOtherMatchType(std::string matchType) { if (matchType == "atcam_partition_index") return "ATCAM"_cs; if (matchType == "dleft_hash") return "DLEFT_HASH"_cs; diff --git a/control-plane/p4RuntimeArchHandler.cpp b/control-plane/p4RuntimeArchHandler.cpp index 8c8466acff8..7b7104da194 100644 --- a/control-plane/p4RuntimeArchHandler.cpp +++ b/control-plane/p4RuntimeArchHandler.cpp @@ -94,7 +94,7 @@ int64_t getTableSize(const IR::P4Table *table) { // default table size. const int64_t defaultTableSize = P4V1::V1Model::instance.tableAttributes.defaultTableSize; - auto sizeProperty = table->properties->getProperty("size"_cs); + auto sizeProperty = table->properties->getProperty("size"); if (sizeProperty == nullptr) { return defaultTableSize; } diff --git a/control-plane/p4RuntimeArchStandard.h b/control-plane/p4RuntimeArchStandard.h index 4bd40bfdd33..64f646f728e 100644 --- a/control-plane/p4RuntimeArchStandard.h +++ b/control-plane/p4RuntimeArchStandard.h @@ -1058,7 +1058,7 @@ class P4RuntimeArchHandlerPSAPNA : public P4RuntimeArchHandlerCommon { /// @return true if @table's 'psa_idle_timeout' property exists and is true. This /// indicates that @table supports entry ageing. static bool getSupportsTimeout(const IR::P4Table *table) { - auto timeout = table->properties->getProperty("psa_idle_timeout"_cs); + auto timeout = table->properties->getProperty("psa_idle_timeout"); if (timeout == nullptr) return false; diff --git a/frontends/p4/checkNamedArgs.cpp b/frontends/p4/checkNamedArgs.cpp index a26c0745af4..431592ae86f 100644 --- a/frontends/p4/checkNamedArgs.cpp +++ b/frontends/p4/checkNamedArgs.cpp @@ -16,12 +16,14 @@ limitations under the License. #include "checkNamedArgs.h" +#include "lib/hash.h" + namespace P4 { bool CheckNamedArgs::checkArguments(const IR::Vector *arguments) { bool first = true; bool hasName = false; - std::map found; + absl::flat_hash_map found; for (auto arg : *arguments) { cstring argName = arg->name.name; diff --git a/frontends/p4/parameterSubstitution.h b/frontends/p4/parameterSubstitution.h index 2da2c51bd91..15fcc0c4f08 100644 --- a/frontends/p4/parameterSubstitution.h +++ b/frontends/p4/parameterSubstitution.h @@ -22,7 +22,6 @@ limitations under the License. #include "ir/ir.h" #include "lib/cstring.h" #include "lib/enumerator.h" -#include "lib/exceptions.h" namespace P4 { @@ -30,16 +29,6 @@ namespace P4 { parameter identity is not important, but the parameter name is. */ class ParameterSubstitution : public IHasDbPrint { protected: - // Parameter names are unique for a procedure, so each name - // should show up only once. - std::map parameterValues; - /// Map from parameter name to parameter. - std::map parametersByName; - /// Parameters in the order they were added. - std::vector parameters; - /// If created using populate this is non-null. - const IR::ParameterList *paramList = nullptr; - bool containsName(cstring name) const { return parameterValues.find(name) != parameterValues.end(); } @@ -94,6 +83,17 @@ class ParameterSubstitution : public IHasDbPrint { out << dbp(s.second) << "=>" << dbp(lookupByName(s.first)) << std::endl; } } + + private: + // Parameter names are unique for a procedure, so each name + // should show up only once. + absl::flat_hash_map parameterValues; + /// Map from parameter name to parameter. + absl::flat_hash_map parametersByName; + /// Parameters in the order they were added. + std::vector parameters; + /// If created using populate this is non-null. + const IR::ParameterList *paramList = nullptr; }; } // namespace P4 diff --git a/frontends/p4/typeChecking/typeChecker.cpp b/frontends/p4/typeChecking/typeChecker.cpp index 5a420e1d7dc..811b7352e31 100644 --- a/frontends/p4/typeChecking/typeChecker.cpp +++ b/frontends/p4/typeChecking/typeChecker.cpp @@ -18,6 +18,7 @@ limitations under the License. #include +#include "absl/container/flat_hash_map.h" #include "frontends/common/constantFolding.h" #include "frontends/common/resolveReferences/referenceMap.h" #include "frontends/common/resolveReferences/resolveReferences.h" @@ -27,6 +28,7 @@ limitations under the License. #include "frontends/p4/toP4/toP4.h" #include "lib/algorithm.h" #include "lib/cstring.h" +#include "lib/hash.h" #include "lib/log.h" #include "syntacticEquivalence.h" #include "typeConstraints.h" @@ -3486,7 +3488,7 @@ const IR::Expression *TypeInference::actionCall(bool inActionList, auto params = new IR::ParameterList; // keep track of parameters that have not been matched yet - std::map left; + absl::flat_hash_map left; for (auto p : baseType->parameters->parameters) left.emplace(p->name, p); auto paramIt = baseType->parameters->parameters.begin(); @@ -3513,10 +3515,10 @@ const IR::Expression *TypeInference::actionCall(bool inActionList, } LOG2("Action parameter " << dbp(param)); - auto leftIt = left.find(param->name.name); - // This should have been checked by the CheckNamedArgs pass. - BUG_CHECK(leftIt != left.end(), "%1%: Duplicate argument name?", param->name); - left.erase(leftIt); + if (!left.erase(param->name)) { + // This should have been checked by the CheckNamedArgs pass. + BUG("%1%: Duplicate argument name?", param->name); + } auto paramType = getType(param); auto argType = getType(arg); @@ -4082,7 +4084,7 @@ const IR::Node *TypeInference::postorder(IR::SwitchStatement *stat) { if (auto ae = type->to()) { // switch (table.apply(...)) - std::map foundLabels; + absl::flat_hash_map foundLabels; const IR::Node *foundDefault = nullptr; for (auto c : stat->cases) { if (c->label->is()) { @@ -4092,10 +4094,9 @@ const IR::Node *TypeInference::postorder(IR::SwitchStatement *stat) { continue; } else if (auto pe = c->label->to()) { cstring label = pe->path->name.name; - auto it = foundLabels.find(label); - if (it != foundLabels.end()) + auto [it, inserted] = foundLabels.emplace(label, c->label); + if (!inserted) typeError("%1%: 'switch' label duplicates %2%", c->label, it->second); - foundLabels.emplace(label, c->label); if (!ae->contains(label)) typeError("%1% is not a legal label (action name)", c->label); } else { diff --git a/frontends/p4/typeChecking/typeUnification.cpp b/frontends/p4/typeChecking/typeUnification.cpp index fcbe426cd9c..ea8e5863b87 100644 --- a/frontends/p4/typeChecking/typeUnification.cpp +++ b/frontends/p4/typeChecking/typeUnification.cpp @@ -57,7 +57,7 @@ bool TypeUnification::unifyCall(const BinaryConstraint *constraint) { auto paramIt = dest->parameters->begin(); // keep track of parameters that have not been matched yet - std::map left; + absl::flat_hash_map left; for (auto p : dest->parameters->parameters) left.emplace(p->name, p); for (auto arg : *src->arguments) { @@ -77,10 +77,10 @@ bool TypeUnification::unifyCall(const BinaryConstraint *constraint) { param = *paramIt; } - auto leftIt = left.find(param->name.name); - // This shold have been checked by the CheckNamedArgs pass. - BUG_CHECK(leftIt != left.end(), "%1%: Duplicate argument name?", param->name); - left.erase(leftIt); + if (!left.erase(param->name)) { + // This shold have been checked by the CheckNamedArgs pass. + BUG("%1%: Duplicate argument name?", param->name); + } if (arg->type->is() && param->direction != IR::Direction::Out) return constraint->reportError( diff --git a/frontends/p4/validateParsedProgram.cpp b/frontends/p4/validateParsedProgram.cpp index d301865004e..58383c6db65 100644 --- a/frontends/p4/validateParsedProgram.cpp +++ b/frontends/p4/validateParsedProgram.cpp @@ -111,15 +111,12 @@ void ValidateParsedProgram::postorder(const IR::P4Table *t) { void ValidateParsedProgram::distinctParameters(const IR::TypeParameters *typeParams, const IR::ParameterList *apply, const IR::ParameterList *constr) { - std::map found; + absl::flat_hash_map found; for (auto p : typeParams->parameters) found.emplace(p->getName(), p); for (auto p : apply->parameters) { - auto it = found.find(p->getName()); - if (it != found.end()) - ::error(ErrorType::ERR_DUPLICATE, "%1% duplicates %2%.", it->second, p); - else - found.emplace(p->getName(), p); + auto [it, inserted] = found.emplace(p->getName(), p); + if (!inserted) ::error(ErrorType::ERR_DUPLICATE, "%1% duplicates %2%.", it->second, p); } for (auto p : constr->parameters) { auto it = found.find(p->getName()); diff --git a/ir/base.def b/ir/base.def index 68500cb97b6..a1e6d3f29e1 100644 --- a/ir/base.def +++ b/ir/base.def @@ -65,6 +65,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; } /// A general namespace can have multiple declarations with the same name diff --git a/ir/id.h b/ir/id.h index ede6526b380..22eced72488 100644 --- a/ir/id.h +++ b/ir/id.h @@ -19,6 +19,7 @@ limitations under the License. #include "lib/cstring.h" #include "lib/exceptions.h" +#include "lib/hash.h" #include "lib/source_file.h" namespace IR { @@ -61,4 +62,12 @@ struct ID : Util::IHasSourceInfo { }; } // namespace IR + +namespace Util { +template <> +struct Hasher { + size_t operator()(const IR::ID &id) const { return Util::Hash{}(id.name); } +}; +} // namespace Util + #endif /* IR_ID_H_ */ diff --git a/ir/indexed_vector.h b/ir/indexed_vector.h index e32f20a72d6..fd1cc9dd198 100644 --- a/ir/indexed_vector.h +++ b/ir/indexed_vector.h @@ -23,8 +23,8 @@ limitations under the License. #include "lib/error.h" #include "lib/map.h" #include "lib/null.h" -#include "lib/ordered_map.h" #include "lib/safe_vector.h" +#include "lib/string_map.h" class JSONLoader; @@ -36,7 +36,7 @@ namespace IR { */ template class IndexedVector : public Vector { - ordered_map declarations; + string_map declarations; bool invalid = false; // set when an error occurs; then we don't // expect the validity check to succeed. @@ -44,13 +44,10 @@ class IndexedVector : public Vector { if (a == nullptr || !a->template is()) return; auto decl = a->template to(); auto name = decl->getName().name; - auto previous = declarations.find(name); - if (previous != declarations.end()) { + auto [it, inserted] = declarations.emplace(name, decl); + if (!inserted) { invalid = true; - ::error(ErrorType::ERR_DUPLICATE, "%1%: Duplicates declaration %2%", a, - previous->second); - } else { - declarations[name] = decl; + ::error(ErrorType::ERR_DUPLICATE, "%1%: Duplicates declaration %2%", a, it->second); } } void removeFromMap(const T *a) { @@ -70,7 +67,7 @@ class IndexedVector : public Vector { IndexedVector() = default; IndexedVector(const IndexedVector &) = default; IndexedVector(IndexedVector &&) = default; - IndexedVector(const std::initializer_list &a) : Vector(a) { + IndexedVector(std::initializer_list a) : Vector(a) { for (auto el : *this) insertInMap(el); } IndexedVector &operator=(const IndexedVector &) = default; @@ -96,12 +93,23 @@ class IndexedVector : public Vector { if (it == declarations.end()) return nullptr; return it->second; } + const IDeclaration *getDeclaration(std::string_view name) const { + auto it = declarations.find(name); + if (it == declarations.end()) return nullptr; + return it->second; + } template const U *getDeclaration(cstring name) const { auto it = declarations.find(name); if (it == declarations.end()) return nullptr; return it->second->template to(); } + template + const U *getDeclaration(std::string_view name) const { + auto it = declarations.find(name); + if (it == declarations.end()) return nullptr; + return it->second->template to(); + } Util::Enumerator *getDeclarations() const { return Util::enumerate(Values(declarations)); } diff --git a/ir/ir.cpp b/ir/ir.cpp index 2322377438e..002482c5eda 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -20,11 +20,11 @@ limitations under the License. #include #include -#include -#include #include #include +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "ir/declaration.h" #include "ir/id.h" #include "ir/indexed_vector.h" @@ -89,7 +89,7 @@ Util::Enumerator *INestedNamespace::getDeclarations() cons bool IFunctional::callMatches(const Vector *arguments) const { auto paramList = getParameters()->parameters; - std::map paramNames; + absl::flat_hash_map paramNames; for (auto param : paramList) paramNames.emplace(param->name.name, param); size_t index = 0; @@ -100,12 +100,10 @@ bool IFunctional::callMatches(const Vector *arguments) const { cstring argName = arg->name; if (argName.isNullOrEmpty()) argName = paramList.at(index)->name.name; - auto it = paramNames.find(argName); - if (it == paramNames.end()) + if (!paramNames.erase(argName)) { // Argument name does not match a parameter return false; - else - paramNames.erase(it); + } index++; } // Check if all remaining parameters have default values @@ -117,16 +115,14 @@ bool IFunctional::callMatches(const Vector *arguments) const { } void IGeneralNamespace::checkDuplicateDeclarations() const { - std::unordered_map seen; - for (auto decl : *getDeclarations()) { + absl::flat_hash_set seen; + for (const auto *decl : *getDeclarations()) { IR::ID name = decl->getName(); - auto f = seen.find(name.name); - if (f != seen.end()) { + auto [it, inserted] = seen.emplace(name); + if (!inserted) { ::error(ErrorType::ERR_DUPLICATE, - "Duplicate declaration of %1%: previous declaration at %2%", name, - f->second.srcInfo); + "Duplicate declaration of %1%: previous declaration at %2%", name, it->srcInfo); } - seen.emplace(name.name, name); } } diff --git a/ir/ir.def b/ir/ir.def index ee7cd965529..f1365e94a7c 100644 --- a/ir/ir.def +++ b/ir/ir.def @@ -65,6 +65,8 @@ class ParserState : ISimpleNamespace, Declaration, IAnnotated { return components.getDeclarations(); } const IDeclaration* getDeclByName(cstring name) const override { return components.getDeclaration(name); } + const IDeclaration* getDeclByName(std::string_view name) const override { + return components.getDeclaration(name); } static const cstring accept; static const cstring reject; @@ -96,6 +98,11 @@ class P4Parser : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, I auto decl = parserLocals.getDeclaration(name); if (!decl) decl = states.getDeclaration(name); return decl; } + IDeclaration getDeclByName(std::string_view name) const override { + auto decl = parserLocals.getDeclaration(name); + if (!decl) decl = states.getDeclaration(name); + return decl; } + Type_Method getApplyMethodType() const override { return type->getApplyMethodType(); } ParameterList getApplyParameters() const override { return type->getApplyParameters(); } Type_Method getConstructorMethodType() const override; @@ -132,6 +139,8 @@ class P4Control : Type_Declaration, INestedNamespace, ISimpleNamespace, IApply, Type_Method getConstructorMethodType() const override; IDeclaration getDeclByName(cstring name) const override { return controlLocals.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return controlLocals.getDeclaration(name); } ParameterList getConstructorParameters() const override { return constructorParams; } Type getType() const override { return this->type; } #apply @@ -152,6 +161,8 @@ class P4Action : Declaration, ISimpleNamespace, IAnnotated, IFunctional { return parameters->getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return parameters->getDeclByName(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return parameters->getDeclByName(name); } Annotations getAnnotations() const override { return annotations; } ParameterList getParameters() const override { return parameters; } } @@ -163,6 +174,8 @@ class Type_Error : ISimpleNamespace, Type_Declaration { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return members.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return members.getDeclaration(name); } validate{ members.check_null(); } } @@ -173,6 +186,8 @@ class Declaration_MatchKind : ISimpleNamespace { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return members.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return members.getDeclaration(name); } validate{ members.check_null(); } } @@ -290,6 +305,10 @@ class TableProperties : ISimpleNamespace { return properties.getDeclaration(name); } IDeclaration getDeclByName(cstring name) const override { return properties.getDeclaration(name); } + Property getProperty(std::string_view name) const { + return properties.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return properties.getDeclaration(name); } void push_back(Property prop) { properties.push_back(prop); } static const cstring actionsPropertyName; @@ -473,6 +492,8 @@ class BlockStatement : Statement, ISimpleNamespace, IAnnotated { optional inline IndexedVector components; IDeclaration getDeclByName(cstring name) const override { return components.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return components.getDeclaration(name); } Util::Enumerator* getDeclarations() const override { return components.getDeclarations(); } void push_back(StatOrDecl st) { components.push_back(st); } @@ -529,6 +550,8 @@ class ForStatement : LoopStatement { Statement body; IDeclaration getDeclByName(cstring name) const override { return init.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return init.getDeclaration(name); } Util::Enumerator* getDeclarations() const override { return init.getDeclarations(); } visit_children; @@ -551,6 +574,8 @@ class ForInStatement : LoopStatement { : 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 { + return decl && decl->name.name == name ? decl : nullptr; } Util::Enumerator* getDeclarations() const override { if (decl) return new Util::SingleEnumerator(decl); return new Util::EmptyEnumerator(); } @@ -574,6 +599,8 @@ class Function : Declaration, IFunctional, IAnnotated, ISimpleNamespace, INested return type->parameters->getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return type->parameters->getDeclByName(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return type->parameters->getDeclByName(name); } std::vector getNestedNamespaces() const override { return { type->typeParameters }; } Annotations getAnnotations() const override { return annotations; } diff --git a/ir/json_loader.h b/ir/json_loader.h index eefbd42cbd2..c11ce5848ff 100644 --- a/ir/json_loader.h +++ b/ir/json_loader.h @@ -170,6 +170,17 @@ class JSONLoader { v.insert(temp); } } + template + void unpack_json(string_map &v) { + std::pair temp; + for (auto e : json->as()) { + JsonString *k = new JsonString(e.first); + load(k, temp.first); + load(e.second, temp.second); + v.insert(temp); + } + } + template void unpack_json(std::multimap &v) { std::pair temp; diff --git a/ir/node.cpp b/ir/node.cpp index da7d521ce0f..13498216f06 100644 --- a/ir/node.cpp +++ b/ir/node.cpp @@ -120,18 +120,18 @@ Util::JsonObject *IR::Node::sourceInfoJsonObj() const { // Added source_info for jsonObject when "--fromJSON" flag is used // which parameters are saved in srcInfo fileds(filename, line, column and srcBrief) auto json1 = new Util::JsonObject(); - json1->emplace("filename"_cs, srcInfo.filename); - json1->emplace("line"_cs, srcInfo.line); - json1->emplace("column"_cs, srcInfo.column); - json1->emplace("source_fragment"_cs, srcInfo.srcBrief); + json1->emplace("filename", srcInfo.filename); + json1->emplace("line", srcInfo.line); + json1->emplace("column", srcInfo.column); + json1->emplace("source_fragment", srcInfo.srcBrief); return json1; } } else { auto json = new Util::JsonObject(); - json->emplace("filename"_cs, fName); - json->emplace("line"_cs, lineNumber); - json->emplace("column"_cs, columnNumber); - json->emplace("source_fragment"_cs, si.toBriefSourceFragment().escapeJson()); + json->emplace("filename", fName); + json->emplace("line", lineNumber); + json->emplace("column", columnNumber); + json->emplace("source_fragment", si.toBriefSourceFragment().escapeJson()); return json; } } diff --git a/ir/type.def b/ir/type.def index e4a547fd0dc..1bc9920f13c 100644 --- a/ir/type.def +++ b/ir/type.def @@ -209,11 +209,14 @@ class ParameterList : ISimpleNamespace { bool empty() const { return size() == 0; } IR::Parameter getParameter(cstring name) const { return parameters.getDeclaration(name); } + IR::Parameter getParameter(std::string_view name) const { + return parameters.getDeclaration(name); } IR::Parameter getParameter(unsigned index) const { for (auto ¶m : parameters) if (0 == index--) return param; BUG("Only %1% parameters; index #%2% requested", size(), size()+index); } IR::IDeclaration getDeclByName(cstring name) const override { return getParameter(name); } + IR::IDeclaration getDeclByName(std::string_view name) const override { return getParameter(name); } void push_back(const Parameter *p) { parameters.push_back(p); } toString { std::string result = ""; @@ -311,6 +314,8 @@ class TypeParameters : ISimpleNamespace { size_t size() const { return parameters.size(); } IR::IDeclaration getDeclByName(cstring name) const override { return parameters.getDeclaration(name); } + IR::IDeclaration getDeclByName(std::string_view name) const override { + return parameters.getDeclaration(name); } void push_back(Type_Var tv) { parameters.push_back(tv); } validate{ parameters.check_null(); } toString { @@ -351,7 +356,7 @@ abstract Type_StructLike : Type_Declaration, INestedNamespace, ISimpleNamespace, for (auto f : fields) { if (f->name == name) return index_pos; - index_pos++; + index_pos++; } return -1; } @@ -379,6 +384,8 @@ abstract Type_StructLike : Type_Declaration, INestedNamespace, ISimpleNamespace, return rv; } IR::IDeclaration getDeclByName(cstring name) const override { return fields.getDeclaration(name); } + IR::IDeclaration getDeclByName(std::string_view name) const override { + return fields.getDeclaration(name); } validate{ fields.check_null(); } dbprint; #apply @@ -509,6 +516,8 @@ abstract Type_ArchBlock : Type_Declaration, IMayBeGenericType, IAnnotated, ISimp return typeParameters->getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return typeParameters->getDeclByName(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return typeParameters->getDeclByName(name); } } class Type_Package : Type_ArchBlock, IContainer, ISimpleNamespace { @@ -523,6 +532,10 @@ class Type_Package : Type_ArchBlock, IContainer, ISimpleNamespace { auto decl = constructorParams->getDeclByName(name); if (!decl) decl = typeParameters->getDeclByName(name); return decl; } + IDeclaration getDeclByName(std::string_view name) const override { + auto decl = constructorParams->getDeclByName(name); + if (!decl) decl = typeParameters->getDeclByName(name); + return decl; } } class Type_Parser : Type_ArchBlock, IApply { @@ -640,6 +653,8 @@ class Type_Enum : Type_Declaration, ISimpleNamespace, IAnnotated { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return members.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return members.getDeclaration(name); } #nodbprint validate{ members.check_null(); } } @@ -661,6 +676,8 @@ class Type_SerEnum : Type_Declaration, ISimpleNamespace, IAnnotated { return members.getDeclarations(); } IDeclaration getDeclByName(cstring name) const override { return members.getDeclaration(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return members.getDeclaration(name); } #nodbprint validate{ members.check_null(); } } @@ -706,6 +723,10 @@ abstract Type_MethodBase : Type, IMayBeGenericType, ISimpleNamespace { auto decl = parameters->getDeclByName(name); if (!decl) decl = typeParameters->getDeclByName(name); return decl; } + IDeclaration getDeclByName(std::string_view name) const override { + auto decl = parameters->getDeclByName(name); + if (!decl) decl = typeParameters->getDeclByName(name); + return decl; } } /// Type for a method or function. @@ -758,6 +779,8 @@ class Method : Declaration, IAnnotated, IFunctional, ISimpleNamespace { // annotations can refer to parameters, so need to look them up in scope IDeclaration getDeclByName(cstring name) const override { return type->parameters->getDeclByName(name); } + IDeclaration getDeclByName(std::string_view name) const override { + return type->parameters->getDeclByName(name); } Util::Enumerator *getDeclarations() const override { return type->parameters->getDeclarations(); } } diff --git a/ir/v1.def b/ir/v1.def index 4edff84727e..0cf0583ee16 100644 --- a/ir/v1.def +++ b/ir/v1.def @@ -435,6 +435,7 @@ class AttribLocals : ISimpleNamespace { Util::Enumerator *getDeclarations() const override { return locals.valueEnumerator()->as(); } IDeclaration getDeclByName(cstring name) const override { return locals[name]; } + IDeclaration getDeclByName(std::string_view name) const override { return locals[cstring(name)]; } } class Attribute : Declaration { diff --git a/lib/json.cpp b/lib/json.cpp index 7620ab07c15..9641b6e2038 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -19,6 +19,7 @@ limitations under the License. #include #include +#include "absl/strings/str_cat.h" #include "indent.h" #include "lib/big_int_util.h" @@ -71,11 +72,18 @@ bool JsonValue::operator==(const cstring &s) const { return tag == Kind::String ? s == str : false; } bool JsonValue::operator==(const std::string &s) const { - return tag == Kind::String ? cstring(s) == str : false; + // Note that it does not make sense to convert `s` to `cstring` here. Such + // conversion involves cstring cache lookup and strcmp() in any case. Here + // we just doing strcmp() saving 1-2 map lookups + return tag == Kind::String ? str == s : false; } bool JsonValue::operator==(const char *s) const { - return tag == Kind::String ? cstring(s) == str : false; + // Note that it does not make sense to convert `s` to `cstring` here. Such + // conversion involves cstring cache lookup and strcmp() in any case. Here + // we just doing strcmp() saving 1-2 map lookups + return tag == Kind::String ? str == s : false; } + bool JsonValue::operator==(const JsonValue &other) const { if (tag != other.tag) return false; switch (tag) { @@ -167,7 +175,21 @@ JsonObject *JsonObject::emplace(cstring label, IJson *value) { "for a label which already exists ") + label.string() + " " + s.string()); } - ordered_map::emplace(label, value); + base::emplace(label, value); + return this; +} + +JsonObject *JsonObject::emplace(std::string_view label, IJson *value) { + if (label.empty()) throw std::logic_error("Empty label"); + auto j = get(label); + if (j != nullptr) { + cstring s = value->toString(); + throw std::logic_error( + absl::StrCat("Attempt to add to json object a value " + "for a label which already exists ", + label, " ", s.string_view())); + } + base::emplace(label, value); return this; } diff --git a/lib/json.h b/lib/json.h index 5b0f53c8730..5faee55960f 100644 --- a/lib/json.h +++ b/lib/json.h @@ -25,11 +25,11 @@ limitations under the License. #ifdef P4C_GTEST_ENABLED #include "gtest/gtest_prod.h" #endif -#include "lib/big_int_util.h" +#include "lib/big_int.h" #include "lib/castable.h" #include "lib/cstring.h" #include "lib/map.h" -#include "lib/ordered_map.h" +#include "lib/string_map.h" namespace Test { class TestJson; @@ -55,32 +55,36 @@ class JsonValue final : public IJson { public: enum Kind { String, Number, True, False, Null }; JsonValue() : tag(Kind::Null) {} - JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT - JsonValue(big_int v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(int v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(long v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(long long v); // NOLINT - JsonValue(unsigned v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(unsigned long v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(unsigned long long v); // NOLINT - JsonValue(double v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(float v) : tag(Kind::Number), value(v) {} // NOLINT - JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT - JsonValue(const std::string &s) : tag(Kind::String), str(s) {} // NOLINT + JsonValue(bool b) : tag(b ? Kind::True : Kind::False) {} // NOLINT + JsonValue(big_int v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(int v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(long v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(long long v); // NOLINT + JsonValue(unsigned v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(unsigned long v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(unsigned long long v); // NOLINT + JsonValue(double v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(float v) : tag(Kind::Number), value(v) {} // NOLINT + JsonValue(cstring s) : tag(Kind::String), str(s) {} // NOLINT + // FIXME: replace these two ctors with std::string view, cannot do now as + // std::string is implicitly convertible to cstring JsonValue(const char *s) : tag(Kind::String), str(s) {} // NOLINT + JsonValue(const std::string &s) : tag(Kind::String), str(s) {} // NOLINT void serialize(std::ostream &out) const override; bool operator==(const big_int &v) const; // is_integral is true for bool - template ::value, int>::type = 0> + template , int> = 0> bool operator==(const T &v) const { return (tag == Kind::Number) && (v == value); } bool operator==(const double &v) const; bool operator==(const float &v) const; bool operator==(const cstring &s) const; - bool operator==(const std::string &s) const; + // FIXME: replace these two methods with std::string view, cannot do now as + // std::string is implicitly convertible to cstring bool operator==(const char *s) const; + bool operator==(const std::string &s) const; bool operator==(const JsonValue &other) const; bool isNumber() const { return tag == Kind::Number; } @@ -103,7 +107,7 @@ class JsonValue final : public IJson { const Kind tag; const big_int value = 0; - const cstring str = ""_cs; + const cstring str = cstring::empty; DECLARE_TYPEINFO(JsonValue, IJson); }; @@ -136,11 +140,13 @@ class JsonArray final : public IJson, public std::vector { append(new JsonValue(s)); return this; } - JsonArray *append(const std::string &s) { + // FIXME: replace these two methods with std::string view, cannot do now as + // std::string is implicitly convertible to cstring + JsonArray *append(const char *s) { append(new JsonValue(s)); return this; } - JsonArray *append(const char *s) { + JsonArray *append(const std::string &s) { append(new JsonValue(s)); return this; } @@ -155,40 +161,32 @@ class JsonArray final : public IJson, public std::vector { DECLARE_TYPEINFO(JsonArray, IJson); }; -class JsonObject final : public IJson, public ordered_map { +class JsonObject final : public IJson, public string_map { friend class Test::TestJson; + using base = string_map; + public: JsonObject() = default; void serialize(std::ostream &out) const override; - JsonObject *emplace(cstring label, IJson *value); JsonObject *emplace_non_null(cstring label, IJson *value); - JsonObject *emplace(cstring label, big_int v) { - emplace(label, new JsonValue(v)); - return this; - } - template ::value, int>::type = 0> - JsonObject *emplace(cstring label, T v) { - emplace(label, new JsonValue(v)); - return this; - } - JsonObject *emplace(cstring label, float v) { - emplace(label, new JsonValue(v)); - return this; - } - JsonObject *emplace(cstring label, cstring s) { - emplace(label, new JsonValue(s)); - return this; - } - JsonObject *emplace(cstring label, std::string s) { - emplace(label, new JsonValue(s)); - return this; - } - JsonObject *emplace(cstring label, const char *s) { - emplace(label, new JsonValue(s)); + + JsonObject *emplace(cstring label, IJson *value); + JsonObject *emplace(std::string_view label, IJson *value); + + template + auto emplace(String label, + T &&s) -> std::enable_if_t, JsonObject *> { + emplace(label, new JsonValue(std::forward(s))); return this; } + IJson *get(cstring label) const { return ::get(*this, label); } + IJson *get(std::string_view label) const { return ::get(*this, label); } + template + T *getAs(S label) const { + return get(label)->template to(); + } DECLARE_TYPEINFO(JsonObject, IJson); }; diff --git a/lib/string_map.h b/lib/string_map.h new file mode 100644 index 00000000000..bab7c00c63b --- /dev/null +++ b/lib/string_map.h @@ -0,0 +1,239 @@ +/* +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 LIB_STRING_MAP_H_ +#define LIB_STRING_MAP_H_ + +#include +#include +#include +#include + +#include "absl/container/flat_hash_map.h" +#include "cstring.h" + +/// Map with string keys that is ordered by order of element insertion. +/// Use this map only when stable iteration order is significant. For everything +/// else consider using some other unordered containers with cstring keys. Never +/// use std::map or ordered_map as these maps will +/// have significant overhead due to lexicographical ordering of the keys. +/// +/// For this particular implementation: +/// * Key are stored as cstrings in the underlying abseil hash map. +/// * Heterogenous lookup (with std::string_view keys) is supported. Special +/// care is done not to create cstrings in case if they are not in the map +/// already +/// * Values are stored in std::list, similar to ordered_map. +template +class string_map { + public: + using key_type = cstring; + using mapped_type = V; + using value_type = std::pair; + using reference = value_type &; + using const_reference = const value_type &; + + private: + // TODO: Allow different containers (e.g. vector / small vector) + using list_type = std::list; + using list_iterator = typename list_type::iterator; + list_type data; + + public: + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + private: + using map_type = absl::flat_hash_map; + map_type data_map; + void init_data_map() { + data_map.clear(); + for (auto it = data.begin(); it != data.end(); it++) data_map.emplace(it->first, it); + } + iterator tr_iter(typename map_type::iterator i) { + if (i == data_map.end()) return data.end(); + return i->second; + } + const_iterator tr_iter(typename map_type::const_iterator i) const { + if (i == data_map.end()) return data.end(); + return i->second; + } + + public: + using size_type = typename map_type::size_type; + + string_map() = default; + string_map(const string_map &a) : data(a.data) { init_data_map(); } + template + string_map(InputIt first, InputIt last) { + insert(first, last); + } + string_map(string_map &&a) = default; + string_map &operator=(const string_map &a) { + if (this != &a) { + data.clear(); + data.insert(data.end(), a.data.begin(), a.data.end()); + init_data_map(); + } + return *this; + } + string_map &operator=(string_map &&a) = default; + string_map(std::initializer_list il) { insert(il.begin(), il.end()); } + + iterator begin() noexcept { return data.begin(); } + const_iterator begin() const noexcept { return data.begin(); } + iterator end() noexcept { return data.end(); } + const_iterator end() const noexcept { return data.end(); } + reverse_iterator rbegin() noexcept { return data.rbegin(); } + const_reverse_iterator rbegin() const noexcept { return data.rbegin(); } + reverse_iterator rend() noexcept { return data.rend(); } + const_reverse_iterator rend() const noexcept { return data.rend(); } + const_iterator cbegin() const noexcept { return data.cbegin(); } + const_iterator cend() const noexcept { return data.cend(); } + const_reverse_iterator crbegin() const noexcept { return data.crbegin(); } + const_reverse_iterator crend() const noexcept { return data.crend(); } + + bool empty() const noexcept { return data.empty(); } + size_type size() const noexcept { return data_map.size(); } + size_type max_size() const noexcept { return data_map.max_size(); } + /// As the map is ordered, two maps are only considered equal if the elements + /// are inserted in the same order. Same as with ordered_map though. + bool operator==(const string_map &a) const { return data == a.data; } + bool operator!=(const string_map &a) const { return data != a.data; } + void clear() { + data.clear(); + data_map.clear(); + } + + iterator find(cstring a) { return tr_iter(data_map.find(a)); } + /// Functions below do have `std::string_view` versions. Here we are having + /// important special case: if `a` is not something that was interned, we do + /// not copy / intern it, we know for sure that `a` is not in the map and we + /// do not need to perform a lookup. + iterator find(std::string_view a) { + cstring key = cstring::get_cached(a); + if (key.isNull()) return data.end(); + + return tr_iter(data_map.find(key)); + } + const_iterator find(cstring a) const { return tr_iter(data_map.find(a)); } + const_iterator find(std::string_view a) const { + cstring key = cstring::get_cached(a); + if (key.isNull()) return data.end(); + + return tr_iter(data_map.find(key)); + } + + size_type count(cstring a) const { return data_map.count(a); } + size_type count(std::string_view a) const { + cstring key = cstring::get_cached(a); + if (key.isNull()) return 0; + + return data_map.count(key); + } + + bool contains(cstring a) const { return data_map.contains(a); } + bool contains(std::string_view a) const { + cstring key = cstring::get_cached(a); + if (key.isNull()) return false; + + return data_map.contains(key); + } + + template + V &operator[](Key &&k) { + auto it = find(key_type(std::forward(k))); + if (it == data.end()) { + it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k), + std::forward_as_tuple()); + data_map.emplace(it->first, it); + } + return it->second; + } + + template + V &at(Key &&k) { + auto it = find(std::forward(k)); + if (it == data.end()) throw std::out_of_range("string_map::at"); + return it->second; + } + template + const V &at(Key &&k) const { + auto it = find(std::forward(k)); + if (it == data.end()) throw std::out_of_range("string_map::at"); + return it->second; + } + + template + std::pair emplace(Key &&k, VV &&...v) { + auto it = find(key_type(std::forward(k))); + if (it == data.end()) { + it = data.emplace(data.end(), std::piecewise_construct, std::forward_as_tuple(k), + std::forward_as_tuple(std::forward(v)...)); + data_map.emplace(it->first, it); + return {it, true}; + } + return {it, false}; + } + + std::pair insert(value_type &&value) { + return emplace(std::move(value.first), std::move(value.second)); + } + std::pair insert(const value_type &value) { + return emplace(value.first, value.second); + } + + template + void insert(InputIterator b, InputIterator e) { + while (b != e) insert(*b++); + } + + iterator erase(const_iterator pos) { + auto it = data_map.find(pos->first); + assert(it != data_map.end()); + // get the non-const std::list iterator -- libstdc++ is missing + // std::list::erase(const_iterator) overload + auto list_it = it->second; + data_map.erase(it); + return data.erase(list_it); + } + size_type erase(cstring k) { + auto it = find(k); + if (it != data.end()) { + data_map.erase(k); + data.erase(it); + return 1; + } + return 0; + } + size_type erase(std::string_view k) { + auto it = find(k); + if (it != data.end()) { + data_map.erase(it->first); + data.erase(it); + return 1; + } + return 0; + } + + void swap(string_map &other) { + using std::swap; + swap(data, other.data); + swap(data_map, other.data_map); + } +}; + +#endif /* LIB_STRING_MAP_H_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7e8b31d65dd..19908274d06 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,7 @@ set (GTEST_UNITTEST_SOURCES gtest/p4runtime.cpp gtest/source_file_test.cpp gtest/strength_reduction.cpp + gtest/string_map.cpp gtest/transforms.cpp gtest/rtti_test.cpp gtest/nethash.cpp diff --git a/test/gtest/json_test.cpp b/test/gtest/json_test.cpp index 0f9e80a9f7d..0d4a5629b6a 100644 --- a/test/gtest/json_test.cpp +++ b/test/gtest/json_test.cpp @@ -65,9 +65,9 @@ TEST(Util, Json) { auto obj = new JsonObject(); EXPECT_EQ("{\n}", obj->toString()); - obj->emplace("x"_cs, "x"); + obj->emplace("x", "x"); EXPECT_EQ("{\n \"x\" : \"x\"\n}", obj->toString()); - obj->emplace("y"_cs, arr); + obj->emplace("y", arr); EXPECT_EQ("{\n \"x\" : \"x\",\n \"y\" : [\n 5,\n \"5\",\n [true]\n ]\n}", obj->toString()); } diff --git a/test/gtest/string_map.cpp b/test/gtest/string_map.cpp new file mode 100644 index 00000000000..d814b0b7047 --- /dev/null +++ b/test/gtest/string_map.cpp @@ -0,0 +1,294 @@ +/* +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 "lib/string_map.h" + +#include +#include + +#include + +#include "lib/map.h" +#include "lib/ordered_map.h" + +using namespace P4::literals; +using ::testing::ElementsAre; +using ::testing::ElementsAreArray; + +namespace Test { + +TEST(StringMap, RangeConstructor) { + string_map::value_type myMap[] = {{"One"_cs, 1}, {"One"_cs, 2}, {"One"_cs, 3}, + {"Two"_cs, 1}, {"Two"_cs, 2}, {"Two"_cs, 3}, + {"Three"_cs, 1}, {"Three"_cs, 2}, {"Three"_cs, 3}}; + + string_map first(std::begin(myMap), std::end(myMap)); + EXPECT_THAT(first, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 1), + std::pair("Three"_cs, 1))); +} + +TEST(StringMap, InitializerListConstructor) { + string_map myMap({{"One"_cs, 1}, + {"Two"_cs, 2}, + {"Three"_cs, 3}, + {"Four"_cs, 4}, + {"Five"_cs, 5}, + {"One"_cs, 2}, + {"Ten"_cs, 10}, + {"Eight"_cs, 8}}); + EXPECT_THAT( + myMap, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 2), std::pair("Three"_cs, 3), + std::pair("Four"_cs, 4), std::pair("Five"_cs, 5), + std::pair("Ten"_cs, 10), std::pair("Eight"_cs, 8))); +} + +TEST(StringMap, InitializerListAssignment) { + string_map myMap; + myMap = {{"One"_cs, 1}, {"Two"_cs, 2}}; + EXPECT_THAT(myMap, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 2))); +} + +TEST(StringMap, InsertFindSize) { + string_map s; + s.insert(std::pair("One"_cs, 1)); + s.insert(std::pair("One"_cs, 1)); + s.insert(std::pair("Two"_cs, 2)); + + EXPECT_EQ(2u, s.size()); + EXPECT_EQ(std::pair("One"_cs, 1u), *s.find("One"_cs)); + EXPECT_EQ(std::pair("Two"_cs, 2u), *s.find("Two"_cs)); + EXPECT_EQ(s.end(), s.find("Seven"_cs)); +} + +TEST(StringMap, CopySwap) { + string_map original; + original.insert({"One"_cs, 1}); + original.insert({"Two"_cs, 2}); + EXPECT_THAT(original, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 2))); + + string_map copy(original); + EXPECT_THAT(copy, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 2))); + + copy.erase(copy.begin()); + copy.insert({"Ten"_cs, 10}); + EXPECT_THAT(copy, ElementsAre(std::pair("Two"_cs, 2), std::pair("Ten"_cs, 10))); + + original.swap(copy); + EXPECT_THAT(original, ElementsAre(std::pair("Two"_cs, 2), std::pair("Ten"_cs, 10))); + EXPECT_THAT(copy, ElementsAre(std::pair("One"_cs, 1), std::pair("Two"_cs, 2))); +} + +// operator[](const Key&) +TEST(StringMap, SubscriptConstKey) { + string_map m; + + // Default construct elements that don't exist yet. + unsigned &s = m["a"_cs]; + EXPECT_EQ(0, s); + EXPECT_EQ(1u, m.size()); + + // The returned mapped reference should refer to the map. + s = 22; + EXPECT_EQ(22, m["a"_cs]); + + // Overwrite existing elements. + m["a"_cs] = 44; + EXPECT_EQ(44, m["a"_cs]); + + // Same, but with heterogeneous lookup + unsigned &s2 = m["b"]; + EXPECT_EQ(0, s2); + EXPECT_EQ(2u, m.size()); + + // The returned mapped reference should refer to the map. + s2 = 22; + EXPECT_EQ(22, m["b"]); + + // Overwrite existing elements. + m["b"] = 44; + EXPECT_EQ(44, m["b"]); +} + +// mapped_type& at(const Key&) +// const mapped_type& at(const Key&) const +TEST(StringMap, At) { + string_map m = {{"a"_cs, 1}, {"b"_cs, 2}}; + + // basic usage. + EXPECT_EQ(1, m.at("a"_cs)); + EXPECT_EQ(2, m.at("b"_cs)); + + // const reference works. + const unsigned &const_ref = std::as_const(m).at("a"_cs); + EXPECT_EQ(1, const_ref); + + // reference works + m.at("a"_cs) = 3; + EXPECT_EQ(3, m.at("a"_cs)); + + // out-of-bounds will throw. + EXPECT_THROW(m.at("c"_cs), std::out_of_range); + EXPECT_THROW({ m.at("c"_cs) = 42; }, std::out_of_range); + + // heterogeneous look-up works. + string_map m2 = {{"a"_cs, 1}, {"b"_cs, 2}}; + EXPECT_EQ(1, m2.at(std::string_view("a"))); + EXPECT_EQ(2, std::as_const(m2).at(std::string_view("b"))); +} + +TEST(StringMap, InsertEmplaceErase) { + string_map om; + ordered_map sm; + + auto it = om.end(); + for (auto v : {0, 1, 2, 3, 4, 5, 6, 7, 8}) { + sm.emplace(std::to_string(v), 2 * v); + std::pair pair{std::to_string(v), 2 * v}; + if (v % 2 == 0) { + if ((v / 2) % 2 == 0) { + it = om.insert(pair).first; + } else { + it = om.emplace(std::string_view(std::to_string(v)), pair.second).first; + } + } else { + if ((v / 2) % 2 == 0) { + it = om.insert(std::move(pair)).first; + } else { + it = om.emplace(std::string_view(std::to_string(v)), v * 2).first; + } + } + } + + EXPECT_THAT(om, ElementsAreArray(sm.begin(), sm.end())); + + it = std::next(om.begin(), 2); + om.erase(it); + sm.erase(std::next(sm.begin(), 2)); + + EXPECT_EQ(om.size(), sm.size()); + + EXPECT_THAT(om, ElementsAreArray(sm.begin(), sm.end())); +} + +TEST(StringMap, MapEqual) { + string_map a; + string_map b; + + EXPECT_TRUE(a == b); + + a["1"_cs] = 111; + a["2"_cs] = 222; + a["3"_cs] = 333; + a["4"_cs] = 444; + + b["1"_cs] = 111; + b["2"_cs] = 222; + b["3"_cs] = 333; + b["4"_cs] = 444; + + EXPECT_EQ(a, b); + + a.erase("2"_cs); + b.erase("2"_cs); + + EXPECT_EQ(a, b); + + a.clear(); + b.clear(); + + EXPECT_EQ(a, b); +} + +TEST(StringMap, MapNotEqual) { + string_map a; + string_map b; + + EXPECT_TRUE(a == b); + + a["1"_cs] = 111; + a["2"_cs] = 222; + a["3"_cs] = 333; + a["4"_cs] = 444; + + b["4"_cs] = 444; + b["3"_cs] = 333; + b["2"_cs] = 222; + b["1"_cs] = 111; + + EXPECT_NE(a, b); + + a.clear(); + b.clear(); + + EXPECT_EQ(a, b); + + a["1"_cs] = 111; + a["2"_cs] = 222; + + b["1"_cs] = 111; + b["2"_cs] = 222; + b["3"_cs] = 333; + + EXPECT_NE(a, b); + + a.clear(); + b.clear(); + + EXPECT_EQ(a, b); + + a["1"_cs] = 111; + a["2"_cs] = 222; + a["3"_cs] = 333; + a["4"_cs] = 444; + + b["4"_cs] = 111; + b["3"_cs] = 222; + b["2"_cs] = 333; + b["1"_cs] = 444; + + EXPECT_NE(a, b); + + a.clear(); + b.clear(); + + EXPECT_EQ(a, b); + + a["1"_cs] = 111; + a["2"_cs] = 222; + a["3"_cs] = 333; + a["4"_cs] = 444; + + b["1"_cs] = 111; + b["2"_cs] = 111; + b["3"_cs] = 111; + b["4"_cs] = 111; + + EXPECT_NE(a, b); +} + +TEST(StringMap, ExistingKey) { + string_map myMap{{"One"_cs, 1}, {"Two"_cs, 2}, {"Three"_cs, 3}}; + + EXPECT_EQ(get(myMap, "One"_cs), 1); + EXPECT_EQ(get(myMap, "Two"_cs), 2); + EXPECT_EQ(get(myMap, "Three"_cs), 3); +} + +TEST(StringMap, NonExistingKey) { + string_map myMap{{"One"_cs, 1}, {"Two"_cs, 2}, {"Three"_cs, 3}}; + + EXPECT_EQ(get(myMap, "Four"_cs), 0); +} + +} // namespace Test diff --git a/tools/ir-generator/irclass.cpp b/tools/ir-generator/irclass.cpp index f2f11451c9e..501c4f6774b 100644 --- a/tools/ir-generator/irclass.cpp +++ b/tools/ir-generator/irclass.cpp @@ -128,6 +128,7 @@ void IrDefinitions::generate(std::ostream &t, std::ostream &out, std::ostream &i << "#include \"ir/node.h\" // IWYU pragma: keep\n" << "#include \"ir/nodemap.h\" // IWYU pragma: keep\n" << "#include \"ir/vector.h\" // IWYU pragma: keep\n" + << "#include \"lib/ordered_map.h\" // IWYU pragma: keep\n" << std::endl << "class JSONLoader;\n" << "using NodeFactoryFn = IR::Node*(*)(JSONLoader&);\n"