From 57da1b0456383bbfd8670db0d5328c7a737325e1 Mon Sep 17 00:00:00 2001 From: Chris Dodd Date: Sat, 22 Feb 2025 10:58:09 +0000 Subject: [PATCH] Clean up and fix JSONLoader code - use unqiue_ptr to manage memory so as to not excercise the garbage collector as much Signed-off-by: Chris Dodd --- backends/bmv2/pna_nic/main.cpp | 2 +- backends/bmv2/psa_switch/main.cpp | 2 +- backends/bmv2/simple_switch/main.cpp | 2 +- backends/dpdk/main.cpp | 2 +- backends/ebpf/p4c-ebpf.cpp | 2 +- backends/graphs/p4c-graphs.cpp | 2 +- backends/p4tools/common/core/z3_solver.cpp | 4 +- backends/tofino/bf-p4c/ir/unique_id.cpp | 7 +- backends/tofino/bf-p4c/mau/hash_function.cpp | 2 +- .../tofino/bf-p4c/parde/match_register.cpp | 2 +- backends/tofino/bf-p4c/phv/phv.cpp | 2 +- ir/json_loader.h | 189 +++++++++++------- ir/json_parser.cpp | 92 ++------- ir/json_parser.h | 47 ++--- ir/node.cpp | 9 + ir/node.h | 1 + test/gtest/dumpjson.cpp | 2 +- test/gtest/load_ir_from_json.cpp | 2 +- 18 files changed, 180 insertions(+), 191 deletions(-) diff --git a/backends/bmv2/pna_nic/main.cpp b/backends/bmv2/pna_nic/main.cpp index f6c2814c7e2..aae04fccf3f 100644 --- a/backends/bmv2/pna_nic/main.cpp +++ b/backends/bmv2/pna_nic/main.cpp @@ -84,7 +84,7 @@ int main(int argc, char *const argv[]) { } std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_IO, "%s: Not valid input file", options.file); return 1; } diff --git a/backends/bmv2/psa_switch/main.cpp b/backends/bmv2/psa_switch/main.cpp index 507aa52301d..33256a0d814 100644 --- a/backends/bmv2/psa_switch/main.cpp +++ b/backends/bmv2/psa_switch/main.cpp @@ -84,7 +84,7 @@ int main(int argc, char *const argv[]) { } std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_IO, "%s: Not valid input file", options.file); return 1; } diff --git a/backends/bmv2/simple_switch/main.cpp b/backends/bmv2/simple_switch/main.cpp index 63d311c10a3..a33f35acd84 100644 --- a/backends/bmv2/simple_switch/main.cpp +++ b/backends/bmv2/simple_switch/main.cpp @@ -87,7 +87,7 @@ int main(int argc, char *const argv[]) { } std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_IO, "%s: Not valid json input file", options.file); return 1; } diff --git a/backends/dpdk/main.cpp b/backends/dpdk/main.cpp index ad5eb908391..773b8366463 100644 --- a/backends/dpdk/main.cpp +++ b/backends/dpdk/main.cpp @@ -105,7 +105,7 @@ int main(int argc, char *const argv[]) { } std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_INVALID, "Not valid input file"); return 1; } diff --git a/backends/ebpf/p4c-ebpf.cpp b/backends/ebpf/p4c-ebpf.cpp index 30355f77c5b..956340bc545 100644 --- a/backends/ebpf/p4c-ebpf.cpp +++ b/backends/ebpf/p4c-ebpf.cpp @@ -56,7 +56,7 @@ void compile(EbpfOptions &options) { std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_IO, "%s: Not valid input file", options.file); return; } diff --git a/backends/graphs/p4c-graphs.cpp b/backends/graphs/p4c-graphs.cpp index 3c4d78137bd..143491bc4da 100644 --- a/backends/graphs/p4c-graphs.cpp +++ b/backends/graphs/p4c-graphs.cpp @@ -151,7 +151,7 @@ int main(int argc, char *const argv[]) { std::istream inJson(&fb); JSONLoader jsonFileLoader(inJson); - if (jsonFileLoader.json == nullptr) { + if (!jsonFileLoader) { ::P4::error(ErrorType::ERR_IO, "Not valid input file"); return 1; } diff --git a/backends/p4tools/common/core/z3_solver.cpp b/backends/p4tools/common/core/z3_solver.cpp index a94a5ca36ce..97b47d71661 100644 --- a/backends/p4tools/common/core/z3_solver.cpp +++ b/backends/p4tools/common/core/z3_solver.cpp @@ -340,13 +340,13 @@ Z3Solver::Z3Solver(bool isIncremental, std::optional inOpt) JSONLoader loader(*inOpt.value()); JSONLoader solverCheckpoints(loader, "checkpoints"); - BUG_CHECK(solverCheckpoints.json->is(), + BUG_CHECK(solverCheckpoints.is(), "Z3 solver loading: can't find list of checkpoint"); solverCheckpoints >> checkpoints; // loading all assertions JSONLoader solverAssertions(loader, "assertions"); - BUG_CHECK(solverAssertions.json->is(), + BUG_CHECK(solverAssertions.is(), "Z3 solver loading: can't find list of assertions"); safe_vector assertions; solverAssertions >> assertions; diff --git a/backends/tofino/bf-p4c/ir/unique_id.cpp b/backends/tofino/bf-p4c/ir/unique_id.cpp index b99a6cdcc31..c85c5e89a22 100644 --- a/backends/tofino/bf-p4c/ir/unique_id.cpp +++ b/backends/tofino/bf-p4c/ir/unique_id.cpp @@ -36,9 +36,10 @@ void UniqueAttachedId::toJSON(P4::JSONGenerator &json) const { UniqueAttachedId UniqueAttachedId::fromJSON(P4::JSONLoader &json) { UniqueAttachedId uai; - if (!json.json) return uai; - json.load("name", uai.name); - json.load("type", uai.type); + if (json) { + json.load("name", uai.name); + json.load("type", uai.type); + } return uai; } diff --git a/backends/tofino/bf-p4c/mau/hash_function.cpp b/backends/tofino/bf-p4c/mau/hash_function.cpp index 692fb582622..effc0750b07 100644 --- a/backends/tofino/bf-p4c/mau/hash_function.cpp +++ b/backends/tofino/bf-p4c/mau/hash_function.cpp @@ -580,7 +580,7 @@ void IR::MAU::HashFunction::build_algorithm_t(bfn_hash_algorithm_ *alg) const { } IR::MAU::HashFunction *IR::MAU::HashFunction::fromJSON(JSONLoader &json) { - if (!json.json) return nullptr; + if (!json) return nullptr; auto *rv = new HashFunction; int type = 0; json.load("type", type); diff --git a/backends/tofino/bf-p4c/parde/match_register.cpp b/backends/tofino/bf-p4c/parde/match_register.cpp index b219da91729..284752e5fa7 100644 --- a/backends/tofino/bf-p4c/parde/match_register.cpp +++ b/backends/tofino/bf-p4c/parde/match_register.cpp @@ -47,7 +47,7 @@ void MatchRegister::toJSON(JSONGenerator &json) const { json.emit(toString()); } /* static */ MatchRegister MatchRegister::fromJSON(JSONLoader &json) { - if (auto *v = json.json->to()) return MatchRegister(cstring(v->c_str())); + if (json.is()) return MatchRegister(json.as()); BUG("Couldn't decode JSON value to parser match register"); return MatchRegister(); } diff --git a/backends/tofino/bf-p4c/phv/phv.cpp b/backends/tofino/bf-p4c/phv/phv.cpp index e37135e3173..a82b40e8b70 100644 --- a/backends/tofino/bf-p4c/phv/phv.cpp +++ b/backends/tofino/bf-p4c/phv/phv.cpp @@ -162,7 +162,7 @@ cstring Container::toString() const { void Container::toJSON(P4::JSONGenerator &json) const { json.emit(toString()); } /* static */ Container Container::fromJSON(P4::JSONLoader &json) { - if (auto *v = json.json->to()) return Container(v->c_str()); + if (json.is()) return Container(json.as().c_str()); BUG("Couldn't decode JSON value to container"); return Container(); } diff --git a/ir/json_loader.h b/ir/json_loader.h index b8d027b4b55..0bb35d492c2 100644 --- a/ir/json_loader.h +++ b/ir/json_loader.h @@ -53,43 +53,57 @@ class JSONLoader { static const bool value = sizeof(test(0)) == sizeof(char); }; - public: std::unordered_map &node_refs; - JsonData *json = nullptr; + std::unique_ptr json_root; + const JsonData *json = nullptr; + public: explicit JSONLoader(std::istream &in) : node_refs(*(new std::unordered_map())) { - in >> json; + in >> json_root; + json = json_root.get(); } - explicit JSONLoader(JsonData *json) - : node_refs(*(new std::unordered_map())), json(json) {} - + private: JSONLoader(JsonData *json, std::unordered_map &refs) : node_refs(refs), json(json) {} + public: JSONLoader(const JSONLoader &unpacker, const std::string &field) : node_refs(unpacker.node_refs), json(nullptr) { - if (auto *obj = unpacker.json->to()) json = get(obj, field); + if (!unpacker) return; + if (auto *obj = unpacker.json->to()) { + if (auto it = obj->find(field); it != obj->end()) { + json = it->second.get(); + } + } + } + + explicit operator bool() const { return json != nullptr; } + template + [[nodiscard]] bool is() const { + return json && json->is(); + } + template + [[nodiscard]] const T &as() const { + return json->as(); } private: const IR::Node *get_node() { if (!json || !json->is()) return nullptr; // invalid json exception? - int id = json->as().get_id(); + int id; + load("Node_ID", id); if (id >= 0) { if (node_refs.find(id) == node_refs.end()) { - if (auto fn = get(IR::unpacker_table, json->as().get_type())) { + cstring type; + load("Node_Type", type); + if (auto fn = get(IR::unpacker_table, type)) { node_refs[id] = fn(*this); // Creating JsonObject from source_info read from jsonFile // and setting SourceInfo for each node // when "--fromJSON" flag is used - JsonObject *obj = new JsonObject(json->as().get_sourceJson()); - if (obj->hasSrcInfo() == true) { - node_refs[id]->srcInfo = - Util::SourceInfo(obj->get_filename(), obj->get_line(), - obj->get_column(), obj->get_sourceFragment()); - } + node_refs[id]->sourceInfoFromJSON(*this); } else { return nullptr; } // invalid json exception? @@ -102,8 +116,9 @@ class JSONLoader { template void unpack_json(safe_vector &v) { T temp; - for (auto e : json->as()) { - load(e, temp); + v.clear(); + for (auto &e : as()) { + load(e.get(), temp); v.push_back(temp); } } @@ -111,8 +126,9 @@ class JSONLoader { template void unpack_json(std::set &v) { T temp; - for (auto e : json->as()) { - load(e, temp); + v.clear(); + for (auto &e : as()) { + load(e.get(), temp); v.insert(temp); } } @@ -120,8 +136,9 @@ class JSONLoader { template void unpack_json(ordered_set &v) { T temp; - for (auto e : json->as()) { - load(e, temp); + v.clear(); + for (auto &e : as()) { + load(e.get(), temp); v.insert(temp); } } @@ -156,30 +173,46 @@ class JSONLoader { template void unpack_json(std::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); + v.clear(); + if (is()) { + for (auto &e : as()) { + load(e.get(), temp); + v.insert(temp); + } + } else { + for (auto &e : as()) { + JsonString *k = new JsonString(e.first); + load(k, temp.first); + load(e.second.get(), temp.second); + v.insert(temp); + } } } template void unpack_json(ordered_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); + v.clear(); + if (is()) { + for (auto &e : as()) { + load(e.get(), temp); + v.insert(temp); + } + } else { + for (auto &e : as()) { + JsonString *k = new JsonString(e.first); + load(k, temp.first); + load(e.second.get(), temp.second); + 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.clear(); + for (auto &e : as()) { + temp.first = e.first; + load(e.second.get(), temp.second); v.insert(temp); } } @@ -187,78 +220,83 @@ class JSONLoader { template void unpack_json(std::multimap &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); + v.clear(); + if (is()) { + for (auto &e : as()) { + load(e.get(), temp); + v.insert(temp); + } + } else { + for (auto &e : as()) { + JsonString *k = new JsonString(e.first); + load(k, temp.first); + load(e.second.get(), temp.second); + v.insert(temp); + } } } template void unpack_json(std::vector &v) { T temp; - for (auto e : json->as()) { - load(e, temp); + v.clear(); + for (auto &e : as()) { + load(e.get(), temp); v.push_back(temp); } } template void unpack_json(std::pair &v) { - const JsonObject *obj = json->checkedTo(); - load(::P4::get(obj, "first"), v.first); - load(::P4::get(obj, "second"), v.second); + load("first", v.first); + load("second", v.second); } template void unpack_json(std::optional &v) { - const JsonObject *obj = json->checkedTo(); bool isValid = false; - load(::P4::get(obj, "valid"), isValid); + load("valid", isValid); if (!isValid) { v = std::nullopt; return; } T value; - load(::P4::get(obj, "value"), value), v = std::move(value); + load("value", value); + v = std::move(value); } template - std::enable_if_t> unpack_variant(const JsonObject *, - int /*target*/, + std::enable_if_t> unpack_variant(int /*target*/, Variant & /*variant*/) { BUG("Error traversing variant during load"); } template - std::enable_if_t<(N < std::variant_size_v)> unpack_variant(const JsonObject *obj, - int target, + std::enable_if_t<(N < std::variant_size_v)> unpack_variant(int target, Variant &variant) { if (N == target) { variant.template emplace(); - load(P4::get(obj, "value"), std::get(variant)); + load("value", std::get(variant)); } else - unpack_variant(obj, target, variant); + unpack_variant(target, variant); } template void unpack_json(std::variant &v) { - const JsonObject *obj = json->checkedTo(); int index = -1; - load(P4::get(obj, "variant_index"), index); - unpack_variant<0>(obj, index, v); + load("variant_index", index); + unpack_variant<0>(index, v); } - void unpack_json(bool &v) { v = json->as(); } + void unpack_json(bool &v) { v = as(); } template std::enable_if_t> unpack_json(T &v) { - v = json->as(); + v = as(); } - void unpack_json(big_int &v) { v = json->as().val; } + void unpack_json(big_int &v) { v = as().val; } void unpack_json(cstring &v) { - std::string tmp = json->as(); + std::string tmp = as(); std::string::size_type p = 0; while ((p = tmp.find('\\', p)) != std::string::npos) { tmp.erase(p, 1); @@ -278,7 +316,7 @@ class JSONLoader { if (!json->is()) v = tmp; } void unpack_json(IR::ID &v) { - if (!json->is()) v.name = json->as(); + if (!json->is()) v.name = as(); } void unpack_json(LTBitMatrix &m) { @@ -346,33 +384,36 @@ class JSONLoader { void unpack_json(T (&v)[N]) { if (auto *j = json->to()) { for (size_t i = 0; i < N && i < j->size(); ++i) { - json = (*j)[i]; - unpack_json(v[i]); + load((*j)[i].get(), v[i]); } } } - public: template void load(JsonData *json, T &v) { JSONLoader(json, node_refs).unpack_json(v); } + public: template - void load(const std::string field, T *&v) { - JSONLoader loader(*this, field); - if (loader.json == nullptr) { - v = nullptr; - } else { + bool load(const std::string field, T *&v) { + if (auto loader = JSONLoader(*this, field)) { loader.unpack_json(v); + return true; + } else { + v = nullptr; + return false; } } template - void load(const std::string field, T &v) { - JSONLoader loader(*this, field); - if (loader.json == nullptr) return; - loader.unpack_json(v); + bool load(const std::string field, T &v) { + if (auto loader = JSONLoader(*this, field)) { + loader.unpack_json(v); + return true; + } else { + return false; + } } template diff --git a/ir/json_parser.cpp b/ir/json_parser.cpp index 3a55f9b74b0..bfde1b2b1b1 100644 --- a/ir/json_parser.cpp +++ b/ir/json_parser.cpp @@ -23,64 +23,6 @@ limitations under the License. namespace P4 { -int JsonObject::get_id() const { - auto it = find("Node_ID"); - if (it == end()) return -1; - - return it->second->as(); -} - -std::string JsonObject::get_type() const { - auto it = find("Node_Type"); - if (it == end()) return ""; - - return it->second->as(); -} - -std::string JsonObject::get_filename() const { - auto it = find("filename"); - - if (it == end()) return ""; - - return it->second->as(); -} - -std::string JsonObject::get_sourceFragment() const { - auto it = find("source_fragment"); - - if (it == end()) return ""; - - return it->second->as(); -} - -int JsonObject::get_line() const { - auto it = find("line"); - - if (it == end()) return -1; - - return it->second->as(); -} - -int JsonObject::get_column() const { - auto it = find("column"); - - if (it == end()) return -1; - - return it->second->as(); -} - -JsonObject JsonObject::get_sourceJson() const { - auto it = find("Source_Info"); - - if (it == end()) { - JsonObject obj; - obj.setSrcInfo(false); - return obj; - } - - return it->second->as(); -} - // Hack to make << operator work multi-threaded static thread_local int level = 0; @@ -90,14 +32,14 @@ std::string getIndent(int l) { return ss.str(); } -std::ostream &operator<<(std::ostream &out, JsonData *json) { +std::ostream &operator<<(std::ostream &out, const JsonData *json) { if (auto *obj = json->to()) { out << "{"; if (obj->size() > 0) { level++; out << std::endl; for (auto &e : *obj) - out << getIndent(level) << e.first << " : " << e.second << "," << std::endl; + out << getIndent(level) << e.first << " : " << e.second.get() << "," << std::endl; out << getIndent(--level); } out << "}"; @@ -107,7 +49,7 @@ std::ostream &operator<<(std::ostream &out, JsonData *json) { level++; out << std::endl; for (auto &e : *vec) { - out << getIndent(level) << e << "," << std::endl; + out << getIndent(level) << e.get() << "," << std::endl; } out << getIndent(--level); } @@ -126,43 +68,43 @@ std::ostream &operator<<(std::ostream &out, JsonData *json) { return out; } -std::istream &operator>>(std::istream &in, JsonData *&json) { +std::istream &operator>>(std::istream &in, std::unique_ptr &json) { while (in) { char ch; in >> ch; switch (ch) { case '{': { - ordered_map obj; + ordered_map> obj; do { in >> std::ws >> ch; if (ch == '}') break; in.unget(); - JsonData *key, *val; + std::unique_ptr key, val; in >> key >> std::ws >> ch >> std::ws >> val; - obj[key->as()] = val; + obj[key->as()] = std::move(val); in >> std::ws >> ch; } while (in && ch != '}'); - json = new JsonObject(obj); + json = std::make_unique(std::move(obj)); return in; } case '[': { - std::vector vec; + std::vector> vec; do { in >> std::ws >> ch; if (ch == ']') break; in.unget(); - JsonData *elem; + std::unique_ptr elem; in >> elem; - vec.push_back(elem); + vec.emplace_back(std::move(elem)); in >> std::ws >> ch; } while (in && ch != ']'); - json = new JsonVector(vec); + json = std::make_unique(std::move(vec)); return in; } case '"': { @@ -177,7 +119,7 @@ std::istream &operator>>(std::istream &in, JsonData *&json) { getline(in, more, '"'); s += more; } - json = new JsonString(s); + json = std::make_unique(s); return in; } case '-': @@ -200,23 +142,23 @@ std::istream &operator>>(std::istream &in, JsonData *&json) { in >> ch; } while (isdigit(ch)); in.unget(); - json = new JsonNumber(big_int(num)); + json = std::make_unique(big_int(num)); return in; } case 't': case 'T': in.ignore(3); - json = new JsonBoolean(true); + json = std::make_unique(true); return in; case 'f': case 'F': in.ignore(4); - json = new JsonBoolean(false); + json = std::make_unique(false); return in; case 'n': case 'N': in.ignore(3); - json = new JsonNull(); + json = std::make_unique(); return in; default: return in; diff --git a/ir/json_parser.h b/ir/json_parser.h index 073caca78e4..69d8910b0df 100644 --- a/ir/json_parser.h +++ b/ir/json_parser.h @@ -2,6 +2,7 @@ #define IR_JSON_PARSER_H_ #include +#include #include #include @@ -13,13 +14,15 @@ namespace P4 { class JsonData : public ICastable { - public: + protected: JsonData() {} JsonData(const JsonData &) = default; JsonData(JsonData &&) = default; - JsonData &operator=(const JsonData &) & = default; - JsonData &operator=(JsonData &&) & = default; - virtual ~JsonData() {} + JsonData &operator=(const JsonData &) = default; + JsonData &operator=(JsonData &&) = default; + + public: + virtual ~JsonData() = default; DECLARE_TYPEINFO(JsonData); }; @@ -56,35 +59,26 @@ class JsonString : public JsonData, public std::string { DECLARE_TYPEINFO(JsonString, JsonData); }; -class JsonVector : public JsonData, public std::vector { +class JsonVector : public JsonData, public std::vector> { public: JsonVector() {} - JsonVector(const std::vector &v) // NOLINT(runtime/explicit) - : std::vector(v) {} - JsonVector &operator=(const JsonVector &) & = default; - JsonVector &operator=(JsonVector &&) & = default; + JsonVector(std::vector> &&v) // NOLINT(runtime/explicit) + : std::vector>(std::move(v)) {} + JsonVector &operator=(const JsonVector &) = delete; + JsonVector &operator=(JsonVector &&) = default; DECLARE_TYPEINFO(JsonVector, JsonData); }; -class JsonObject : public JsonData, public ordered_map { - bool _hasSrcInfo = true; +class JsonObject : public JsonData, public ordered_map> { + // bool _hasSrcInfo = true; public: JsonObject() {} - JsonObject(const JsonObject &obj) = default; - JsonObject &operator=(JsonObject &&) & = default; - JsonObject(const ordered_map &v) // NOLINT(runtime/explicit) - : ordered_map(v) {} - int get_id() const; - std::string get_type() const; - std::string get_filename() const; - std::string get_sourceFragment() const; - int get_line() const; - int get_column() const; - JsonObject get_sourceJson() const; - bool hasSrcInfo() { return _hasSrcInfo; } - void setSrcInfo(bool value) { _hasSrcInfo = value; } + JsonObject(const JsonObject &obj) = delete; + JsonObject &operator=(JsonObject &&) = default; + JsonObject(ordered_map> &&v) // NOLINT(runtime/explicit) + : ordered_map>(std::move(v)) {} DECLARE_TYPEINFO(JsonObject, JsonData); }; @@ -95,8 +89,9 @@ class JsonNull : public JsonData { std::string getIndent(int l); -std::ostream &operator<<(std::ostream &out, JsonData *json); -std::istream &operator>>(std::istream &in, JsonData *&json); +std::ostream &operator<<(std::ostream &out, const JsonData *json); +inline std::ostream &operator<<(std::ostream &out, const JsonData &json) { return out << &json; } +std::istream &operator>>(std::istream &in, std::unique_ptr &json); } // namespace P4 diff --git a/ir/node.cpp b/ir/node.cpp index b684819c37f..b10420529c7 100644 --- a/ir/node.cpp +++ b/ir/node.cpp @@ -155,6 +155,15 @@ void IR::Node::sourceInfoToJSON(JSONGenerator &json) const { json.end_object(state); } +void IR::Node::sourceInfoFromJSON(JSONLoader &json) { + if (auto si = JSONLoader(json, "Source_Info")) { + si.load("filename", srcInfo.filename); + si.load("line", srcInfo.line); + si.load("column", srcInfo.column); + si.load("source_fragment", srcInfo.srcBrief); + } +} + IRNODE_DEFINE_APPLY_OVERLOAD(Node, , ) } // namespace P4 diff --git a/ir/node.h b/ir/node.h index a5e0d4c6afe..96c4cb30d20 100644 --- a/ir/node.h +++ b/ir/node.h @@ -148,6 +148,7 @@ class Node : public virtual INode { cstring toString() const override { return node_type_name(); } void toJSON(JSONGenerator &json) const override; void sourceInfoToJSON(JSONGenerator &json) const; + void sourceInfoFromJSON(JSONLoader &json); Util::JsonObject *sourceInfoJsonObj() const; /* operator== does a 'shallow' comparison, comparing two Node subclass objects for equality, * and comparing pointers in the Node directly for equality */ diff --git a/test/gtest/dumpjson.cpp b/test/gtest/dumpjson.cpp index 37ec8469c6c..a766f8efa38 100644 --- a/test/gtest/dumpjson.cpp +++ b/test/gtest/dumpjson.cpp @@ -33,7 +33,7 @@ TEST(IR, DumpJSON) { std::cout << ss.str(); JSONLoader loader(ss); - std::cout << loader.json; + std::cout << loader.as(); const IR::Node *e2 = nullptr; loader >> e2; diff --git a/test/gtest/load_ir_from_json.cpp b/test/gtest/load_ir_from_json.cpp index ef9b9a0f927..8620a7ac28c 100644 --- a/test/gtest/load_ir_from_json.cpp +++ b/test/gtest/load_ir_from_json.cpp @@ -52,7 +52,7 @@ TEST_F(FromJSONTest, load_ir_from_json) { "grep -v program outputFROM.json > outputFROM.json.tmp; " "mv outputFROM.json.tmp outputFROM.json"); ASSERT_FALSE(exitCode); - exitCode = system("json_diff outputTO.json outputFROM.json"); + exitCode = system("diff outputTO.json outputFROM.json"); ASSERT_FALSE(exitCode); exitCode = system("rm -f outputFROM.json outputTo.json"); ASSERT_FALSE(exitCode);