Skip to content

Commit

Permalink
Introduce string map class and switch to it (#4774)
Browse files Browse the repository at this point in the history
* Add string map that serves as an improved version of ordered_map<cstring, ...>:
  - Underlying map is abseil's unordered map
  - Supports heterogenous lookups with std::string_view keys
  - Several ordered_map<cstring, ...> bugs are fixed

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Make use of string_map in IndexedVector

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Switch to string_map for JSonObject. Some small cleanup while there

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Allow heterogenous lookup for json values. Simplifies code a bit

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Add convenient helper for `::get + cast`. Simplify code a bit

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Allow heterogenous lookup for JsonObject. Simplify code around.

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Throw in few std::string_view overloads

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* No need for std::map in validateParsedProgram

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Use unordered container in typeUnification

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Switch to proper string maps in type checker

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Switch to better map in checkNamedArgs

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Move ParameterSubstitution to better maps

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Switch to better maps for various IR methods

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Address review comments

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

* Use `Util::Hash` for "internal maps". Some cleanup while there.

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>

---------

Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>
  • Loading branch information
asl authored Jul 12, 2024
1 parent a258b7e commit 0ccd7c6
Show file tree
Hide file tree
Showing 53 changed files with 1,511 additions and 876 deletions.
140 changes: 70 additions & 70 deletions backends/bmv2/common/JsonObjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Util::JsonObject>();
auto val = obj->get("id"_cs)->to<Util::JsonValue>();
auto val = obj->getAs<Util::JsonValue>("id");
if (val != nullptr && val->isNumber() && val->getInt() == static_cast<int>(id)) {
return obj->get("elements"_cs)->to<Util::JsonArray>();
return obj->getAs<Util::JsonArray>("elements");
}
}
return nullptr;
Expand All @@ -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<Util::JsonObject>();
auto val = obj->get("name"_cs)->to<Util::JsonValue>();
auto val = obj->getAs<Util::JsonValue>("name");
if (val != nullptr && val->isString() && val->getString() == name) {
return obj;
}
Expand All @@ -90,16 +90,16 @@ 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;
static constexpr int version_minor = JSON_MINOR_VERSION;
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
Expand All @@ -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;
}
Expand All @@ -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 {
Expand All @@ -158,18 +158,18 @@ 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;
}

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>();
Util::JsonArray *fields = headerType->getAs<Util::JsonArray>("fields");
BUG_CHECK(fields != nullptr, "header '%1%' not found", name);
fields->append(field);
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -218,12 +218,12 @@ void JsonObjects::add_header_stack(const cstring &type, const cstring &name, con
const std::vector<unsigned> &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);
}
Expand All @@ -234,12 +234,12 @@ void JsonObjects::add_header_union_stack(const cstring &type, const cstring &nam
const unsigned size, const std::vector<unsigned> &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);
}
Expand All @@ -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);
Expand All @@ -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<Util::JsonArray>();
auto entries = enum_json->getAs<Util::JsonArray>("entries");
auto entry = new Util::JsonArray();
entry->append(entry_name);
entry->append(entry_value);
Expand All @@ -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);
Expand All @@ -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<Util::JsonArray>();
auto states = parser->getAs<Util::JsonArray>("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;
Expand All @@ -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<Util::JsonArray>();
auto transitions = state->getAs<Util::JsonArray>("transitions");
CHECK_NULL(transitions);
auto trans = transition->to<Util::JsonObject>();
CHECK_NULL(trans);
Expand All @@ -325,15 +325,15 @@ 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<Util::JsonArray>();
auto statements = state->getAs<Util::JsonArray>("parser_ops");
CHECK_NULL(statements);
statements->append(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<Util::JsonArray>();
auto keys = state->getAs<Util::JsonArray>("transition_key");
CHECK_NULL(keys);
auto new_keys = newKey->to<Util::JsonArray>();
for (auto k : *new_keys) {
Expand All @@ -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);
}

Expand All @@ -358,32 +358,32 @@ unsigned JsonObjects::add_action(const cstring &name, Util::JsonArray *&params,
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;
}

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);
}

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);
}

Expand Down
6 changes: 3 additions & 3 deletions backends/bmv2/common/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void ActionConverter::convertActionBody(const IR::Vector<IR::StatOrDecl> *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<P4::ExternMethod>()) {
Expand Down Expand Up @@ -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<IR::Type_Bits>() || type->is<IR::Type_Enum>()))
::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);
}
}
Expand Down
Loading

0 comments on commit 0ccd7c6

Please sign in to comment.