Skip to content

Commit

Permalink
Fix/improve safety of JSONGenerator
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Dodd <cdodd@nvidia.com>
  • Loading branch information
ChrisDodd committed Feb 25, 2025
1 parent d647430 commit d04dde0
Show file tree
Hide file tree
Showing 28 changed files with 260 additions and 278 deletions.
2 changes: 1 addition & 1 deletion backends/bmv2/pna_nic/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ int main(int argc, char *const argv[]) {
if (::P4::errorCount() > 1 || toplevel == nullptr || toplevel->getMain() == nullptr)
return 1;
if (options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true), true) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true), true).emit(program);
} catch (const std::exception &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/psa_switch/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ int main(int argc, char *const argv[]) {
if (::P4::errorCount() > 1 || toplevel == nullptr || toplevel->getMain() == nullptr)
return 1;
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true), true) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true), true).emit(program);
} catch (const std::exception &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
2 changes: 1 addition & 1 deletion backends/bmv2/simple_switch/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ int main(int argc, char *const argv[]) {
if (::P4::errorCount() > 1 || toplevel == nullptr || toplevel->getMain() == nullptr)
return 1;
if (!options.dumpJsonFile.empty() && !options.loadIRFromJson)
JSONGenerator(*openFile(options.dumpJsonFile, true), true) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true), true).emit(program);
} catch (const std::exception &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
2 changes: 1 addition & 1 deletion backends/dpdk/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ int main(int argc, char *const argv[]) {
if (::P4::errorCount() > 1 || toplevel == nullptr || toplevel->getMain() == nullptr)
return 1;
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true), true) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true), true).emit(program);
} catch (const std::exception &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
2 changes: 1 addition & 1 deletion backends/ebpf/p4c-ebpf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void compile(EbpfOptions &options) {
midend.addDebugHook(hook);
auto toplevel = midend.run(options, program);
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true)) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true)).emit(program);
if (::P4::errorCount() > 0) return;

EBPF::run_ebpf_backend(options, toplevel, &midend.refMap, &midend.typeMap);
Expand Down
2 changes: 1 addition & 1 deletion backends/graphs/p4c-graphs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ int main(int argc, char *const argv[]) {
try {
top = midEnd.process(program);
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true)) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true)).emit(program);
} catch (const std::exception &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
6 changes: 3 additions & 3 deletions backends/p4test/p4test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,17 @@ int main(int argc, char *const argv[]) {
}
if (program) {
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true), true) << program << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true), true).emit(program);
if (options.debugJson) {
std::stringstream ss1, ss2;
JSONGenerator gen1(ss1), gen2(ss2);
gen1 << program;
gen1.emit(program);

const IR::Node *node = nullptr;
JSONLoader loader(ss1);
loader >> node;

gen2 << node;
gen2.emit(node);
if (ss1.str() != ss2.str()) {
error(ErrorType::ERR_UNEXPECTED, "json mismatch");
std::ofstream t1("t1.json"), t2("t2.json");
Expand Down
14 changes: 5 additions & 9 deletions backends/p4tools/common/core/z3_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,11 @@ const IR::Literal *Z3Solver::toLiteral(const z3::expr &e, const IR::Type *type)
}

void Z3Solver::toJSON(JSONGenerator &json) const {
json << json.indent << "{\n";
json.indent++;
json << json.indent << "\"checkpoints\" : " << checkpoints;
json << ",\n";
json << json.indent << "\"declarations\" : " << declaredVarsById;
json << ",\n";
json << json.indent << "\"assertions\" : " << p4Assertions;
json.indent--;
json << json.indent << "}\n";
auto state = json.begin_object();
json.emit("checkpoints", checkpoints);
json.emit("declarations", declaredVarsById);
json.emit("assertions", p4Assertions);
json.end_object(state);
}

void Z3Solver::addZ3Pushes(size_t &chkIndex, size_t asrtIndex) {
Expand Down
2 changes: 1 addition & 1 deletion backends/tc/tc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ int main(int argc, char *const argv[]) {
return 1;
}
if (!options.dumpJsonFile.empty())
JSONGenerator(*openFile(options.dumpJsonFile, true)) << toplevel << std::endl;
JSONGenerator(*openFile(options.dumpJsonFile, true)).emit(toplevel);
} catch (const Util::P4CExceptionBase &bug) {
std::cerr << bug.what() << std::endl;
return 1;
Expand Down
6 changes: 3 additions & 3 deletions backends/tofino/bf-p4c/ir/arch.def
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ class P4Thread {
const IR::P4Control *mau = nullptr;
const IR::P4Control *deparser = nullptr;
toJSON {
json << json.indent << "\"parsers\" : " << parsers << "," << std::endl
<< json.indent << "\"mau\" : " << mau << "," << std::endl
<< json.indent << "\"deparser\" : " << deparser; }
json.emit("parsers", parsers);
json.emit("mau", mau);
json.emit("deparser", deparser); }
fromJSON {
IR::BFN::P4Thread * thread = new IR::BFN::P4Thread();
json.load("parsers", thread->parsers);
Expand Down
8 changes: 4 additions & 4 deletions backends/tofino/bf-p4c/ir/tofino.def
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ class BFN::Pipe {
hw_constrained_fields == a.hw_constrained_fields;
}
toJSON {
json << json.indent << "\"parser\" : " << parsers << "," << std::endl
<< json.indent << "\"mau\" : " << mau << "," << std::endl
<< json.indent << "\"deparser\" : " << deparser << std::endl
<< json.indent << "\"hw_constrained_fields\" : " << hw_constrained_fields; }
json.emit("parser", parsers);
json.emit("mau", mau);
json.emit("deparser", deparser);
json.emit("hw_constrained_fields", hw_constrained_fields); }
fromJSON {
IR::BFN::Pipe::thread_t * thread = new IR::BFN::Pipe::thread_t();
json.load("parsers", thread->parsers);
Expand Down
4 changes: 2 additions & 2 deletions backends/tofino/bf-p4c/ir/unique_id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ static const char *attached_id_to_str[] = {"", "tind", "idletime", "sta
static const char *speciality_to_str[] = {"", "atcam", "dleft"};

void UniqueAttachedId::toJSON(P4::JSONGenerator &json) const {
json << json.indent << "\"name\": " << name << ",\n"
<< json.indent << "\"type\": " << type << ",\n";
json.emit("name", name);
json.emit("type", type);
}

UniqueAttachedId UniqueAttachedId::fromJSON(P4::JSONLoader &json) {
Expand Down
16 changes: 8 additions & 8 deletions backends/tofino/bf-p4c/mau/hash_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,14 @@ bool IR::MAU::HashFunction::convertPolynomialExtern(const IR::GlobalRef *ref) {
}

void IR::MAU::HashFunction::toJSON(JSONGenerator &json) const {
json << json.indent << "\"type\": " << static_cast<int>(type) << ",\n"
<< json.indent << "\"size\": " << size << ",\n"
<< json.indent << "\"msb\": " << msb << ",\n"
<< json.indent << "\"reverse\": " << reverse << ",\n"
<< json.indent << "\"poly\": " << poly << ",\n"
<< json.indent << "\"init\": " << init << ",\n"
<< json.indent << "\"xor\": " << final_xor << ",\n"
<< json.indent << "\"extend\": " << extend;
json.emit("type", static_cast<int>(type));
json.emit("size", size);
json.emit("msb", msb);
json.emit("reverse", reverse);
json.emit("poly", poly);
json.emit("init", init);
json.emit("xor", final_xor);
json.emit("extend", extend);
}

void IR::MAU::HashFunction::build_algorithm_t(bfn_hash_algorithm_ *alg) const {
Expand Down
2 changes: 1 addition & 1 deletion backends/tofino/bf-p4c/mau/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ struct TableResourceAlloc {
meter_format.clear();
meter_xbar.reset();
}
void toJSON(P4::JSONGenerator &json) const { json << "null"; }
void toJSON(P4::JSONGenerator &json) const { json.emit(nullptr); }
static TableResourceAlloc *fromJSON(P4::JSONLoader &) { return nullptr; }

void merge_instr(const TableResourceAlloc *);
Expand Down
2 changes: 1 addition & 1 deletion backends/tofino/bf-p4c/p4c-barefoot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ int main(int ac, char **av) {
// Print out the IR for p4i after frontend (--toJson "-" signifies stdout)
auto &irFile = irFilePath != "-" ? *openFile(irFilePath, false) : std::cout;
LOG3("IR dump after frontend to " << irFilePath);
JSONGenerator(irFile, true) << program << std::endl;
JSONGenerator(irFile, true).emit(program);
}

#if BAREFOOT_INTERNAL
Expand Down
29 changes: 13 additions & 16 deletions backends/tofino/bf-p4c/parde/clot/clot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,20 @@ void Clot::set_slices(cstring parser_state, const std::vector<const PHV::FieldSl
}
}

void Clot::toJSON(JSONGenerator &json) const { json << *this; }
void Clot::toJSON(JSONGenerator &json) const {
json.emit("tag", tag);
json.emit("gress", gress);
json.emit("pov_bit", pov_bit);
json.emit("stack_depth", stack_depth);
json.emit("stack_inc", stack_inc);
}

/* static */ Clot *Clot::fromJSON(JSONLoader &json) {
if (auto *v = json.json->to<JsonString>()) return new Clot(cstring(v->c_str()));
BUG("Couldn't decode JSON value to clot");
return new Clot();
Clot::Clot(JSONLoader &json) {
json.load("tag", tag);
json.load("gress", gress);
json.load("pov_bit", pov_bit);
json.load("stack_depth", stack_depth);
json.load("stack_inc", stack_inc);
}

std::ostream &operator<<(std::ostream &out, const Clot &clot) { return out << "CLOT " << clot.tag; }
Expand All @@ -209,14 +217,3 @@ std::ostream &operator<<(std::ostream &out, const Clot *clot) {
else
return out << "(nullptr)";
}

P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const Clot &clot) {
return out << clot.toString();
}

P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const Clot *clot) {
if (clot)
return out << *clot;
else
return out << "(nullptr)";
}
5 changes: 2 additions & 3 deletions backends/tofino/bf-p4c/parde/clot/clot.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ class Clot final : public LiftCompare<Clot> {

/// JSON serialization/deserialization.
void toJSON(JSONGenerator &json) const;
static Clot *fromJSON(JSONLoader &json);
explicit Clot(JSONLoader &json);
static Clot *fromJSON(JSONLoader &json) { return new Clot(json); }

/// Identifies the hardware CLOT associated with this object.
unsigned tag;
Expand Down Expand Up @@ -185,7 +186,5 @@ class Clot final : public LiftCompare<Clot> {

std::ostream &operator<<(std::ostream &out, const Clot &clot);
std::ostream &operator<<(std::ostream &out, const Clot *clot);
P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const Clot &clot);
P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const Clot *clot);

#endif /* BACKENDS_TOFINO_BF_P4C_PARDE_CLOT_CLOT_H_ */
17 changes: 13 additions & 4 deletions backends/tofino/bf-p4c/parde/marshal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,26 @@
#include "marshal.h"

#include "ir/ir.h"
#include "ir/json_generator.h"
#include "ir/json_loader.h"

std::string MarshaledFrom::toString() const {
std::stringstream tmp;
tmp << *this;
return tmp.str();
}

void MarshaledFrom::toJSON(JSONGenerator &json) const { json << *this; }
void MarshaledFrom::toJSON(JSONGenerator &json) const {
json.emit("gress", gress);
json.emit("field_name", field_name);
json.emit("pre_padding", pre_padding);
}

/* static */
MarshaledFrom MarshaledFrom::fromJSON(JSONLoader &) {
BUG("Uninmplemented");
return MarshaledFrom();
MarshaledFrom MarshaledFrom::fromJSON(JSONLoader &json) {
MarshaledFrom rv;
json.load("gress", rv.gress);
json.load("field_name", rv.field_name);
json.load("pre_padding", rv.pre_padding);
return rv;
}
5 changes: 0 additions & 5 deletions backends/tofino/bf-p4c/parde/marshal.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ inline std::ostream &operator<<(std::ostream &s, const MarshaledFrom &m) {
return s;
}

inline JSONGenerator &operator<<(JSONGenerator &out, const MarshaledFrom &c) {
c.toJSON(out);
return out;
}

} // namespace P4

#endif /* PARDE_MARSHAL_H_ */
6 changes: 1 addition & 5 deletions backends/tofino/bf-p4c/parde/match_register.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,11 @@ MatchRegister::MatchRegister(cstring n) : name(n), id(s_id++) {
BUG("Invalid parser match register %s", name);
}

void MatchRegister::toJSON(JSONGenerator &json) const { json << *this; }
void MatchRegister::toJSON(JSONGenerator &json) const { json.emit(toString()); }

/* static */
MatchRegister MatchRegister::fromJSON(JSONLoader &json) {
if (auto *v = json.json->to<JsonString>()) return MatchRegister(cstring(v->c_str()));
BUG("Couldn't decode JSON value to parser match register");
return MatchRegister();
}

P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const MatchRegister &c) {
return out << c.toString();
}
6 changes: 1 addition & 5 deletions backends/tofino/bf-p4c/phv/phv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ cstring Container::toString() const {
return tmp.str();
}

void Container::toJSON(P4::JSONGenerator &json) const { json << *this; }
void Container::toJSON(P4::JSONGenerator &json) const { json.emit(toString()); }

/* static */ Container Container::fromJSON(P4::JSONLoader &json) {
if (auto *v = json.json->to<JsonString>()) return Container(v->c_str());
Expand Down Expand Up @@ -259,10 +259,6 @@ std::ostream &operator<<(std::ostream &out, const PHV::Container c) {
return out << c.type() << c.index();
}

P4::JSONGenerator &operator<<(P4::JSONGenerator &out, const PHV::Container c) {
return out << c.toString();
}

std::ostream &operator<<(std::ostream &out, ordered_set<const PHV::Container *> &c_set) {
out << "{";
for (auto &c : c_set) {
Expand Down
45 changes: 12 additions & 33 deletions ir/ir-inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,18 +138,11 @@ void IR::Vector<T>::parallel_visit_children(Visitor &v, const char *) const {
IRNODE_DEFINE_APPLY_OVERLOAD(Vector, template <class T>, <T>)
template <class T>
void IR::Vector<T>::toJSON(JSONGenerator &json) const {
const char *sep = "";
Node::toJSON(json);
json << "," << std::endl << json.indent++ << "\"vec\" : [";
for (auto &k : vec) {
json << sep << std::endl << json.indent << k;
sep = ",";
}
--json.indent;
if (*sep) {
json << std::endl << json.indent;
}
json << "]";
json.emit_tag("vec");
auto state = json.begin_vector();
for (auto &k : vec) json.emit(k);
json.end_vector(state);
}

std::ostream &operator<<(std::ostream &out, const IR::Vector<IR::Expression> &v);
Expand Down Expand Up @@ -188,18 +181,11 @@ void IR::IndexedVector<T>::visit_children(Visitor &v, const char *name) const {
}
template <class T>
void IR::IndexedVector<T>::toJSON(JSONGenerator &json) const {
const char *sep = "";
Vector<T>::toJSON(json);
json << "," << std::endl << json.indent++ << "\"declarations\" : {";
for (const auto &k : declarations) {
json << sep << std::endl << json.indent << k.first << " : " << k.second;
sep = ",";
}
--json.indent;
if (*sep != 0) {
json << std::endl << json.indent;
}
json << "}";
json.emit_tag("declarations");
auto state = json.begin_object();
for (auto &k : declarations) json.emit(k.first, k.second);
json.end_object(state);
}
IRNODE_DEFINE_APPLY_OVERLOAD(IndexedVector, template <class T>, <T>)

Expand Down Expand Up @@ -278,18 +264,11 @@ template <class T, template <class K, class V, class COMP, class ALLOC> class MA
class COMP /*= std::less<cstring>*/,
class ALLOC /*= std::allocator<std::pair<cstring, const T*>>*/>
void IR::NameMap<T, MAP, COMP, ALLOC>::toJSON(JSONGenerator &json) const {
const char *sep = "";
Node::toJSON(json);
json << "," << std::endl << json.indent++ << "\"symbols\" : {";
for (auto &k : symbols) {
json << sep << std::endl << json.indent << k.first << " : " << k.second;
sep = ",";
}
--json.indent;
if (*sep) {
json << std::endl << json.indent;
}
json << "}";
json.emit_tag("symbols");
auto state = json.begin_object();
for (auto &k : symbols) json.emit(k.first, k.second);
json.end_object(state);
}

template <class KEY, class VALUE,
Expand Down
Loading

0 comments on commit d04dde0

Please sign in to comment.