From 2524925c81817ffa0ccda42924d4482acbc82300 Mon Sep 17 00:00:00 2001 From: Nitish Date: Sat, 10 Aug 2024 23:01:50 +0530 Subject: [PATCH 01/16] [p4fmt]: pretty printer for p4fmt Signed-off-by: Nitish --- backends/p4fmt/CMakeLists.txt | 2 + backends/p4fmt/p4fmt.cpp | 4 +- backends/p4fmt/toP4/toP4.cpp | 1658 +++++++++++++++++++++++++++++++++ backends/p4fmt/toP4/toP4.h | 266 ++++++ 4 files changed, 1928 insertions(+), 2 deletions(-) create mode 100644 backends/p4fmt/toP4/toP4.cpp create mode 100644 backends/p4fmt/toP4/toP4.h diff --git a/backends/p4fmt/CMakeLists.txt b/backends/p4fmt/CMakeLists.txt index a12fc774636..ebc8869c6d6 100644 --- a/backends/p4fmt/CMakeLists.txt +++ b/backends/p4fmt/CMakeLists.txt @@ -2,12 +2,14 @@ set(FMT_SRCS p4fmt.cpp options.cpp main.cpp + toP4/toP4.cpp ) set(REFCHECK_SRCS refcheck.cpp options.cpp p4fmt.cpp + toP4/toP4.cpp ) # p4fmt diff --git a/backends/p4fmt/p4fmt.cpp b/backends/p4fmt/p4fmt.cpp index 6296d37d80b..df5de3c2d3d 100644 --- a/backends/p4fmt/p4fmt.cpp +++ b/backends/p4fmt/p4fmt.cpp @@ -2,11 +2,11 @@ #include "frontends/common/parseInput.h" #include "frontends/common/parser_options.h" -#include "frontends/p4/toP4/toP4.h" #include "ir/ir.h" #include "lib/compile_context.h" #include "lib/error.h" #include "options.h" +#include "toP4/toP4.h" namespace P4::P4Fmt { @@ -24,7 +24,7 @@ std::stringstream getFormattedOutput(std::filesystem::path inputFile) { return formattedOutput; } - auto top4 = P4::ToP4(&formattedOutput, false); + auto top4 = P4Fmt::P4::ToP4(&formattedOutput, false); // Print the program before running front end passes. program->apply(top4); diff --git a/backends/p4fmt/toP4/toP4.cpp b/backends/p4fmt/toP4/toP4.cpp new file mode 100644 index 00000000000..03ca2c158b4 --- /dev/null +++ b/backends/p4fmt/toP4/toP4.cpp @@ -0,0 +1,1658 @@ +#include "toP4.h" + +#include +#include +#include + +#include "frontends/common/options.h" +#include "frontends/p4/fromv1.0/v1model.h" +#include "frontends/parsers/p4/p4parser.hpp" +#include "ir/dump.h" + +namespace P4Fmt { +namespace P4 { + +Visitor::profile_t ToP4::init_apply(const IR::Node *node) { + LOG4("Program dump:" << std::endl << dumpToString(node)); + listTerminators_init_apply_size = listTerminators.size(); + vectorSeparator_init_apply_size = vectorSeparator.size(); + return Inspector::init_apply(node); +} + +void ToP4::end_apply(const IR::Node *) { + if (outStream != nullptr) { + cstring result = builder.toString(); + *outStream << result.c_str(); + outStream->flush(); + } + BUG_CHECK(listTerminators.size() == listTerminators_init_apply_size, + "inconsistent listTerminators"); + BUG_CHECK(vectorSeparator.size() == vectorSeparator_init_apply_size, + "inconsistent vectorSeparator"); +} + +// Try to guess whether a file is a "system" file +bool ToP4::isSystemFile(cstring file) { + if (noIncludes) return false; + if (file.startsWith(p4includePath)) return true; + return false; +} + +cstring ToP4::ifSystemFile(const IR::Node *node) { + if (!node->srcInfo.isValid()) return nullptr; + auto sourceFile = node->srcInfo.getSourceFile(); + if (isSystemFile(sourceFile)) return sourceFile; + return nullptr; +} + +namespace { +class DumpIR : public Inspector { + unsigned depth; + std::stringstream str; + + DumpIR(unsigned depth, unsigned startDepth) : depth(depth) { + for (unsigned i = 0; i < startDepth; i++) str << IndentCtl::indent; + setName("DumpIR"); + visitDagOnce = false; + } + void display(const IR::Node *node) { + str << IndentCtl::endl; + if (node->is()) { + node->Node::dbprint(str); + str << node->to()->member; + } else if (node->is()) { + node->Node::dbprint(str); + str << " " << node; + } else if (node->is()) { + node->Node::dbprint(str); + str << ", size=" << node->to()->size(); + } else if (node->is()) { + node->dbprint(str); + } else { + node->Node::dbprint(str); + } + } + + bool goDeeper(const IR::Node *node) const { + return node->is() || node->is() || node->is(); + } + + bool preorder(const IR::Node *node) override { + if (depth == 0) return false; + display(node); + if (goDeeper(node)) + // increase depth limit for expressions. + depth++; + else + depth--; + str << IndentCtl::indent; + return true; + } + void postorder(const IR::Node *node) override { + if (goDeeper(node)) + depth--; + else + depth++; + str << IndentCtl::unindent; + } + + public: + static std::string dump(const IR::Node *node, unsigned depth, unsigned startDepth) { + DumpIR dumper(depth, startDepth); + node->apply(dumper); + auto result = dumper.str.str(); + return result; + } +}; +} // namespace + +unsigned ToP4::curDepth() const { + unsigned result = 0; + auto ctx = getContext(); + while (ctx != nullptr) { + ctx = ctx->parent; + result++; + } + return result; +} + +void ToP4::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) { + if (!showIR) return; + if (node == nullptr) node = getOriginal(); + + auto str = DumpIR::dump(node, depth, adjDepth + curDepth()); + bool spc = builder.lastIsSpace(); + builder.commentStart(); + builder.append(str); + builder.commentEnd(); + builder.newline(); + if (spc) + // rather heuristic, but the output is very ugly anyway + builder.emitIndent(); +} + +bool ToP4::preorder(const IR::P4Program *program) { + std::set includesEmitted; + + bool first = true; + dump(2); + for (auto a : program->objects) { + // Check where this declaration originates + cstring sourceFile = ifSystemFile(a); + if (!a->is() && // errors can come from multiple files + sourceFile != nullptr) { + /* FIXME -- when including a user header file (sourceFile != + * mainFile), do we want to emit an #include of it or not? Probably + * not when translating from P4-14, as that would create a P4-16 + * file that tries to include a P4-14 header. Unless we want to + * allow converting headers independently (is that even possible?). + * For now we ignore mainFile and don't emit #includes for any + * non-system header */ + + if (includesEmitted.find(sourceFile) == includesEmitted.end()) { + if (sourceFile.startsWith(p4includePath)) { + const char *p = sourceFile.c_str() + strlen(p4includePath); + if (*p == '/') p++; + if (P4V1::V1Model::instance.file.name == p) { + P4V1::getV1ModelVersion g; + program->apply(g); + builder.append("#define V1MODEL_VERSION "); + builder.append(g.version); + builder.newline(); + } + builder.append("#include <"); + builder.append(p); + builder.append(">"); + builder.newline(); + } else { + builder.append("#include \""); + builder.append(sourceFile); + builder.append("\""); + builder.newline(); + } + includesEmitted.emplace(sourceFile); + } + first = false; + continue; + } + if (!first) builder.newline(); + first = false; + visit(a); + } + if (!program->objects.empty()) builder.newline(); + return false; +} + +bool ToP4::preorder(const IR::Type_Bits *t) { + if (t->expression) { + builder.append("bit<("); + visit(t->expression); + builder.append(")>"); + } else { + builder.append(t->toString()); + } + return false; +} + +bool ToP4::preorder(const IR::Type_String *t) { + builder.append(t->toString()); + return false; +} + +bool ToP4::preorder(const IR::Type_InfInt *t) { + builder.append(t->toString()); + return false; +} + +bool ToP4::preorder(const IR::Type_Var *t) { + builder.append(t->name); + return false; +} + +bool ToP4::preorder(const IR::Type_Unknown *) { + BUG("Cannot emit code for an unknown type"); + // builder.append("*unknown type*"); + return false; +} + +bool ToP4::preorder(const IR::Type_Dontcare *) { + builder.append("_"); + return false; +} + +bool ToP4::preorder(const IR::Type_Void *) { + builder.append("void"); + return false; +} + +bool ToP4::preorder(const IR::Type_Name *t) { + visit(t->path); + return false; +} + +bool ToP4::preorder(const IR::Type_Stack *t) { + dump(2); + visit(t->elementType); + builder.append("["); + visit(t->size); + builder.append("]"); + return false; +} + +bool ToP4::preorder(const IR::Type_Specialized *t) { + dump(3); + visit(t->baseType); + builder.append("<"); + setVecSep(", "); + visit(t->arguments); + doneVec(); + builder.append(">"); + return false; +} + +bool ToP4::preorder(const IR::Argument *arg) { + dump(2); + if (!arg->name.name.isNullOrEmpty()) { + builder.append(arg->name.name); + builder.append(" = "); + } + visit(arg->expression); + return false; +} + +bool ToP4::preorder(const IR::Type_Typedef *t) { + dump(2); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("typedef "); + visit(t->type); + builder.spc(); + builder.append(t->name); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Type_Newtype *t) { + dump(2); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("type "); + visit(t->type); + builder.spc(); + builder.append(t->name); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Type_BaseList *t) { + dump(3); + builder.append("tuple<"); + bool first = true; + for (auto a : t->components) { + if (!first) builder.append(", "); + first = false; + auto p4type = a->getP4Type(); + CHECK_NULL(p4type); + visit(p4type); + } + builder.append(">"); + return false; +} + +bool ToP4::preorder(const IR::P4ValueSet *t) { + dump(1); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("value_set<"); + auto p4type = t->elementType->getP4Type(); + CHECK_NULL(p4type); + visit(p4type); + builder.append(">"); + builder.append("("); + visit(t->size); + builder.append(")"); + builder.spc(); + builder.append(t->name); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Type_Enum *t) { + dump(1); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("enum "); + builder.append(t->name); + builder.spc(); + builder.blockStart(); + bool first = true; + for (auto a : *t->getDeclarations()) { + dump(2, a->getNode(), 1); + if (!first) builder.append(",\n"); + first = false; + builder.emitIndent(); + builder.append(a->getName()); + } + builder.newline(); + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::Type_SerEnum *t) { + dump(1); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("enum "); + visit(t->type); + builder.spc(); + builder.append(t->name); + builder.spc(); + builder.blockStart(); + bool first = true; + for (auto a : t->members) { + dump(2, a->getNode(), 1); + if (!first) builder.append(",\n"); + first = false; + builder.emitIndent(); + builder.append(a->getName()); + builder.append(" = "); + visit(a->value); + } + builder.newline(); + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::TypeParameters *t) { + if (!t->empty()) { + builder.append("<"); + bool first = true; + bool decl = isDeclaration; + isDeclaration = false; + for (auto a : t->parameters) { + if (!first) builder.append(", "); + first = false; + visit(a); + } + isDeclaration = decl; + builder.append(">"); + } + return false; +} + +bool ToP4::preorder(const IR::Method *m) { + dump(1); + if (!m->annotations->annotations.empty()) { + visit(m->annotations); + builder.spc(); + } + const Context *ctx = getContext(); + bool standaloneFunction = !ctx || !ctx->node->is(); + // standalone function declaration: not in a Vector of methods + if (standaloneFunction) builder.append("extern "); + + if (m->isAbstract) builder.append("abstract "); + auto t = m->type; + BUG_CHECK(t != nullptr, "Method %1% has no type", m); + if (t->returnType != nullptr) { + visit(t->returnType); + builder.spc(); + } + builder.append(m->name); + visit(t->typeParameters); + visit(t->parameters); + if (standaloneFunction) builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Function *function) { + dump(1); + if (!function->annotations->annotations.empty()) { + visit(function->annotations); + builder.spc(); + } + auto t = function->type; + BUG_CHECK(t != nullptr, "Function %1% has no type", function); + if (t->returnType != nullptr) { + visit(t->returnType); + builder.spc(); + } + builder.append(function->name); + visit(t->typeParameters); + visit(t->parameters); + builder.spc(); + visit(function->body); + return false; +} + +bool ToP4::preorder(const IR::Type_Extern *t) { + dump(2); + if (isDeclaration) { + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("extern "); + } + builder.append(t->name); + visit(t->typeParameters); + if (!isDeclaration) return false; + builder.spc(); + builder.blockStart(); + + if (t->attributes.size() != 0) + warn(ErrorType::WARN_UNSUPPORTED, + "%1%: extern has attributes, which are not supported " + "in P4-16, and thus are not emitted as P4-16", + t); + + setVecSep(";\n", ";\n"); + bool decl = isDeclaration; + isDeclaration = true; + preorder(&t->methods); + isDeclaration = decl; + doneVec(); + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::Type_Boolean *) { + builder.append("bool"); + return false; +} + +bool ToP4::preorder(const IR::Type_Varbits *t) { + if (t->expression) { + builder.append("varbit<("); + visit(t->expression); + builder.append(")>"); + } else { + builder.appendFormat("varbit<%d>", t->size); + } + return false; +} + +bool ToP4::preorder(const IR::Type_Package *package) { + dump(2); + builder.emitIndent(); + if (!package->annotations->annotations.empty()) { + visit(package->annotations); + builder.spc(); + } + builder.append("package "); + builder.append(package->name); + visit(package->typeParameters); + visit(package->constructorParams); + if (isDeclaration) builder.endOfStatement(); + return false; +} + +bool ToP4::process(const IR::Type_StructLike *t, const char *name) { + dump(2); + if (isDeclaration) { + builder.emitIndent(); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.appendFormat("%s ", name); + } + builder.append(t->name); + visit(t->typeParameters); + if (!isDeclaration) return false; + builder.spc(); + builder.blockStart(); + + std::map type; + size_t len = 0; + for (auto f : t->fields) { + Util::SourceCodeBuilder builder; + ToP4 rec(builder, showIR); + + f->type->apply(rec); + cstring t = builder.toString(); + if (t.size() > len) len = t.size(); + type.emplace(f, t); + } + + for (auto f : t->fields) { + dump(4, f, 1); // this will dump annotations + if (f->annotations->size() > 0) { + builder.emitIndent(); + if (!f->annotations->annotations.empty()) { + visit(f->annotations); + } + builder.newline(); + } + builder.emitIndent(); + cstring t = get(type, f); + builder.append(t); + size_t spaces = len + 1 - t.size(); + builder.append(std::string(spaces, ' ')); + builder.append(f->name); + builder.endOfStatement(true); + } + + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::Type_Parser *t) { + dump(2); + builder.emitIndent(); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("parser "); + builder.append(t->name); + visit(t->typeParameters); + visit(t->applyParams); + if (isDeclaration) builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Type_Control *t) { + dump(2); + builder.emitIndent(); + if (!t->annotations->annotations.empty()) { + visit(t->annotations); + builder.spc(); + } + builder.append("control "); + builder.append(t->name); + visit(t->typeParameters); + visit(t->applyParams); + if (isDeclaration) builder.endOfStatement(); + return false; +} + +/////////////////////// + +bool ToP4::preorder(const IR::Constant *c) { + const IR::Type_Bits *tb = c->type->to(); + unsigned width; + bool sign; + if (tb == nullptr) { + width = 0; + sign = false; + } else { + width = tb->size; + sign = tb->isSigned; + } + cstring s = Util::toString(c->value, width, sign, c->base); + builder.append(s); + return false; +} + +bool ToP4::preorder(const IR::BoolLiteral *b) { + builder.append(b->toString()); + return false; +} + +bool ToP4::preorder(const IR::StringLiteral *s) { + builder.append(s->toString()); + return false; +} + +bool ToP4::preorder(const IR::Declaration_Constant *cst) { + dump(2); + if (!cst->annotations->annotations.empty()) { + visit(cst->annotations); + builder.spc(); + } + builder.append("const "); + auto type = cst->type->getP4Type(); + CHECK_NULL(type); + visit(type); + builder.spc(); + builder.append(cst->name); + builder.append(" = "); + + setListTerm("{ ", " }"); + visit(cst->initializer); + doneList(); + + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Declaration_Instance *i) { + dump(3); + if (!i->annotations->annotations.empty()) { + visit(i->annotations); + builder.spc(); + } + auto type = i->type->getP4Type(); + CHECK_NULL(type); + visit(type); + builder.append("("); + setVecSep(", "); + visit(i->arguments); + doneVec(); + builder.append(")"); + builder.spc(); + builder.append(i->name); + if (i->initializer != nullptr) { + builder.append(" = "); + visit(i->initializer); + } + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Declaration_Variable *v) { + dump(2); + if (!v->annotations->annotations.empty()) { + visit(v->annotations); + builder.spc(); + } + auto type = v->type->getP4Type(); + CHECK_NULL(type); + visit(type); + builder.spc(); + builder.append(v->name); + if (v->initializer != nullptr) { + builder.append(" = "); + setListTerm("{ ", " }"); + visit(v->initializer); + doneList(); + } + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::Type_Error *d) { + dump(1); + bool first = true; + for (auto a : *d->getDeclarations()) { + if (ifSystemFile(a->getNode())) + // only print if not from a system file + continue; + if (!first) { + builder.append(",\n"); + } else { + builder.append("error "); + builder.blockStart(); + } + dump(1, a->getNode(), 1); + first = false; + builder.emitIndent(); + builder.append(a->getName()); + } + if (!first) { + builder.newline(); + builder.blockEnd(true); + } + return false; +} + +bool ToP4::preorder(const IR::Declaration_MatchKind *d) { + dump(1); + builder.append("match_kind "); + builder.blockStart(); + bool first = true; + for (auto a : *d->getDeclarations()) { + if (!first) builder.append(",\n"); + dump(1, a->getNode(), 1); + first = false; + builder.emitIndent(); + builder.append(a->getName()); + } + builder.newline(); + builder.blockEnd(true); + return false; +} + +/////////////////////////////////////////////////// + +#define VECTOR_VISIT(V, T) \ + bool ToP4::preorder(const IR::V *v) { \ + if (v == nullptr) return false; \ + bool first = true; \ + VecPrint sep = getSep(); \ + for (auto a : *v) { \ + if (!first) { \ + builder.append(sep.separator); \ + } \ + if (sep.separator.endsWith("\n")) { \ + builder.emitIndent(); \ + } \ + first = false; \ + visit(a); \ + } \ + if (!v->empty() && !sep.terminator.isNullOrEmpty()) { \ + builder.append(sep.terminator); \ + } \ + return false; \ + } + +VECTOR_VISIT(Vector, ActionListElement) +VECTOR_VISIT(Vector, Annotation) +VECTOR_VISIT(Vector, Entry) +VECTOR_VISIT(Vector, Expression) +VECTOR_VISIT(Vector, Argument) +VECTOR_VISIT(Vector, KeyElement) +VECTOR_VISIT(Vector, Method) +VECTOR_VISIT(Vector, Node) +VECTOR_VISIT(Vector, SelectCase) +VECTOR_VISIT(Vector, SwitchCase) +VECTOR_VISIT(Vector, Type) +VECTOR_VISIT(IndexedVector, Declaration) +VECTOR_VISIT(IndexedVector, Declaration_ID) +VECTOR_VISIT(IndexedVector, Node) +VECTOR_VISIT(IndexedVector, ParserState) +VECTOR_VISIT(IndexedVector, StatOrDecl) + +#undef VECTOR_VISIT + +/////////////////////////////////////////// + +bool ToP4::preorder(const IR::Slice *slice) { + int prec = expressionPrecedence; + bool useParens = prec > slice->getPrecedence(); + if (useParens) builder.append("("); + expressionPrecedence = slice->getPrecedence(); + + visit(slice->e0); + builder.append("["); + expressionPrecedence = DBPrint::Prec_Low; + visit(slice->e1); + builder.append(":"); + expressionPrecedence = DBPrint::Prec_Low; + visit(slice->e2); + builder.append("]"); + expressionPrecedence = prec; + + if (useParens) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::DefaultExpression *) { + // Within a method call this is rendered as a don't care + if (withinArgument) + builder.append("_"); + else + builder.append("default"); + return false; +} + +bool ToP4::preorder(const IR::This *) { + builder.append("this"); + return false; +} + +bool ToP4::preorder(const IR::PathExpression *p) { + visit(p->path); + return false; +} + +bool ToP4::preorder(const IR::TypeNameExpression *e) { + visit(e->typeName); + return false; +} + +bool ToP4::preorder(const IR::ConstructorCallExpression *e) { + visit(e->constructedType); + builder.append("("); + setVecSep(", "); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + visit(e->arguments); + expressionPrecedence = prec; + doneVec(); + builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::Member *e) { + int prec = expressionPrecedence; + expressionPrecedence = e->getPrecedence(); + visit(e->expr); + builder.append("."); + builder.append(e->member); + expressionPrecedence = prec; + return false; +} + +bool ToP4::preorder(const IR::SelectCase *e) { + dump(2); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + setListTerm("(", ")"); + visit(e->keyset); + expressionPrecedence = prec; + doneList(); + builder.append(": "); + visit(e->state); + return false; +} + +bool ToP4::preorder(const IR::SelectExpression *e) { + builder.append("select("); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + setListTerm("", ""); + visit(e->select); + doneList(); + builder.append(") "); + builder.blockStart(); + setVecSep(";\n", ";\n"); + expressionPrecedence = DBPrint::Prec_Low; + preorder(&e->selectCases); + doneVec(); + builder.blockEnd(true); + expressionPrecedence = prec; + return false; +} + +bool ToP4::preorder(const IR::ListExpression *e) { + using ::P4::literals::operator""_cs; + cstring start, end; + if (listTerminators.empty()) { + start = "{ "_cs; + end = " }"_cs; + } else { + start = listTerminators.back().start; + end = listTerminators.back().end; + } + builder.append(start); + setVecSep(", "); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + setListTerm("{ ", " }"); + preorder(&e->components); + doneList(); + expressionPrecedence = prec; + doneVec(); + builder.append(end); + return false; +} + +bool ToP4::preorder(const IR::P4ListExpression *e) { + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); + if (e->elementType != nullptr) { + builder.append("(list<"); + visit(e->elementType->getP4Type()); + builder.append(">)"); + } + builder.append("{"); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + bool first = true; + for (auto c : e->components) { + if (!first) builder.append(","); + first = false; + visit(c); + } + expressionPrecedence = prec; + builder.append("}"); + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::NamedExpression *e) { + builder.append(e->name.name); + builder.append(" = "); + visit(e->expression); + return false; +} + +bool ToP4::preorder(const IR::StructExpression *e) { + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); + if (e->structType != nullptr) { + builder.append("("); + visit(e->structType); + builder.append(")"); + } + builder.append("{"); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + bool first = true; + for (auto c : e->components) { + if (!first) builder.append(","); + first = false; + visit(c); + } + expressionPrecedence = prec; + builder.append("}"); + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::HeaderStackExpression *e) { + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); + if (e->headerStackType != nullptr) { + builder.append("("); + visit(e->headerStackType); + builder.append(")"); + } + builder.append("{"); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + bool first = true; + for (auto c : e->components) { + if (!first) builder.append(","); + first = false; + visit(c); + } + expressionPrecedence = prec; + builder.append("}"); + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::Invalid *) { + builder.append("{#}"); + return false; +} + +bool ToP4::preorder(const IR::Dots *) { + builder.append("..."); + return false; +} + +bool ToP4::preorder(const IR::NamedDots *) { + builder.append("..."); + return false; +} + +bool ToP4::preorder(const IR::InvalidHeader *e) { + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); + builder.append("("); + visit(e->headerType); + builder.append(")"); + builder.append("{#}"); + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::InvalidHeaderUnion *e) { + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); + builder.append("("); + visit(e->headerUnionType); + builder.append(")"); + builder.append("{#}"); + if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::MethodCallExpression *e) { + int prec = expressionPrecedence; + bool useParens = (prec > DBPrint::Prec_Postfix) || + (!e->typeArguments->empty() && prec >= DBPrint::Prec_Cond); + // FIXME: we use parenthesis more often than necessary + // because the bison parser has a bug which parses + // these expressions incorrectly. + expressionPrecedence = DBPrint::Prec_Postfix; + if (useParens) builder.append("("); + visit(e->method); + if (!e->typeArguments->empty()) { + bool decl = isDeclaration; + isDeclaration = false; + builder.append("<"); + setVecSep(", "); + visit(e->typeArguments); + doneVec(); + builder.append(">"); + isDeclaration = decl; + } + builder.append("("); + setVecSep(", "); + expressionPrecedence = DBPrint::Prec_Low; + withinArgument = true; + visit(e->arguments); + withinArgument = false; + doneVec(); + builder.append(")"); + if (useParens) builder.append(")"); + expressionPrecedence = prec; + return false; +} + +bool ToP4::preorder(const IR::Operation_Binary *b) { + int prec = expressionPrecedence; + bool useParens = prec > b->getPrecedence(); + if (useParens) builder.append("("); + expressionPrecedence = b->getPrecedence(); + visit(b->left); + builder.spc(); + builder.append(b->getStringOp()); + builder.spc(); + expressionPrecedence = b->getPrecedence() + 1; + visit(b->right); + if (useParens) builder.append(")"); + expressionPrecedence = prec; + return false; +} + +bool ToP4::preorder(const IR::Mux *b) { + int prec = expressionPrecedence; + bool useParens = prec >= b->getPrecedence(); + if (useParens) builder.append("("); + expressionPrecedence = b->getPrecedence(); + visit(b->e0); + builder.append(" ? "); + expressionPrecedence = DBPrint::Prec_Low; + visit(b->e1); + builder.append(" : "); + expressionPrecedence = b->getPrecedence(); + visit(b->e2); + expressionPrecedence = prec; + if (useParens) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::Operation_Unary *u) { + int prec = expressionPrecedence; + bool useParens = prec > u->getPrecedence(); + if (useParens) builder.append("("); + builder.append(u->getStringOp()); + expressionPrecedence = u->getPrecedence(); + visit(u->expr); + expressionPrecedence = prec; + if (useParens) builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::ArrayIndex *a) { + int prec = expressionPrecedence; + bool useParens = prec > a->getPrecedence(); + if (useParens) builder.append("("); + expressionPrecedence = a->getPrecedence(); + visit(a->left); + builder.append("["); + expressionPrecedence = DBPrint::Prec_Low; + visit(a->right); + builder.append("]"); + if (useParens) builder.append(")"); + expressionPrecedence = prec; + return false; +} + +bool ToP4::preorder(const IR::Cast *c) { + int prec = expressionPrecedence; + bool useParens = prec > c->getPrecedence(); + if (useParens) builder.append("("); + builder.append("("); + visit(c->destType); + builder.append(")"); + expressionPrecedence = c->getPrecedence(); + visit(c->expr); + if (useParens) builder.append(")"); + expressionPrecedence = prec; + return false; +} + +////////////////////////////////////////////////////////// + +bool ToP4::preorder(const IR::AssignmentStatement *a) { + dump(2); + visit(a->left); + builder.append(" = "); + visit(a->right); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::BlockStatement *s) { + dump(1); + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.blockStart(); + setVecSep("\n", "\n"); + preorder(&s->components); + doneVec(); + builder.blockEnd(false); + return false; +} + +bool ToP4::preorder(const IR::BreakStatement *) { + dump(1); + builder.append("break"); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::ContinueStatement *) { + dump(1); + builder.append("continue"); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::ExitStatement *) { + dump(1); + builder.append("exit"); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::ReturnStatement *statement) { + dump(2); + builder.append("return"); + if (statement->expression != nullptr) { + builder.spc(); + visit(statement->expression); + } + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::EmptyStatement *) { + dump(1); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::IfStatement *s) { + dump(2); + builder.append("if ("); + visit(s->condition); + builder.append(") "); + if (!s->ifTrue->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->ifTrue); + if (!s->ifTrue->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + if (s->ifFalse != nullptr) { + builder.append(" else "); + if (!s->ifFalse->is() && !s->ifFalse->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->ifFalse); + if (!s->ifFalse->is() && !s->ifFalse->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + } + return false; +} + +bool ToP4::preorder(const IR::ForStatement *s) { + dump(2); + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.append("for ("); + bool first = true; + for (auto *d : s->init) { + if (!first) builder.append(", "); + builder.supressStatementSemi(); + visit(d, "init"); + first = false; + } + builder.append("; "); + visit(s->condition, "condition"); + builder.append("; "); + first = true; + for (auto *e : s->updates) { + if (e->is()) continue; + if (!first) builder.append(", "); + builder.supressStatementSemi(); + visit(e, "updates"); + first = false; + } + builder.append(") "); + if (!s->body->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->body, "body"); + if (!s->body->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + return false; +} + +bool ToP4::preorder(const IR::ForInStatement *s) { + dump(2); + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.append("for ("); + if (s->decl) { + builder.supressStatementSemi(); + visit(s->decl, "decl"); + } else { + auto *decl = resolveUnique(s->ref->path->name, ::P4::ResolutionType::Any); + if (auto *di = decl->to()) { + builder.supressStatementSemi(); + visit(di, "decl"); + } else { + visit(s->ref, "ref"); + } + } + builder.append(" in "); + visit(s->collection); + builder.append(") "); + if (!s->body->is()) { + builder.append("{"); + builder.increaseIndent(); + builder.newline(); + builder.emitIndent(); + } + visit(s->body, "body"); + if (!s->body->is()) { + builder.newline(); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + } + return false; +} + +bool ToP4::preorder(const IR::MethodCallStatement *s) { + dump(3); + visit(s->methodCall); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::SwitchCase *s) { + visit(s->label); + builder.append(": "); + visit(s->statement); + return false; +} + +bool ToP4::preorder(const IR::SwitchStatement *s) { + dump(4); + builder.append("switch ("); + visit(s->expression); + builder.append(") "); + builder.blockStart(); + setVecSep("\n", "\n"); + preorder(&s->cases); + doneVec(); + builder.blockEnd(false); + return false; +} + +//////////////////////////////////// + +bool ToP4::preorder(const IR::Annotations *a) { + bool first = true; + for (const auto *anno : a->annotations) { + if (!first) { + builder.spc(); + } else { + first = false; + } + visit(anno); + } + return false; +} + +bool ToP4::preorder(const IR::Annotation *a) { + builder.append("@"); + builder.append(a->name); + const char *open = a->structured ? "[" : "("; + const char *close = a->structured ? "]" : ")"; + if (!a->expr.empty()) { + builder.append(open); + setVecSep(", "); + preorder(&a->expr); + doneVec(); + builder.append(close); + } + if (!a->kv.empty()) { + builder.append(open); + bool first = true; + for (auto kvp : a->kv) { + if (!first) builder.append(", "); + first = false; + builder.append(kvp->name); + builder.append("="); + visit(kvp->expression); + } + builder.append(close); + } + if (a->expr.empty() && a->kv.empty() && a->structured) { + builder.append("[]"); + } + if (!a->body.empty() && a->expr.empty() && a->kv.empty()) { + // Have an unparsed annotation. + // We could be prettier here with smarter logic, but let's do the easy + // thing by separating every token with a space. + builder.append(open); + bool first = true; + for (auto tok : a->body) { + if (!first) builder.append(" "); + first = false; + + bool haveStringLiteral = + tok->token_type == ::P4::P4Parser::token_type::TOK_STRING_LITERAL; + if (haveStringLiteral) builder.append("\""); + builder.append(tok->text); + if (haveStringLiteral) builder.append("\""); + } + builder.append(close); + } + return false; +} + +bool ToP4::preorder(const IR::Parameter *p) { + dump(2); + if (!p->annotations->annotations.empty()) { + visit(p->annotations); + builder.spc(); + } + switch (p->direction) { + case IR::Direction::None: + break; + case IR::Direction::In: + builder.append("in "); + break; + case IR::Direction::Out: + builder.append("out "); + break; + case IR::Direction::InOut: + builder.append("inout "); + break; + default: + BUG("Unexpected case"); + } + bool decl = isDeclaration; + isDeclaration = false; + visit(p->type); + isDeclaration = decl; + builder.spc(); + builder.append(p->name); + if (p->defaultValue != nullptr) { + builder.append("="); + visit(p->defaultValue); + } + return false; +} + +bool ToP4::preorder(const IR::P4Control *c) { + dump(1); + bool decl = isDeclaration; + isDeclaration = false; + visit(c->type); + isDeclaration = decl; + if (c->constructorParams->size() != 0) visit(c->constructorParams); + builder.spc(); + builder.blockStart(); + for (auto s : c->controlLocals) { + builder.emitIndent(); + visit(s); + builder.newline(); + } + + builder.emitIndent(); + builder.append("apply "); + visit(c->body); + builder.newline(); + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::ParameterList *p) { + builder.append("("); + bool first = true; + for (auto param : *p->getEnumerator()) { + if (!first) builder.append(", "); + first = false; + visit(param); + } + builder.append(")"); + return false; +} + +bool ToP4::preorder(const IR::P4Action *c) { + dump(2); + if (!c->annotations->annotations.empty()) { + visit(c->annotations); + builder.spc(); + } + builder.append("action "); + builder.append(c->name); + visit(c->parameters); + builder.spc(); + visit(c->body); + return false; +} + +bool ToP4::preorder(const IR::ParserState *s) { + dump(1); + if (s->isBuiltin()) return false; + + if (!s->annotations->annotations.empty()) { + visit(s->annotations); + builder.spc(); + } + builder.append("state "); + builder.append(s->name); + builder.spc(); + builder.blockStart(); + setVecSep("\n", "\n"); + preorder(&s->components); + doneVec(); + + if (s->selectExpression != nullptr) { + dump(2, s->selectExpression, 1); + builder.emitIndent(); + builder.append("transition "); + visit(s->selectExpression); + if (!s->selectExpression->is()) { + builder.endOfStatement(); + builder.newline(); + } + } + builder.blockEnd(false); + return false; +} + +bool ToP4::preorder(const IR::P4Parser *c) { + dump(1); + bool decl = isDeclaration; + isDeclaration = false; + visit(c->type); + isDeclaration = decl; + if (c->constructorParams->size() != 0) visit(c->constructorParams); + builder.spc(); + builder.blockStart(); + setVecSep("\n", "\n"); + preorder(&c->parserLocals); + doneVec(); + // explicit visit of parser states + for (auto s : c->states) { + if (s->isBuiltin()) continue; + builder.emitIndent(); + visit(s); + builder.append("\n"); + } + builder.blockEnd(true); + return false; +} + +bool ToP4::preorder(const IR::ExpressionValue *v) { + dump(2); + visit(v->expression); + builder.endOfStatement(); + return false; +} + +bool ToP4::preorder(const IR::ActionListElement *ale) { + dump(3); + if (!ale->annotations->annotations.empty()) { + visit(ale->annotations); + builder.spc(); + } + visit(ale->expression); + return false; +} + +bool ToP4::preorder(const IR::ActionList *v) { + dump(2); + builder.blockStart(); + setVecSep(";\n", ";\n"); + preorder(&v->actionList); + doneVec(); + builder.blockEnd(false); + return false; +} + +bool ToP4::preorder(const IR::Key *v) { + dump(2); + builder.blockStart(); + + std::map kf; + size_t len = 0; + for (auto f : v->keyElements) { + Util::SourceCodeBuilder builder; + ToP4 rec(builder, showIR); + + f->expression->apply(rec); + cstring s = builder.toString(); + if (s.size() > len) len = s.size(); + kf.emplace(f, s); + } + + for (auto f : v->keyElements) { + dump(2, f, 2); + builder.emitIndent(); + cstring s = get(kf, f); + builder.append(s); + size_t spaces = len - s.size(); + builder.append(std::string(spaces, ' ')); + builder.append(": "); + visit(f->matchType); + if (!f->annotations->annotations.empty()) { + builder.append(" "); + visit(f->annotations); + } + builder.endOfStatement(true); + } + builder.blockEnd(false); + return false; +} + +bool ToP4::preorder(const IR::Property *p) { + dump(1); + if (!p->annotations->annotations.empty()) { + visit(p->annotations); + builder.spc(); + } + if (p->isConstant) builder.append("const "); + builder.append(p->name); + builder.append(" = "); + visit(p->value); + return false; +} + +bool ToP4::preorder(const IR::TableProperties *t) { + for (auto p : t->properties) { + builder.emitIndent(); + visit(p); + builder.newline(); + } + return false; +} + +bool ToP4::preorder(const IR::EntriesList *l) { + dump(1); + builder.append("{"); + builder.newline(); + builder.increaseIndent(); + visit(&l->entries); + builder.decreaseIndent(); + builder.emitIndent(); + builder.append("}"); + return false; +} + +bool ToP4::preorder(const IR::Entry *e) { + dump(2); + builder.emitIndent(); + if (e->isConst) builder.append("const "); + if (e->priority) { + builder.append("priority="); + visit(e->priority); + builder.append(": "); + } + if (e->keys->components.size() == 1) + setListTerm("", ""); + else + setListTerm("(", ")"); + visit(e->keys); + doneList(); + builder.append(" : "); + visit(e->action); + if (!e->annotations->annotations.empty()) { + visit(e->annotations); + } + builder.append(";"); + return false; +} + +bool ToP4::preorder(const IR::P4Table *c) { + dump(2); + if (!c->annotations->annotations.empty()) { + visit(c->annotations); + builder.spc(); + } + builder.append("table "); + builder.append(c->name); + builder.spc(); + builder.blockStart(); + setVecSep("\n", "\n"); + visit(c->properties); + doneVec(); + builder.blockEnd(false); + return false; +} + +bool ToP4::preorder(const IR::Path *p) { + builder.append(p->asString()); + return false; +} + +std::string toP4(const IR::INode *node) { + std::stringstream stream; + P4::ToP4 toP4(&stream, false); + node->getNode()->apply(toP4); + return stream.str(); +} + +void dumpP4(const IR::INode *node) { + auto s = toP4(node); + std::cout << s; +} + +} // namespace P4 +} // namespace P4Fmt diff --git a/backends/p4fmt/toP4/toP4.h b/backends/p4fmt/toP4/toP4.h new file mode 100644 index 00000000000..e137ba14ef2 --- /dev/null +++ b/backends/p4fmt/toP4/toP4.h @@ -0,0 +1,266 @@ +#ifndef P4FMT_TOP4_TOP4_H_ +#define P4FMT_TOP4_TOP4_H_ + +#include "frontends/common/resolveReferences/resolveReferences.h" +#include "ir/ir.h" +#include "ir/visitor.h" +#include "lib/sourceCodeBuilder.h" + +namespace P4Fmt { +namespace P4 { + +/** +This pass converts a P4-16 IR into a P4 source (text) program. +It can optionally emit as comments a representation of the program IR. +*/ +class ToP4 : public Inspector, ::P4::ResolutionContext { + int expressionPrecedence; /// precedence of current IR::Operation + bool isDeclaration; /// current type is a declaration + bool showIR; /// if true dump IR as comments + bool withinArgument; /// if true we are within a method call argument + bool noIncludes = false; /// If true do not generate #include statements. + /// Used for debugging. + + struct VecPrint { + cstring separator; + cstring terminator; + + VecPrint(const char *sep, const char *term) : separator(sep), terminator(term) {} + }; + + struct ListPrint { + cstring start; + cstring end; + + ListPrint(const char *start, const char *end) : start(start), end(end) {} + }; + + // maintained as stacks + std::vector vectorSeparator; + size_t vectorSeparator_init_apply_size = 0; + std::vector listTerminators; + size_t listTerminators_init_apply_size = 0; + + void setVecSep(const char *sep, const char *term = nullptr) { + vectorSeparator.push_back(VecPrint(sep, term)); + } + void doneVec() { + BUG_CHECK(!vectorSeparator.empty(), "Empty vectorSeparator"); + vectorSeparator.pop_back(); + } + VecPrint getSep() { + BUG_CHECK(!vectorSeparator.empty(), "Empty vectorSeparator"); + return vectorSeparator.back(); + } + + void doneList() { + BUG_CHECK(!listTerminators.empty(), "Empty listTerminators"); + listTerminators.pop_back(); + } + bool isSystemFile(cstring file); + cstring ifSystemFile(const IR::Node *node); // return file containing node if system file + // dump node IR tree up to depth - in the form of a comment + void dump(unsigned depth, const IR::Node *node = nullptr, unsigned adjDepth = 0); + unsigned curDepth() const; + + public: + // Output is constructed here + Util::SourceCodeBuilder &builder; + /* FIXME -- simplify this by getting rid of the 'builder' object and just emitting + * directly to the ostream. The SourceCodeBuilder object does not appear to add any + * useful functionality the ostream does not already provide; it just serves to + * obfuscate the code */ + std::ostream *outStream; + /** If this is set to non-nullptr, some declarations + that come from libraries and models are not + emitted. */ + cstring mainFile; + + ToP4(Util::SourceCodeBuilder &builder, bool showIR, cstring mainFile = nullptr) + : expressionPrecedence(DBPrint::Prec_Low), + isDeclaration(true), + showIR(showIR), + withinArgument(false), + builder(builder), + outStream(nullptr), + mainFile(mainFile) { + visitDagOnce = false; + setName("ToP4"); + } + ToP4(std::ostream *outStream, bool showIR, cstring mainFile = nullptr) + : expressionPrecedence(DBPrint::Prec_Low), + isDeclaration(true), + showIR(showIR), + withinArgument(false), + builder(*new Util::SourceCodeBuilder()), + outStream(outStream), + mainFile(mainFile) { + visitDagOnce = false; + setName("ToP4"); + } + ToP4() + : // this is useful for debugging + expressionPrecedence(DBPrint::Prec_Low), + isDeclaration(true), + showIR(false), + withinArgument(false), + builder(*new Util::SourceCodeBuilder()), + outStream(&std::cout), + mainFile(nullptr) { + visitDagOnce = false; + setName("ToP4"); + } + + using Inspector::preorder; + + void setnoIncludesArg(bool condition) { noIncludes = condition; } + + void setListTerm(const char *start, const char *end) { + listTerminators.push_back(ListPrint(start, end)); + } + Visitor::profile_t init_apply(const IR::Node *node) override; + void end_apply(const IR::Node *node) override; + + bool process(const IR::Type_StructLike *t, const char *name); + // types + bool preorder(const IR::Type_Boolean *t) override; + bool preorder(const IR::Type_Varbits *t) override; + bool preorder(const IR::Type_Bits *t) override; + bool preorder(const IR::Type_InfInt *t) override; + bool preorder(const IR::Type_String *t) override; + bool preorder(const IR::Type_Var *t) override; + bool preorder(const IR::Type_Dontcare *t) override; + bool preorder(const IR::Type_Void *t) override; + bool preorder(const IR::Type_Error *t) override; + bool preorder(const IR::Type_Struct *t) override { return process(t, "struct"); } + bool preorder(const IR::Type_Header *t) override { return process(t, "header"); } + bool preorder(const IR::Type_HeaderUnion *t) override { return process(t, "header_union"); } + bool preorder(const IR::Type_Package *t) override; + bool preorder(const IR::Type_Parser *t) override; + bool preorder(const IR::Type_Control *t) override; + bool preorder(const IR::Type_Name *t) override; + bool preorder(const IR::Type_Stack *t) override; + bool preorder(const IR::Type_Specialized *t) override; + bool preorder(const IR::Type_Enum *t) override; + bool preorder(const IR::Type_SerEnum *t) override; + bool preorder(const IR::Type_Typedef *t) override; + bool preorder(const IR::Type_Newtype *t) override; + bool preorder(const IR::Type_Extern *t) override; + bool preorder(const IR::Type_Unknown *t) override; + bool preorder(const IR::Type_BaseList *t) override; + bool preorder(const IR::Type *t) override { + builder.append(t->toString()); + return false; + } + bool preorder(const IR::Type_SpecializedCanonical *t) override { + BUG("%1%: specialized canonical type in IR tree", t); + return false; + } + + // declarations + bool preorder(const IR::Declaration_Constant *cst) override; + bool preorder(const IR::Declaration_Variable *v) override; + bool preorder(const IR::Declaration_Instance *t) override; + bool preorder(const IR::Declaration_MatchKind *d) override; + + // expressions + bool preorder(const IR::Dots *e) override; + bool preorder(const IR::NamedDots *e) override; + bool preorder(const IR::Constant *c) override; + bool preorder(const IR::Slice *slice) override; + bool preorder(const IR::BoolLiteral *b) override; + bool preorder(const IR::StringLiteral *s) override; + bool preorder(const IR::PathExpression *p) override; + bool preorder(const IR::Cast *c) override; + bool preorder(const IR::Operation_Binary *b) override; + bool preorder(const IR::Operation_Unary *u) override; + bool preorder(const IR::ArrayIndex *a) override; + bool preorder(const IR::TypeNameExpression *e) override; + bool preorder(const IR::Mux *a) override; + bool preorder(const IR::ConstructorCallExpression *e) override; + bool preorder(const IR::Member *e) override; + bool preorder(const IR::SelectCase *e) override; + bool preorder(const IR::SelectExpression *e) override; + bool preorder(const IR::ListExpression *e) override; + bool preorder(const IR::P4ListExpression *e) override; + bool preorder(const IR::StructExpression *e) override; + bool preorder(const IR::Invalid *e) override; + bool preorder(const IR::InvalidHeader *e) override; + bool preorder(const IR::InvalidHeaderUnion *e) override; + bool preorder(const IR::HeaderStackExpression *e) override; + bool preorder(const IR::MethodCallExpression *e) override; + bool preorder(const IR::DefaultExpression *e) override; + bool preorder(const IR::This *e) override; + + // vectors + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::Vector *v) override; + bool preorder(const IR::IndexedVector *v) override; + bool preorder(const IR::IndexedVector *v) override; + bool preorder(const IR::IndexedVector *v) override; + bool preorder(const IR::IndexedVector *v) override; + bool preorder(const IR::IndexedVector *v) override; + + // statements + bool preorder(const IR::AssignmentStatement *s) override; + bool preorder(const IR::BlockStatement *s) override; + bool preorder(const IR::MethodCallStatement *s) override; + bool preorder(const IR::EmptyStatement *s) override; + bool preorder(const IR::ReturnStatement *s) override; + bool preorder(const IR::BreakStatement *s) override; + bool preorder(const IR::ContinueStatement *s) override; + bool preorder(const IR::ExitStatement *s) override; + bool preorder(const IR::SwitchCase *s) override; + bool preorder(const IR::SwitchStatement *s) override; + bool preorder(const IR::IfStatement *s) override; + bool preorder(const IR::ForStatement *s) override; + bool preorder(const IR::ForInStatement *s) override; + + // misc + bool preorder(const IR::NamedExpression *ne) override; + bool preorder(const IR::Argument *arg) override; + bool preorder(const IR::Path *p) override; + bool preorder(const IR::Parameter *p) override; + bool preorder(const IR::Annotations *a) override; + bool preorder(const IR::Annotation *a) override; + bool preorder(const IR::P4Program *program) override; + bool preorder(const IR::P4Control *c) override; + bool preorder(const IR::P4Action *c) override; + bool preorder(const IR::ParserState *s) override; + bool preorder(const IR::P4Parser *c) override; + bool preorder(const IR::TypeParameters *p) override; + bool preorder(const IR::ParameterList *p) override; + bool preorder(const IR::Method *p) override; + bool preorder(const IR::Function *function) override; + + bool preorder(const IR::ExpressionValue *v) override; + bool preorder(const IR::ActionListElement *ale) override; + bool preorder(const IR::ActionList *v) override; + bool preorder(const IR::Key *v) override; + bool preorder(const IR::Property *p) override; + bool preorder(const IR::TableProperties *t) override; + bool preorder(const IR::EntriesList *l) override; + bool preorder(const IR::Entry *e) override; + bool preorder(const IR::P4Table *c) override; + bool preorder(const IR::P4ValueSet *c) override; + + // in case it is accidentally called on a V1Program + bool preorder(const IR::V1Program *) override { return false; } +}; + +std::string toP4(const IR::INode *node); +void dumpP4(const IR::INode *node); + +} // namespace P4 + +} // namespace P4Fmt +#endif /* P4FMT_TOP4_TOP4_H_ */ From 46e12754b0d20490a30fc12fe483baade36a4d31 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 14:36:27 +0530 Subject: [PATCH 02/16] remove nested namespace from 'p4fmt' Signed-off-by: Nitish --- backends/p4fmt/p4fmt.cpp | 2 +- backends/p4fmt/toP4/toP4.cpp | 4 +--- backends/p4fmt/toP4/toP4.h | 4 ---- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/backends/p4fmt/p4fmt.cpp b/backends/p4fmt/p4fmt.cpp index df5de3c2d3d..e39297ab13b 100644 --- a/backends/p4fmt/p4fmt.cpp +++ b/backends/p4fmt/p4fmt.cpp @@ -24,7 +24,7 @@ std::stringstream getFormattedOutput(std::filesystem::path inputFile) { return formattedOutput; } - auto top4 = P4Fmt::P4::ToP4(&formattedOutput, false); + auto top4 = P4Fmt::ToP4(&formattedOutput, false); // Print the program before running front end passes. program->apply(top4); diff --git a/backends/p4fmt/toP4/toP4.cpp b/backends/p4fmt/toP4/toP4.cpp index 03ca2c158b4..c7b55b5c4e1 100644 --- a/backends/p4fmt/toP4/toP4.cpp +++ b/backends/p4fmt/toP4/toP4.cpp @@ -10,7 +10,6 @@ #include "ir/dump.h" namespace P4Fmt { -namespace P4 { Visitor::profile_t ToP4::init_apply(const IR::Node *node) { LOG4("Program dump:" << std::endl << dumpToString(node)); @@ -1644,7 +1643,7 @@ bool ToP4::preorder(const IR::Path *p) { std::string toP4(const IR::INode *node) { std::stringstream stream; - P4::ToP4 toP4(&stream, false); + P4Fmt::ToP4 toP4(&stream, false); node->getNode()->apply(toP4); return stream.str(); } @@ -1654,5 +1653,4 @@ void dumpP4(const IR::INode *node) { std::cout << s; } -} // namespace P4 } // namespace P4Fmt diff --git a/backends/p4fmt/toP4/toP4.h b/backends/p4fmt/toP4/toP4.h index e137ba14ef2..b891127cebb 100644 --- a/backends/p4fmt/toP4/toP4.h +++ b/backends/p4fmt/toP4/toP4.h @@ -7,8 +7,6 @@ #include "lib/sourceCodeBuilder.h" namespace P4Fmt { -namespace P4 { - /** This pass converts a P4-16 IR into a P4 source (text) program. It can optionally emit as comments a representation of the program IR. @@ -260,7 +258,5 @@ class ToP4 : public Inspector, ::P4::ResolutionContext { std::string toP4(const IR::INode *node); void dumpP4(const IR::INode *node); -} // namespace P4 - } // namespace P4Fmt #endif /* P4FMT_TOP4_TOP4_H_ */ From 55abd598a0190f88a2a907c341d0c70a80255438 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 15:50:47 +0530 Subject: [PATCH 03/16] rename 'toP4' to 'P4Formatter' Signed-off-by: Nitish --- backends/p4fmt/CMakeLists.txt | 4 +- backends/p4fmt/p4fmt.cpp | 4 +- .../toP4.cpp => p4formatter/p4formatter.cpp} | 206 +++++++++--------- .../toP4.h => p4formatter/p4formatter.h} | 14 +- 4 files changed, 114 insertions(+), 114 deletions(-) rename backends/p4fmt/{toP4/toP4.cpp => p4formatter/p4formatter.cpp} (87%) rename backends/p4fmt/{toP4/toP4.h => p4formatter/p4formatter.h} (96%) diff --git a/backends/p4fmt/CMakeLists.txt b/backends/p4fmt/CMakeLists.txt index ebc8869c6d6..002fccb93da 100644 --- a/backends/p4fmt/CMakeLists.txt +++ b/backends/p4fmt/CMakeLists.txt @@ -2,14 +2,14 @@ set(FMT_SRCS p4fmt.cpp options.cpp main.cpp - toP4/toP4.cpp + p4formatter/p4formatter.cpp ) set(REFCHECK_SRCS refcheck.cpp options.cpp p4fmt.cpp - toP4/toP4.cpp + p4formatter/p4formatter.cpp ) # p4fmt diff --git a/backends/p4fmt/p4fmt.cpp b/backends/p4fmt/p4fmt.cpp index e39297ab13b..6a01745f42a 100644 --- a/backends/p4fmt/p4fmt.cpp +++ b/backends/p4fmt/p4fmt.cpp @@ -6,7 +6,7 @@ #include "lib/compile_context.h" #include "lib/error.h" #include "options.h" -#include "toP4/toP4.h" +#include "p4formatter/p4formatter.h" namespace P4::P4Fmt { @@ -24,7 +24,7 @@ std::stringstream getFormattedOutput(std::filesystem::path inputFile) { return formattedOutput; } - auto top4 = P4Fmt::ToP4(&formattedOutput, false); + auto top4 = P4Fmt::P4Formatter(&formattedOutput, false); // Print the program before running front end passes. program->apply(top4); diff --git a/backends/p4fmt/toP4/toP4.cpp b/backends/p4fmt/p4formatter/p4formatter.cpp similarity index 87% rename from backends/p4fmt/toP4/toP4.cpp rename to backends/p4fmt/p4formatter/p4formatter.cpp index c7b55b5c4e1..fa057e5e59a 100644 --- a/backends/p4fmt/toP4/toP4.cpp +++ b/backends/p4fmt/p4formatter/p4formatter.cpp @@ -1,4 +1,4 @@ -#include "toP4.h" +#include "p4formatter.h" #include #include @@ -11,14 +11,14 @@ namespace P4Fmt { -Visitor::profile_t ToP4::init_apply(const IR::Node *node) { +Visitor::profile_t P4Formatter::init_apply(const IR::Node *node) { LOG4("Program dump:" << std::endl << dumpToString(node)); listTerminators_init_apply_size = listTerminators.size(); vectorSeparator_init_apply_size = vectorSeparator.size(); return Inspector::init_apply(node); } -void ToP4::end_apply(const IR::Node *) { +void P4Formatter::end_apply(const IR::Node *) { if (outStream != nullptr) { cstring result = builder.toString(); *outStream << result.c_str(); @@ -31,13 +31,13 @@ void ToP4::end_apply(const IR::Node *) { } // Try to guess whether a file is a "system" file -bool ToP4::isSystemFile(cstring file) { +bool P4Formatter::isSystemFile(cstring file) { if (noIncludes) return false; if (file.startsWith(p4includePath)) return true; return false; } -cstring ToP4::ifSystemFile(const IR::Node *node) { +cstring P4Formatter::ifSystemFile(const IR::Node *node) { if (!node->srcInfo.isValid()) return nullptr; auto sourceFile = node->srcInfo.getSourceFile(); if (isSystemFile(sourceFile)) return sourceFile; @@ -105,7 +105,7 @@ class DumpIR : public Inspector { }; } // namespace -unsigned ToP4::curDepth() const { +unsigned P4Formatter::curDepth() const { unsigned result = 0; auto ctx = getContext(); while (ctx != nullptr) { @@ -115,7 +115,7 @@ unsigned ToP4::curDepth() const { return result; } -void ToP4::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) { +void P4Formatter::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) { if (!showIR) return; if (node == nullptr) node = getOriginal(); @@ -130,7 +130,7 @@ void ToP4::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) { builder.emitIndent(); } -bool ToP4::preorder(const IR::P4Program *program) { +bool P4Formatter::preorder(const IR::P4Program *program) { std::set includesEmitted; bool first = true; @@ -182,7 +182,7 @@ bool ToP4::preorder(const IR::P4Program *program) { return false; } -bool ToP4::preorder(const IR::Type_Bits *t) { +bool P4Formatter::preorder(const IR::Type_Bits *t) { if (t->expression) { builder.append("bit<("); visit(t->expression); @@ -193,43 +193,43 @@ bool ToP4::preorder(const IR::Type_Bits *t) { return false; } -bool ToP4::preorder(const IR::Type_String *t) { +bool P4Formatter::preorder(const IR::Type_String *t) { builder.append(t->toString()); return false; } -bool ToP4::preorder(const IR::Type_InfInt *t) { +bool P4Formatter::preorder(const IR::Type_InfInt *t) { builder.append(t->toString()); return false; } -bool ToP4::preorder(const IR::Type_Var *t) { +bool P4Formatter::preorder(const IR::Type_Var *t) { builder.append(t->name); return false; } -bool ToP4::preorder(const IR::Type_Unknown *) { +bool P4Formatter::preorder(const IR::Type_Unknown *) { BUG("Cannot emit code for an unknown type"); // builder.append("*unknown type*"); return false; } -bool ToP4::preorder(const IR::Type_Dontcare *) { +bool P4Formatter::preorder(const IR::Type_Dontcare *) { builder.append("_"); return false; } -bool ToP4::preorder(const IR::Type_Void *) { +bool P4Formatter::preorder(const IR::Type_Void *) { builder.append("void"); return false; } -bool ToP4::preorder(const IR::Type_Name *t) { +bool P4Formatter::preorder(const IR::Type_Name *t) { visit(t->path); return false; } -bool ToP4::preorder(const IR::Type_Stack *t) { +bool P4Formatter::preorder(const IR::Type_Stack *t) { dump(2); visit(t->elementType); builder.append("["); @@ -238,7 +238,7 @@ bool ToP4::preorder(const IR::Type_Stack *t) { return false; } -bool ToP4::preorder(const IR::Type_Specialized *t) { +bool P4Formatter::preorder(const IR::Type_Specialized *t) { dump(3); visit(t->baseType); builder.append("<"); @@ -249,7 +249,7 @@ bool ToP4::preorder(const IR::Type_Specialized *t) { return false; } -bool ToP4::preorder(const IR::Argument *arg) { +bool P4Formatter::preorder(const IR::Argument *arg) { dump(2); if (!arg->name.name.isNullOrEmpty()) { builder.append(arg->name.name); @@ -259,7 +259,7 @@ bool ToP4::preorder(const IR::Argument *arg) { return false; } -bool ToP4::preorder(const IR::Type_Typedef *t) { +bool P4Formatter::preorder(const IR::Type_Typedef *t) { dump(2); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -273,7 +273,7 @@ bool ToP4::preorder(const IR::Type_Typedef *t) { return false; } -bool ToP4::preorder(const IR::Type_Newtype *t) { +bool P4Formatter::preorder(const IR::Type_Newtype *t) { dump(2); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -287,7 +287,7 @@ bool ToP4::preorder(const IR::Type_Newtype *t) { return false; } -bool ToP4::preorder(const IR::Type_BaseList *t) { +bool P4Formatter::preorder(const IR::Type_BaseList *t) { dump(3); builder.append("tuple<"); bool first = true; @@ -302,7 +302,7 @@ bool ToP4::preorder(const IR::Type_BaseList *t) { return false; } -bool ToP4::preorder(const IR::P4ValueSet *t) { +bool P4Formatter::preorder(const IR::P4ValueSet *t) { dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -322,7 +322,7 @@ bool ToP4::preorder(const IR::P4ValueSet *t) { return false; } -bool ToP4::preorder(const IR::Type_Enum *t) { +bool P4Formatter::preorder(const IR::Type_Enum *t) { dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -345,7 +345,7 @@ bool ToP4::preorder(const IR::Type_Enum *t) { return false; } -bool ToP4::preorder(const IR::Type_SerEnum *t) { +bool P4Formatter::preorder(const IR::Type_SerEnum *t) { dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -372,7 +372,7 @@ bool ToP4::preorder(const IR::Type_SerEnum *t) { return false; } -bool ToP4::preorder(const IR::TypeParameters *t) { +bool P4Formatter::preorder(const IR::TypeParameters *t) { if (!t->empty()) { builder.append("<"); bool first = true; @@ -389,7 +389,7 @@ bool ToP4::preorder(const IR::TypeParameters *t) { return false; } -bool ToP4::preorder(const IR::Method *m) { +bool P4Formatter::preorder(const IR::Method *m) { dump(1); if (!m->annotations->annotations.empty()) { visit(m->annotations); @@ -414,7 +414,7 @@ bool ToP4::preorder(const IR::Method *m) { return false; } -bool ToP4::preorder(const IR::Function *function) { +bool P4Formatter::preorder(const IR::Function *function) { dump(1); if (!function->annotations->annotations.empty()) { visit(function->annotations); @@ -434,7 +434,7 @@ bool ToP4::preorder(const IR::Function *function) { return false; } -bool ToP4::preorder(const IR::Type_Extern *t) { +bool P4Formatter::preorder(const IR::Type_Extern *t) { dump(2); if (isDeclaration) { if (!t->annotations->annotations.empty()) { @@ -465,12 +465,12 @@ bool ToP4::preorder(const IR::Type_Extern *t) { return false; } -bool ToP4::preorder(const IR::Type_Boolean *) { +bool P4Formatter::preorder(const IR::Type_Boolean *) { builder.append("bool"); return false; } -bool ToP4::preorder(const IR::Type_Varbits *t) { +bool P4Formatter::preorder(const IR::Type_Varbits *t) { if (t->expression) { builder.append("varbit<("); visit(t->expression); @@ -481,7 +481,7 @@ bool ToP4::preorder(const IR::Type_Varbits *t) { return false; } -bool ToP4::preorder(const IR::Type_Package *package) { +bool P4Formatter::preorder(const IR::Type_Package *package) { dump(2); builder.emitIndent(); if (!package->annotations->annotations.empty()) { @@ -496,7 +496,7 @@ bool ToP4::preorder(const IR::Type_Package *package) { return false; } -bool ToP4::process(const IR::Type_StructLike *t, const char *name) { +bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { dump(2); if (isDeclaration) { builder.emitIndent(); @@ -516,7 +516,7 @@ bool ToP4::process(const IR::Type_StructLike *t, const char *name) { size_t len = 0; for (auto f : t->fields) { Util::SourceCodeBuilder builder; - ToP4 rec(builder, showIR); + P4Formatter rec(builder, showIR); f->type->apply(rec); cstring t = builder.toString(); @@ -546,7 +546,7 @@ bool ToP4::process(const IR::Type_StructLike *t, const char *name) { return false; } -bool ToP4::preorder(const IR::Type_Parser *t) { +bool P4Formatter::preorder(const IR::Type_Parser *t) { dump(2); builder.emitIndent(); if (!t->annotations->annotations.empty()) { @@ -561,7 +561,7 @@ bool ToP4::preorder(const IR::Type_Parser *t) { return false; } -bool ToP4::preorder(const IR::Type_Control *t) { +bool P4Formatter::preorder(const IR::Type_Control *t) { dump(2); builder.emitIndent(); if (!t->annotations->annotations.empty()) { @@ -578,7 +578,7 @@ bool ToP4::preorder(const IR::Type_Control *t) { /////////////////////// -bool ToP4::preorder(const IR::Constant *c) { +bool P4Formatter::preorder(const IR::Constant *c) { const IR::Type_Bits *tb = c->type->to(); unsigned width; bool sign; @@ -594,17 +594,17 @@ bool ToP4::preorder(const IR::Constant *c) { return false; } -bool ToP4::preorder(const IR::BoolLiteral *b) { +bool P4Formatter::preorder(const IR::BoolLiteral *b) { builder.append(b->toString()); return false; } -bool ToP4::preorder(const IR::StringLiteral *s) { +bool P4Formatter::preorder(const IR::StringLiteral *s) { builder.append(s->toString()); return false; } -bool ToP4::preorder(const IR::Declaration_Constant *cst) { +bool P4Formatter::preorder(const IR::Declaration_Constant *cst) { dump(2); if (!cst->annotations->annotations.empty()) { visit(cst->annotations); @@ -626,7 +626,7 @@ bool ToP4::preorder(const IR::Declaration_Constant *cst) { return false; } -bool ToP4::preorder(const IR::Declaration_Instance *i) { +bool P4Formatter::preorder(const IR::Declaration_Instance *i) { dump(3); if (!i->annotations->annotations.empty()) { visit(i->annotations); @@ -650,7 +650,7 @@ bool ToP4::preorder(const IR::Declaration_Instance *i) { return false; } -bool ToP4::preorder(const IR::Declaration_Variable *v) { +bool P4Formatter::preorder(const IR::Declaration_Variable *v) { dump(2); if (!v->annotations->annotations.empty()) { visit(v->annotations); @@ -671,7 +671,7 @@ bool ToP4::preorder(const IR::Declaration_Variable *v) { return false; } -bool ToP4::preorder(const IR::Type_Error *d) { +bool P4Formatter::preorder(const IR::Type_Error *d) { dump(1); bool first = true; for (auto a : *d->getDeclarations()) { @@ -696,7 +696,7 @@ bool ToP4::preorder(const IR::Type_Error *d) { return false; } -bool ToP4::preorder(const IR::Declaration_MatchKind *d) { +bool P4Formatter::preorder(const IR::Declaration_MatchKind *d) { dump(1); builder.append("match_kind "); builder.blockStart(); @@ -716,7 +716,7 @@ bool ToP4::preorder(const IR::Declaration_MatchKind *d) { /////////////////////////////////////////////////// #define VECTOR_VISIT(V, T) \ - bool ToP4::preorder(const IR::V *v) { \ + bool P4Formatter::preorder(const IR::V *v) { \ if (v == nullptr) return false; \ bool first = true; \ VecPrint sep = getSep(); \ @@ -757,7 +757,7 @@ VECTOR_VISIT(IndexedVector, StatOrDecl) /////////////////////////////////////////// -bool ToP4::preorder(const IR::Slice *slice) { +bool P4Formatter::preorder(const IR::Slice *slice) { int prec = expressionPrecedence; bool useParens = prec > slice->getPrecedence(); if (useParens) builder.append("("); @@ -777,7 +777,7 @@ bool ToP4::preorder(const IR::Slice *slice) { return false; } -bool ToP4::preorder(const IR::DefaultExpression *) { +bool P4Formatter::preorder(const IR::DefaultExpression *) { // Within a method call this is rendered as a don't care if (withinArgument) builder.append("_"); @@ -786,22 +786,22 @@ bool ToP4::preorder(const IR::DefaultExpression *) { return false; } -bool ToP4::preorder(const IR::This *) { +bool P4Formatter::preorder(const IR::This *) { builder.append("this"); return false; } -bool ToP4::preorder(const IR::PathExpression *p) { +bool P4Formatter::preorder(const IR::PathExpression *p) { visit(p->path); return false; } -bool ToP4::preorder(const IR::TypeNameExpression *e) { +bool P4Formatter::preorder(const IR::TypeNameExpression *e) { visit(e->typeName); return false; } -bool ToP4::preorder(const IR::ConstructorCallExpression *e) { +bool P4Formatter::preorder(const IR::ConstructorCallExpression *e) { visit(e->constructedType); builder.append("("); setVecSep(", "); @@ -814,7 +814,7 @@ bool ToP4::preorder(const IR::ConstructorCallExpression *e) { return false; } -bool ToP4::preorder(const IR::Member *e) { +bool P4Formatter::preorder(const IR::Member *e) { int prec = expressionPrecedence; expressionPrecedence = e->getPrecedence(); visit(e->expr); @@ -824,7 +824,7 @@ bool ToP4::preorder(const IR::Member *e) { return false; } -bool ToP4::preorder(const IR::SelectCase *e) { +bool P4Formatter::preorder(const IR::SelectCase *e) { dump(2); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; @@ -837,7 +837,7 @@ bool ToP4::preorder(const IR::SelectCase *e) { return false; } -bool ToP4::preorder(const IR::SelectExpression *e) { +bool P4Formatter::preorder(const IR::SelectExpression *e) { builder.append("select("); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; @@ -855,7 +855,7 @@ bool ToP4::preorder(const IR::SelectExpression *e) { return false; } -bool ToP4::preorder(const IR::ListExpression *e) { +bool P4Formatter::preorder(const IR::ListExpression *e) { using ::P4::literals::operator""_cs; cstring start, end; if (listTerminators.empty()) { @@ -878,7 +878,7 @@ bool ToP4::preorder(const IR::ListExpression *e) { return false; } -bool ToP4::preorder(const IR::P4ListExpression *e) { +bool P4Formatter::preorder(const IR::P4ListExpression *e) { if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); if (e->elementType != nullptr) { builder.append("(list<"); @@ -900,14 +900,14 @@ bool ToP4::preorder(const IR::P4ListExpression *e) { return false; } -bool ToP4::preorder(const IR::NamedExpression *e) { +bool P4Formatter::preorder(const IR::NamedExpression *e) { builder.append(e->name.name); builder.append(" = "); visit(e->expression); return false; } -bool ToP4::preorder(const IR::StructExpression *e) { +bool P4Formatter::preorder(const IR::StructExpression *e) { if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); if (e->structType != nullptr) { builder.append("("); @@ -929,7 +929,7 @@ bool ToP4::preorder(const IR::StructExpression *e) { return false; } -bool ToP4::preorder(const IR::HeaderStackExpression *e) { +bool P4Formatter::preorder(const IR::HeaderStackExpression *e) { if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); if (e->headerStackType != nullptr) { builder.append("("); @@ -951,22 +951,22 @@ bool ToP4::preorder(const IR::HeaderStackExpression *e) { return false; } -bool ToP4::preorder(const IR::Invalid *) { +bool P4Formatter::preorder(const IR::Invalid *) { builder.append("{#}"); return false; } -bool ToP4::preorder(const IR::Dots *) { +bool P4Formatter::preorder(const IR::Dots *) { builder.append("..."); return false; } -bool ToP4::preorder(const IR::NamedDots *) { +bool P4Formatter::preorder(const IR::NamedDots *) { builder.append("..."); return false; } -bool ToP4::preorder(const IR::InvalidHeader *e) { +bool P4Formatter::preorder(const IR::InvalidHeader *e) { if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); builder.append("("); visit(e->headerType); @@ -976,7 +976,7 @@ bool ToP4::preorder(const IR::InvalidHeader *e) { return false; } -bool ToP4::preorder(const IR::InvalidHeaderUnion *e) { +bool P4Formatter::preorder(const IR::InvalidHeaderUnion *e) { if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append("("); builder.append("("); visit(e->headerUnionType); @@ -986,7 +986,7 @@ bool ToP4::preorder(const IR::InvalidHeaderUnion *e) { return false; } -bool ToP4::preorder(const IR::MethodCallExpression *e) { +bool P4Formatter::preorder(const IR::MethodCallExpression *e) { int prec = expressionPrecedence; bool useParens = (prec > DBPrint::Prec_Postfix) || (!e->typeArguments->empty() && prec >= DBPrint::Prec_Cond); @@ -1019,7 +1019,7 @@ bool ToP4::preorder(const IR::MethodCallExpression *e) { return false; } -bool ToP4::preorder(const IR::Operation_Binary *b) { +bool P4Formatter::preorder(const IR::Operation_Binary *b) { int prec = expressionPrecedence; bool useParens = prec > b->getPrecedence(); if (useParens) builder.append("("); @@ -1035,7 +1035,7 @@ bool ToP4::preorder(const IR::Operation_Binary *b) { return false; } -bool ToP4::preorder(const IR::Mux *b) { +bool P4Formatter::preorder(const IR::Mux *b) { int prec = expressionPrecedence; bool useParens = prec >= b->getPrecedence(); if (useParens) builder.append("("); @@ -1052,7 +1052,7 @@ bool ToP4::preorder(const IR::Mux *b) { return false; } -bool ToP4::preorder(const IR::Operation_Unary *u) { +bool P4Formatter::preorder(const IR::Operation_Unary *u) { int prec = expressionPrecedence; bool useParens = prec > u->getPrecedence(); if (useParens) builder.append("("); @@ -1064,7 +1064,7 @@ bool ToP4::preorder(const IR::Operation_Unary *u) { return false; } -bool ToP4::preorder(const IR::ArrayIndex *a) { +bool P4Formatter::preorder(const IR::ArrayIndex *a) { int prec = expressionPrecedence; bool useParens = prec > a->getPrecedence(); if (useParens) builder.append("("); @@ -1079,7 +1079,7 @@ bool ToP4::preorder(const IR::ArrayIndex *a) { return false; } -bool ToP4::preorder(const IR::Cast *c) { +bool P4Formatter::preorder(const IR::Cast *c) { int prec = expressionPrecedence; bool useParens = prec > c->getPrecedence(); if (useParens) builder.append("("); @@ -1095,7 +1095,7 @@ bool ToP4::preorder(const IR::Cast *c) { ////////////////////////////////////////////////////////// -bool ToP4::preorder(const IR::AssignmentStatement *a) { +bool P4Formatter::preorder(const IR::AssignmentStatement *a) { dump(2); visit(a->left); builder.append(" = "); @@ -1104,7 +1104,7 @@ bool ToP4::preorder(const IR::AssignmentStatement *a) { return false; } -bool ToP4::preorder(const IR::BlockStatement *s) { +bool P4Formatter::preorder(const IR::BlockStatement *s) { dump(1); if (!s->annotations->annotations.empty()) { visit(s->annotations); @@ -1118,28 +1118,28 @@ bool ToP4::preorder(const IR::BlockStatement *s) { return false; } -bool ToP4::preorder(const IR::BreakStatement *) { +bool P4Formatter::preorder(const IR::BreakStatement *) { dump(1); builder.append("break"); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::ContinueStatement *) { +bool P4Formatter::preorder(const IR::ContinueStatement *) { dump(1); builder.append("continue"); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::ExitStatement *) { +bool P4Formatter::preorder(const IR::ExitStatement *) { dump(1); builder.append("exit"); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::ReturnStatement *statement) { +bool P4Formatter::preorder(const IR::ReturnStatement *statement) { dump(2); builder.append("return"); if (statement->expression != nullptr) { @@ -1150,13 +1150,13 @@ bool ToP4::preorder(const IR::ReturnStatement *statement) { return false; } -bool ToP4::preorder(const IR::EmptyStatement *) { +bool P4Formatter::preorder(const IR::EmptyStatement *) { dump(1); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::IfStatement *s) { +bool P4Formatter::preorder(const IR::IfStatement *s) { dump(2); builder.append("if ("); visit(s->condition); @@ -1193,7 +1193,7 @@ bool ToP4::preorder(const IR::IfStatement *s) { return false; } -bool ToP4::preorder(const IR::ForStatement *s) { +bool P4Formatter::preorder(const IR::ForStatement *s) { dump(2); if (!s->annotations->annotations.empty()) { visit(s->annotations); @@ -1235,7 +1235,7 @@ bool ToP4::preorder(const IR::ForStatement *s) { return false; } -bool ToP4::preorder(const IR::ForInStatement *s) { +bool P4Formatter::preorder(const IR::ForInStatement *s) { dump(2); if (!s->annotations->annotations.empty()) { visit(s->annotations); @@ -1273,21 +1273,21 @@ bool ToP4::preorder(const IR::ForInStatement *s) { return false; } -bool ToP4::preorder(const IR::MethodCallStatement *s) { +bool P4Formatter::preorder(const IR::MethodCallStatement *s) { dump(3); visit(s->methodCall); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::SwitchCase *s) { +bool P4Formatter::preorder(const IR::SwitchCase *s) { visit(s->label); builder.append(": "); visit(s->statement); return false; } -bool ToP4::preorder(const IR::SwitchStatement *s) { +bool P4Formatter::preorder(const IR::SwitchStatement *s) { dump(4); builder.append("switch ("); visit(s->expression); @@ -1302,7 +1302,7 @@ bool ToP4::preorder(const IR::SwitchStatement *s) { //////////////////////////////////// -bool ToP4::preorder(const IR::Annotations *a) { +bool P4Formatter::preorder(const IR::Annotations *a) { bool first = true; for (const auto *anno : a->annotations) { if (!first) { @@ -1315,7 +1315,7 @@ bool ToP4::preorder(const IR::Annotations *a) { return false; } -bool ToP4::preorder(const IR::Annotation *a) { +bool P4Formatter::preorder(const IR::Annotation *a) { builder.append("@"); builder.append(a->name); const char *open = a->structured ? "[" : "("; @@ -1363,7 +1363,7 @@ bool ToP4::preorder(const IR::Annotation *a) { return false; } -bool ToP4::preorder(const IR::Parameter *p) { +bool P4Formatter::preorder(const IR::Parameter *p) { dump(2); if (!p->annotations->annotations.empty()) { visit(p->annotations); @@ -1397,7 +1397,7 @@ bool ToP4::preorder(const IR::Parameter *p) { return false; } -bool ToP4::preorder(const IR::P4Control *c) { +bool P4Formatter::preorder(const IR::P4Control *c) { dump(1); bool decl = isDeclaration; isDeclaration = false; @@ -1420,7 +1420,7 @@ bool ToP4::preorder(const IR::P4Control *c) { return false; } -bool ToP4::preorder(const IR::ParameterList *p) { +bool P4Formatter::preorder(const IR::ParameterList *p) { builder.append("("); bool first = true; for (auto param : *p->getEnumerator()) { @@ -1432,7 +1432,7 @@ bool ToP4::preorder(const IR::ParameterList *p) { return false; } -bool ToP4::preorder(const IR::P4Action *c) { +bool P4Formatter::preorder(const IR::P4Action *c) { dump(2); if (!c->annotations->annotations.empty()) { visit(c->annotations); @@ -1446,7 +1446,7 @@ bool ToP4::preorder(const IR::P4Action *c) { return false; } -bool ToP4::preorder(const IR::ParserState *s) { +bool P4Formatter::preorder(const IR::ParserState *s) { dump(1); if (s->isBuiltin()) return false; @@ -1476,7 +1476,7 @@ bool ToP4::preorder(const IR::ParserState *s) { return false; } -bool ToP4::preorder(const IR::P4Parser *c) { +bool P4Formatter::preorder(const IR::P4Parser *c) { dump(1); bool decl = isDeclaration; isDeclaration = false; @@ -1499,14 +1499,14 @@ bool ToP4::preorder(const IR::P4Parser *c) { return false; } -bool ToP4::preorder(const IR::ExpressionValue *v) { +bool P4Formatter::preorder(const IR::ExpressionValue *v) { dump(2); visit(v->expression); builder.endOfStatement(); return false; } -bool ToP4::preorder(const IR::ActionListElement *ale) { +bool P4Formatter::preorder(const IR::ActionListElement *ale) { dump(3); if (!ale->annotations->annotations.empty()) { visit(ale->annotations); @@ -1516,7 +1516,7 @@ bool ToP4::preorder(const IR::ActionListElement *ale) { return false; } -bool ToP4::preorder(const IR::ActionList *v) { +bool P4Formatter::preorder(const IR::ActionList *v) { dump(2); builder.blockStart(); setVecSep(";\n", ";\n"); @@ -1526,7 +1526,7 @@ bool ToP4::preorder(const IR::ActionList *v) { return false; } -bool ToP4::preorder(const IR::Key *v) { +bool P4Formatter::preorder(const IR::Key *v) { dump(2); builder.blockStart(); @@ -1534,7 +1534,7 @@ bool ToP4::preorder(const IR::Key *v) { size_t len = 0; for (auto f : v->keyElements) { Util::SourceCodeBuilder builder; - ToP4 rec(builder, showIR); + P4Formatter rec(builder, showIR); f->expression->apply(rec); cstring s = builder.toString(); @@ -1561,7 +1561,7 @@ bool ToP4::preorder(const IR::Key *v) { return false; } -bool ToP4::preorder(const IR::Property *p) { +bool P4Formatter::preorder(const IR::Property *p) { dump(1); if (!p->annotations->annotations.empty()) { visit(p->annotations); @@ -1574,7 +1574,7 @@ bool ToP4::preorder(const IR::Property *p) { return false; } -bool ToP4::preorder(const IR::TableProperties *t) { +bool P4Formatter::preorder(const IR::TableProperties *t) { for (auto p : t->properties) { builder.emitIndent(); visit(p); @@ -1583,7 +1583,7 @@ bool ToP4::preorder(const IR::TableProperties *t) { return false; } -bool ToP4::preorder(const IR::EntriesList *l) { +bool P4Formatter::preorder(const IR::EntriesList *l) { dump(1); builder.append("{"); builder.newline(); @@ -1595,7 +1595,7 @@ bool ToP4::preorder(const IR::EntriesList *l) { return false; } -bool ToP4::preorder(const IR::Entry *e) { +bool P4Formatter::preorder(const IR::Entry *e) { dump(2); builder.emitIndent(); if (e->isConst) builder.append("const "); @@ -1619,7 +1619,7 @@ bool ToP4::preorder(const IR::Entry *e) { return false; } -bool ToP4::preorder(const IR::P4Table *c) { +bool P4Formatter::preorder(const IR::P4Table *c) { dump(2); if (!c->annotations->annotations.empty()) { visit(c->annotations); @@ -1636,14 +1636,14 @@ bool ToP4::preorder(const IR::P4Table *c) { return false; } -bool ToP4::preorder(const IR::Path *p) { +bool P4Formatter::preorder(const IR::Path *p) { builder.append(p->asString()); return false; } std::string toP4(const IR::INode *node) { std::stringstream stream; - P4Fmt::ToP4 toP4(&stream, false); + P4Fmt::P4Formatter toP4(&stream, false); node->getNode()->apply(toP4); return stream.str(); } diff --git a/backends/p4fmt/toP4/toP4.h b/backends/p4fmt/p4formatter/p4formatter.h similarity index 96% rename from backends/p4fmt/toP4/toP4.h rename to backends/p4fmt/p4formatter/p4formatter.h index b891127cebb..2c25c47c3ad 100644 --- a/backends/p4fmt/toP4/toP4.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -11,7 +11,7 @@ namespace P4Fmt { This pass converts a P4-16 IR into a P4 source (text) program. It can optionally emit as comments a representation of the program IR. */ -class ToP4 : public Inspector, ::P4::ResolutionContext { +class P4Formatter : public Inspector, ::P4::ResolutionContext { int expressionPrecedence; /// precedence of current IR::Operation bool isDeclaration; /// current type is a declaration bool showIR; /// if true dump IR as comments @@ -74,7 +74,7 @@ class ToP4 : public Inspector, ::P4::ResolutionContext { emitted. */ cstring mainFile; - ToP4(Util::SourceCodeBuilder &builder, bool showIR, cstring mainFile = nullptr) + P4Formatter(Util::SourceCodeBuilder &builder, bool showIR, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), showIR(showIR), @@ -83,9 +83,9 @@ class ToP4 : public Inspector, ::P4::ResolutionContext { outStream(nullptr), mainFile(mainFile) { visitDagOnce = false; - setName("ToP4"); + setName("P4Formatter"); } - ToP4(std::ostream *outStream, bool showIR, cstring mainFile = nullptr) + P4Formatter(std::ostream *outStream, bool showIR, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), showIR(showIR), @@ -94,9 +94,9 @@ class ToP4 : public Inspector, ::P4::ResolutionContext { outStream(outStream), mainFile(mainFile) { visitDagOnce = false; - setName("ToP4"); + setName("P4Formatter"); } - ToP4() + P4Formatter() : // this is useful for debugging expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), @@ -106,7 +106,7 @@ class ToP4 : public Inspector, ::P4::ResolutionContext { outStream(&std::cout), mainFile(nullptr) { visitDagOnce = false; - setName("ToP4"); + setName("P4Formatter"); } using Inspector::preorder; From 50f86833f0ed065f19de4ec5ad5f7ac362f5f041 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 15:58:05 +0530 Subject: [PATCH 04/16] update header guard Signed-off-by: Nitish --- backends/p4fmt/p4formatter/p4formatter.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter/p4formatter.h index 2c25c47c3ad..9f96128dfa4 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -1,5 +1,7 @@ -#ifndef P4FMT_TOP4_TOP4_H_ -#define P4FMT_TOP4_TOP4_H_ +#ifndef BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ +#define BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ + +#endif // !BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ #include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" @@ -259,4 +261,4 @@ std::string toP4(const IR::INode *node); void dumpP4(const IR::INode *node); } // namespace P4Fmt -#endif /* P4FMT_TOP4_TOP4_H_ */ +#endif /* BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ */ From d496c8e4af0bb5a70c162c4ee6c80cb4739204b2 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 16:22:41 +0530 Subject: [PATCH 05/16] add a catchall preoder method Signed-off-by: Nitish --- backends/p4fmt/p4formatter/p4formatter.cpp | 7 ++++++- backends/p4fmt/p4formatter/p4formatter.h | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/backends/p4fmt/p4formatter/p4formatter.cpp b/backends/p4fmt/p4formatter/p4formatter.cpp index fa057e5e59a..8ce2b40832a 100644 --- a/backends/p4fmt/p4formatter/p4formatter.cpp +++ b/backends/p4fmt/p4formatter/p4formatter.cpp @@ -130,6 +130,11 @@ void P4Formatter::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) builder.emitIndent(); } +bool P4Formatter::preorder(const IR::Node *node) { + P4C_UNIMPLEMENTED("Unhandled IR node type: ", typeid(*node).name()); + return false; +} + bool P4Formatter::preorder(const IR::P4Program *program) { std::set includesEmitted; @@ -716,7 +721,7 @@ bool P4Formatter::preorder(const IR::Declaration_MatchKind *d) { /////////////////////////////////////////////////// #define VECTOR_VISIT(V, T) \ - bool P4Formatter::preorder(const IR::V *v) { \ + bool P4Formatter::preorder(const IR::V *v) { \ if (v == nullptr) return false; \ bool first = true; \ VecPrint sep = getSep(); \ diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter/p4formatter.h index 9f96128dfa4..0a4a7e8edb0 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -1,8 +1,6 @@ #ifndef BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ #define BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ -#endif // !BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ - #include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" #include "ir/visitor.h" @@ -122,6 +120,9 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { void end_apply(const IR::Node *node) override; bool process(const IR::Type_StructLike *t, const char *name); + + bool preorder(const IR::Node *node) override; + // types bool preorder(const IR::Type_Boolean *t) override; bool preorder(const IR::Type_Varbits *t) override; From 7e9280f863b1bcdcf827775e81198da37a3d9ca7 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 18:28:48 +0530 Subject: [PATCH 06/16] clean member variables & methods Signed-off-by: Nitish --- backends/p4fmt/p4fmt.cpp | 2 +- backends/p4fmt/p4formatter/p4formatter.cpp | 152 +-------------------- backends/p4fmt/p4formatter/p4formatter.h | 12 +- 3 files changed, 6 insertions(+), 160 deletions(-) diff --git a/backends/p4fmt/p4fmt.cpp b/backends/p4fmt/p4fmt.cpp index 6a01745f42a..cb1539ad2f5 100644 --- a/backends/p4fmt/p4fmt.cpp +++ b/backends/p4fmt/p4fmt.cpp @@ -24,7 +24,7 @@ std::stringstream getFormattedOutput(std::filesystem::path inputFile) { return formattedOutput; } - auto top4 = P4Fmt::P4Formatter(&formattedOutput, false); + auto top4 = P4Fmt::P4Formatter(&formattedOutput); // Print the program before running front end passes. program->apply(top4); diff --git a/backends/p4fmt/p4formatter/p4formatter.cpp b/backends/p4fmt/p4formatter/p4formatter.cpp index 8ce2b40832a..878b404cb85 100644 --- a/backends/p4fmt/p4formatter/p4formatter.cpp +++ b/backends/p4fmt/p4formatter/p4formatter.cpp @@ -44,92 +44,6 @@ cstring P4Formatter::ifSystemFile(const IR::Node *node) { return nullptr; } -namespace { -class DumpIR : public Inspector { - unsigned depth; - std::stringstream str; - - DumpIR(unsigned depth, unsigned startDepth) : depth(depth) { - for (unsigned i = 0; i < startDepth; i++) str << IndentCtl::indent; - setName("DumpIR"); - visitDagOnce = false; - } - void display(const IR::Node *node) { - str << IndentCtl::endl; - if (node->is()) { - node->Node::dbprint(str); - str << node->to()->member; - } else if (node->is()) { - node->Node::dbprint(str); - str << " " << node; - } else if (node->is()) { - node->Node::dbprint(str); - str << ", size=" << node->to()->size(); - } else if (node->is()) { - node->dbprint(str); - } else { - node->Node::dbprint(str); - } - } - - bool goDeeper(const IR::Node *node) const { - return node->is() || node->is() || node->is(); - } - - bool preorder(const IR::Node *node) override { - if (depth == 0) return false; - display(node); - if (goDeeper(node)) - // increase depth limit for expressions. - depth++; - else - depth--; - str << IndentCtl::indent; - return true; - } - void postorder(const IR::Node *node) override { - if (goDeeper(node)) - depth--; - else - depth++; - str << IndentCtl::unindent; - } - - public: - static std::string dump(const IR::Node *node, unsigned depth, unsigned startDepth) { - DumpIR dumper(depth, startDepth); - node->apply(dumper); - auto result = dumper.str.str(); - return result; - } -}; -} // namespace - -unsigned P4Formatter::curDepth() const { - unsigned result = 0; - auto ctx = getContext(); - while (ctx != nullptr) { - ctx = ctx->parent; - result++; - } - return result; -} - -void P4Formatter::dump(unsigned depth, const IR::Node *node, unsigned adjDepth) { - if (!showIR) return; - if (node == nullptr) node = getOriginal(); - - auto str = DumpIR::dump(node, depth, adjDepth + curDepth()); - bool spc = builder.lastIsSpace(); - builder.commentStart(); - builder.append(str); - builder.commentEnd(); - builder.newline(); - if (spc) - // rather heuristic, but the output is very ugly anyway - builder.emitIndent(); -} - bool P4Formatter::preorder(const IR::Node *node) { P4C_UNIMPLEMENTED("Unhandled IR node type: ", typeid(*node).name()); return false; @@ -139,7 +53,6 @@ bool P4Formatter::preorder(const IR::P4Program *program) { std::set includesEmitted; bool first = true; - dump(2); for (auto a : program->objects) { // Check where this declaration originates cstring sourceFile = ifSystemFile(a); @@ -235,7 +148,6 @@ bool P4Formatter::preorder(const IR::Type_Name *t) { } bool P4Formatter::preorder(const IR::Type_Stack *t) { - dump(2); visit(t->elementType); builder.append("["); visit(t->size); @@ -244,7 +156,6 @@ bool P4Formatter::preorder(const IR::Type_Stack *t) { } bool P4Formatter::preorder(const IR::Type_Specialized *t) { - dump(3); visit(t->baseType); builder.append("<"); setVecSep(", "); @@ -255,7 +166,6 @@ bool P4Formatter::preorder(const IR::Type_Specialized *t) { } bool P4Formatter::preorder(const IR::Argument *arg) { - dump(2); if (!arg->name.name.isNullOrEmpty()) { builder.append(arg->name.name); builder.append(" = "); @@ -265,7 +175,6 @@ bool P4Formatter::preorder(const IR::Argument *arg) { } bool P4Formatter::preorder(const IR::Type_Typedef *t) { - dump(2); if (!t->annotations->annotations.empty()) { visit(t->annotations); builder.spc(); @@ -279,7 +188,6 @@ bool P4Formatter::preorder(const IR::Type_Typedef *t) { } bool P4Formatter::preorder(const IR::Type_Newtype *t) { - dump(2); if (!t->annotations->annotations.empty()) { visit(t->annotations); builder.spc(); @@ -293,7 +201,6 @@ bool P4Formatter::preorder(const IR::Type_Newtype *t) { } bool P4Formatter::preorder(const IR::Type_BaseList *t) { - dump(3); builder.append("tuple<"); bool first = true; for (auto a : t->components) { @@ -308,7 +215,6 @@ bool P4Formatter::preorder(const IR::Type_BaseList *t) { } bool P4Formatter::preorder(const IR::P4ValueSet *t) { - dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); builder.spc(); @@ -328,7 +234,6 @@ bool P4Formatter::preorder(const IR::P4ValueSet *t) { } bool P4Formatter::preorder(const IR::Type_Enum *t) { - dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); builder.spc(); @@ -339,7 +244,6 @@ bool P4Formatter::preorder(const IR::Type_Enum *t) { builder.blockStart(); bool first = true; for (auto a : *t->getDeclarations()) { - dump(2, a->getNode(), 1); if (!first) builder.append(",\n"); first = false; builder.emitIndent(); @@ -351,7 +255,6 @@ bool P4Formatter::preorder(const IR::Type_Enum *t) { } bool P4Formatter::preorder(const IR::Type_SerEnum *t) { - dump(1); if (!t->annotations->annotations.empty()) { visit(t->annotations); builder.spc(); @@ -364,7 +267,6 @@ bool P4Formatter::preorder(const IR::Type_SerEnum *t) { builder.blockStart(); bool first = true; for (auto a : t->members) { - dump(2, a->getNode(), 1); if (!first) builder.append(",\n"); first = false; builder.emitIndent(); @@ -395,7 +297,6 @@ bool P4Formatter::preorder(const IR::TypeParameters *t) { } bool P4Formatter::preorder(const IR::Method *m) { - dump(1); if (!m->annotations->annotations.empty()) { visit(m->annotations); builder.spc(); @@ -420,7 +321,6 @@ bool P4Formatter::preorder(const IR::Method *m) { } bool P4Formatter::preorder(const IR::Function *function) { - dump(1); if (!function->annotations->annotations.empty()) { visit(function->annotations); builder.spc(); @@ -440,7 +340,6 @@ bool P4Formatter::preorder(const IR::Function *function) { } bool P4Formatter::preorder(const IR::Type_Extern *t) { - dump(2); if (isDeclaration) { if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -487,7 +386,6 @@ bool P4Formatter::preorder(const IR::Type_Varbits *t) { } bool P4Formatter::preorder(const IR::Type_Package *package) { - dump(2); builder.emitIndent(); if (!package->annotations->annotations.empty()) { visit(package->annotations); @@ -502,7 +400,6 @@ bool P4Formatter::preorder(const IR::Type_Package *package) { } bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { - dump(2); if (isDeclaration) { builder.emitIndent(); if (!t->annotations->annotations.empty()) { @@ -521,7 +418,7 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { size_t len = 0; for (auto f : t->fields) { Util::SourceCodeBuilder builder; - P4Formatter rec(builder, showIR); + P4Formatter rec(builder); f->type->apply(rec); cstring t = builder.toString(); @@ -530,7 +427,6 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { } for (auto f : t->fields) { - dump(4, f, 1); // this will dump annotations if (f->annotations->size() > 0) { builder.emitIndent(); if (!f->annotations->annotations.empty()) { @@ -552,7 +448,6 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { } bool P4Formatter::preorder(const IR::Type_Parser *t) { - dump(2); builder.emitIndent(); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -567,7 +462,6 @@ bool P4Formatter::preorder(const IR::Type_Parser *t) { } bool P4Formatter::preorder(const IR::Type_Control *t) { - dump(2); builder.emitIndent(); if (!t->annotations->annotations.empty()) { visit(t->annotations); @@ -610,7 +504,6 @@ bool P4Formatter::preorder(const IR::StringLiteral *s) { } bool P4Formatter::preorder(const IR::Declaration_Constant *cst) { - dump(2); if (!cst->annotations->annotations.empty()) { visit(cst->annotations); builder.spc(); @@ -632,7 +525,6 @@ bool P4Formatter::preorder(const IR::Declaration_Constant *cst) { } bool P4Formatter::preorder(const IR::Declaration_Instance *i) { - dump(3); if (!i->annotations->annotations.empty()) { visit(i->annotations); builder.spc(); @@ -656,7 +548,6 @@ bool P4Formatter::preorder(const IR::Declaration_Instance *i) { } bool P4Formatter::preorder(const IR::Declaration_Variable *v) { - dump(2); if (!v->annotations->annotations.empty()) { visit(v->annotations); builder.spc(); @@ -677,7 +568,6 @@ bool P4Formatter::preorder(const IR::Declaration_Variable *v) { } bool P4Formatter::preorder(const IR::Type_Error *d) { - dump(1); bool first = true; for (auto a : *d->getDeclarations()) { if (ifSystemFile(a->getNode())) @@ -689,7 +579,6 @@ bool P4Formatter::preorder(const IR::Type_Error *d) { builder.append("error "); builder.blockStart(); } - dump(1, a->getNode(), 1); first = false; builder.emitIndent(); builder.append(a->getName()); @@ -702,13 +591,11 @@ bool P4Formatter::preorder(const IR::Type_Error *d) { } bool P4Formatter::preorder(const IR::Declaration_MatchKind *d) { - dump(1); builder.append("match_kind "); builder.blockStart(); bool first = true; for (auto a : *d->getDeclarations()) { if (!first) builder.append(",\n"); - dump(1, a->getNode(), 1); first = false; builder.emitIndent(); builder.append(a->getName()); @@ -830,7 +717,6 @@ bool P4Formatter::preorder(const IR::Member *e) { } bool P4Formatter::preorder(const IR::SelectCase *e) { - dump(2); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; setListTerm("(", ")"); @@ -1101,7 +987,6 @@ bool P4Formatter::preorder(const IR::Cast *c) { ////////////////////////////////////////////////////////// bool P4Formatter::preorder(const IR::AssignmentStatement *a) { - dump(2); visit(a->left); builder.append(" = "); visit(a->right); @@ -1110,7 +995,6 @@ bool P4Formatter::preorder(const IR::AssignmentStatement *a) { } bool P4Formatter::preorder(const IR::BlockStatement *s) { - dump(1); if (!s->annotations->annotations.empty()) { visit(s->annotations); builder.spc(); @@ -1124,28 +1008,24 @@ bool P4Formatter::preorder(const IR::BlockStatement *s) { } bool P4Formatter::preorder(const IR::BreakStatement *) { - dump(1); builder.append("break"); builder.endOfStatement(); return false; } bool P4Formatter::preorder(const IR::ContinueStatement *) { - dump(1); builder.append("continue"); builder.endOfStatement(); return false; } bool P4Formatter::preorder(const IR::ExitStatement *) { - dump(1); builder.append("exit"); builder.endOfStatement(); return false; } bool P4Formatter::preorder(const IR::ReturnStatement *statement) { - dump(2); builder.append("return"); if (statement->expression != nullptr) { builder.spc(); @@ -1156,13 +1036,11 @@ bool P4Formatter::preorder(const IR::ReturnStatement *statement) { } bool P4Formatter::preorder(const IR::EmptyStatement *) { - dump(1); builder.endOfStatement(); return false; } bool P4Formatter::preorder(const IR::IfStatement *s) { - dump(2); builder.append("if ("); visit(s->condition); builder.append(") "); @@ -1199,7 +1077,6 @@ bool P4Formatter::preorder(const IR::IfStatement *s) { } bool P4Formatter::preorder(const IR::ForStatement *s) { - dump(2); if (!s->annotations->annotations.empty()) { visit(s->annotations); builder.spc(); @@ -1241,7 +1118,6 @@ bool P4Formatter::preorder(const IR::ForStatement *s) { } bool P4Formatter::preorder(const IR::ForInStatement *s) { - dump(2); if (!s->annotations->annotations.empty()) { visit(s->annotations); builder.spc(); @@ -1279,7 +1155,6 @@ bool P4Formatter::preorder(const IR::ForInStatement *s) { } bool P4Formatter::preorder(const IR::MethodCallStatement *s) { - dump(3); visit(s->methodCall); builder.endOfStatement(); return false; @@ -1293,7 +1168,6 @@ bool P4Formatter::preorder(const IR::SwitchCase *s) { } bool P4Formatter::preorder(const IR::SwitchStatement *s) { - dump(4); builder.append("switch ("); visit(s->expression); builder.append(") "); @@ -1369,7 +1243,6 @@ bool P4Formatter::preorder(const IR::Annotation *a) { } bool P4Formatter::preorder(const IR::Parameter *p) { - dump(2); if (!p->annotations->annotations.empty()) { visit(p->annotations); builder.spc(); @@ -1403,7 +1276,6 @@ bool P4Formatter::preorder(const IR::Parameter *p) { } bool P4Formatter::preorder(const IR::P4Control *c) { - dump(1); bool decl = isDeclaration; isDeclaration = false; visit(c->type); @@ -1438,7 +1310,6 @@ bool P4Formatter::preorder(const IR::ParameterList *p) { } bool P4Formatter::preorder(const IR::P4Action *c) { - dump(2); if (!c->annotations->annotations.empty()) { visit(c->annotations); builder.spc(); @@ -1452,7 +1323,6 @@ bool P4Formatter::preorder(const IR::P4Action *c) { } bool P4Formatter::preorder(const IR::ParserState *s) { - dump(1); if (s->isBuiltin()) return false; if (!s->annotations->annotations.empty()) { @@ -1468,7 +1338,6 @@ bool P4Formatter::preorder(const IR::ParserState *s) { doneVec(); if (s->selectExpression != nullptr) { - dump(2, s->selectExpression, 1); builder.emitIndent(); builder.append("transition "); visit(s->selectExpression); @@ -1482,7 +1351,6 @@ bool P4Formatter::preorder(const IR::ParserState *s) { } bool P4Formatter::preorder(const IR::P4Parser *c) { - dump(1); bool decl = isDeclaration; isDeclaration = false; visit(c->type); @@ -1505,14 +1373,12 @@ bool P4Formatter::preorder(const IR::P4Parser *c) { } bool P4Formatter::preorder(const IR::ExpressionValue *v) { - dump(2); visit(v->expression); builder.endOfStatement(); return false; } bool P4Formatter::preorder(const IR::ActionListElement *ale) { - dump(3); if (!ale->annotations->annotations.empty()) { visit(ale->annotations); builder.spc(); @@ -1522,7 +1388,6 @@ bool P4Formatter::preorder(const IR::ActionListElement *ale) { } bool P4Formatter::preorder(const IR::ActionList *v) { - dump(2); builder.blockStart(); setVecSep(";\n", ";\n"); preorder(&v->actionList); @@ -1532,14 +1397,13 @@ bool P4Formatter::preorder(const IR::ActionList *v) { } bool P4Formatter::preorder(const IR::Key *v) { - dump(2); builder.blockStart(); std::map kf; size_t len = 0; for (auto f : v->keyElements) { Util::SourceCodeBuilder builder; - P4Formatter rec(builder, showIR); + P4Formatter rec(builder); f->expression->apply(rec); cstring s = builder.toString(); @@ -1548,7 +1412,6 @@ bool P4Formatter::preorder(const IR::Key *v) { } for (auto f : v->keyElements) { - dump(2, f, 2); builder.emitIndent(); cstring s = get(kf, f); builder.append(s); @@ -1567,7 +1430,6 @@ bool P4Formatter::preorder(const IR::Key *v) { } bool P4Formatter::preorder(const IR::Property *p) { - dump(1); if (!p->annotations->annotations.empty()) { visit(p->annotations); builder.spc(); @@ -1589,7 +1451,6 @@ bool P4Formatter::preorder(const IR::TableProperties *t) { } bool P4Formatter::preorder(const IR::EntriesList *l) { - dump(1); builder.append("{"); builder.newline(); builder.increaseIndent(); @@ -1601,7 +1462,6 @@ bool P4Formatter::preorder(const IR::EntriesList *l) { } bool P4Formatter::preorder(const IR::Entry *e) { - dump(2); builder.emitIndent(); if (e->isConst) builder.append("const "); if (e->priority) { @@ -1625,7 +1485,6 @@ bool P4Formatter::preorder(const IR::Entry *e) { } bool P4Formatter::preorder(const IR::P4Table *c) { - dump(2); if (!c->annotations->annotations.empty()) { visit(c->annotations); builder.spc(); @@ -1648,14 +1507,9 @@ bool P4Formatter::preorder(const IR::Path *p) { std::string toP4(const IR::INode *node) { std::stringstream stream; - P4Fmt::P4Formatter toP4(&stream, false); + P4Fmt::P4Formatter toP4(&stream); node->getNode()->apply(toP4); return stream.str(); } -void dumpP4(const IR::INode *node) { - auto s = toP4(node); - std::cout << s; -} - } // namespace P4Fmt diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter/p4formatter.h index 0a4a7e8edb0..86330549e3d 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -14,7 +14,6 @@ It can optionally emit as comments a representation of the program IR. class P4Formatter : public Inspector, ::P4::ResolutionContext { int expressionPrecedence; /// precedence of current IR::Operation bool isDeclaration; /// current type is a declaration - bool showIR; /// if true dump IR as comments bool withinArgument; /// if true we are within a method call argument bool noIncludes = false; /// If true do not generate #include statements. /// Used for debugging. @@ -57,9 +56,6 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { } bool isSystemFile(cstring file); cstring ifSystemFile(const IR::Node *node); // return file containing node if system file - // dump node IR tree up to depth - in the form of a comment - void dump(unsigned depth, const IR::Node *node = nullptr, unsigned adjDepth = 0); - unsigned curDepth() const; public: // Output is constructed here @@ -74,10 +70,9 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { emitted. */ cstring mainFile; - P4Formatter(Util::SourceCodeBuilder &builder, bool showIR, cstring mainFile = nullptr) + P4Formatter(Util::SourceCodeBuilder &builder, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), - showIR(showIR), withinArgument(false), builder(builder), outStream(nullptr), @@ -85,10 +80,9 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { visitDagOnce = false; setName("P4Formatter"); } - P4Formatter(std::ostream *outStream, bool showIR, cstring mainFile = nullptr) + P4Formatter(std::ostream *outStream, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), - showIR(showIR), withinArgument(false), builder(*new Util::SourceCodeBuilder()), outStream(outStream), @@ -100,7 +94,6 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { : // this is useful for debugging expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), - showIR(false), withinArgument(false), builder(*new Util::SourceCodeBuilder()), outStream(&std::cout), @@ -259,7 +252,6 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { }; std::string toP4(const IR::INode *node); -void dumpP4(const IR::INode *node); } // namespace P4Fmt #endif /* BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ */ From dded80921b3f759b0fecd7505e31d294341e7f9c Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 13 Aug 2024 18:37:38 +0530 Subject: [PATCH 07/16] mark single args constructors as explicit Signed-off-by: Nitish --- backends/p4fmt/p4formatter/p4formatter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter/p4formatter.h index 86330549e3d..cfea1dbde2e 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -70,7 +70,7 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { emitted. */ cstring mainFile; - P4Formatter(Util::SourceCodeBuilder &builder, cstring mainFile = nullptr) + explicit P4Formatter(Util::SourceCodeBuilder &builder, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), withinArgument(false), @@ -80,7 +80,7 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { visitDagOnce = false; setName("P4Formatter"); } - P4Formatter(std::ostream *outStream, cstring mainFile = nullptr) + explicit P4Formatter(std::ostream *outStream, cstring mainFile = nullptr) : expressionPrecedence(DBPrint::Prec_Low), isDeclaration(true), withinArgument(false), From 7800b5e9c2ee7307449ae6fc112fac2149392131 Mon Sep 17 00:00:00 2001 From: Nitish Date: Fri, 16 Aug 2024 13:42:26 +0530 Subject: [PATCH 08/16] rebase & update namespace Signed-off-by: Nitish --- backends/p4fmt/p4formatter/p4formatter.cpp | 4 ++-- backends/p4fmt/p4formatter/p4formatter.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backends/p4fmt/p4formatter/p4formatter.cpp b/backends/p4fmt/p4formatter/p4formatter.cpp index 878b404cb85..017156f77f6 100644 --- a/backends/p4fmt/p4formatter/p4formatter.cpp +++ b/backends/p4fmt/p4formatter/p4formatter.cpp @@ -9,7 +9,7 @@ #include "frontends/parsers/p4/p4parser.hpp" #include "ir/dump.h" -namespace P4Fmt { +namespace P4::P4Fmt { Visitor::profile_t P4Formatter::init_apply(const IR::Node *node) { LOG4("Program dump:" << std::endl << dumpToString(node)); @@ -1512,4 +1512,4 @@ std::string toP4(const IR::INode *node) { return stream.str(); } -} // namespace P4Fmt +} // namespace P4::P4Fmt diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter/p4formatter.h index cfea1dbde2e..95ddff51b6f 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter/p4formatter.h @@ -6,7 +6,7 @@ #include "ir/visitor.h" #include "lib/sourceCodeBuilder.h" -namespace P4Fmt { +namespace P4::P4Fmt { /** This pass converts a P4-16 IR into a P4 source (text) program. It can optionally emit as comments a representation of the program IR. @@ -253,5 +253,5 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { std::string toP4(const IR::INode *node); -} // namespace P4Fmt +} // namespace P4::P4Fmt #endif /* BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ */ From ecbd6b7ab546124491f9f64c870296511fe74da4 Mon Sep 17 00:00:00 2001 From: Nitish Date: Fri, 16 Aug 2024 21:02:05 +0530 Subject: [PATCH 09/16] restructure p4fmt dir Signed-off-by: Nitish --- backends/p4fmt/CMakeLists.txt | 4 ++-- backends/p4fmt/p4fmt.cpp | 2 +- backends/p4fmt/{p4formatter => }/p4formatter.cpp | 0 backends/p4fmt/{p4formatter => }/p4formatter.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename backends/p4fmt/{p4formatter => }/p4formatter.cpp (100%) rename backends/p4fmt/{p4formatter => }/p4formatter.h (98%) diff --git a/backends/p4fmt/CMakeLists.txt b/backends/p4fmt/CMakeLists.txt index 002fccb93da..4668e3da899 100644 --- a/backends/p4fmt/CMakeLists.txt +++ b/backends/p4fmt/CMakeLists.txt @@ -2,14 +2,14 @@ set(FMT_SRCS p4fmt.cpp options.cpp main.cpp - p4formatter/p4formatter.cpp + p4formatter.cpp ) set(REFCHECK_SRCS refcheck.cpp options.cpp p4fmt.cpp - p4formatter/p4formatter.cpp + p4formatter.cpp ) # p4fmt diff --git a/backends/p4fmt/p4fmt.cpp b/backends/p4fmt/p4fmt.cpp index cb1539ad2f5..72aa602181e 100644 --- a/backends/p4fmt/p4fmt.cpp +++ b/backends/p4fmt/p4fmt.cpp @@ -6,7 +6,7 @@ #include "lib/compile_context.h" #include "lib/error.h" #include "options.h" -#include "p4formatter/p4formatter.h" +#include "p4formatter.h" namespace P4::P4Fmt { diff --git a/backends/p4fmt/p4formatter/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp similarity index 100% rename from backends/p4fmt/p4formatter/p4formatter.cpp rename to backends/p4fmt/p4formatter.cpp diff --git a/backends/p4fmt/p4formatter/p4formatter.h b/backends/p4fmt/p4formatter.h similarity index 98% rename from backends/p4fmt/p4formatter/p4formatter.h rename to backends/p4fmt/p4formatter.h index 95ddff51b6f..4e4f7913d30 100644 --- a/backends/p4fmt/p4formatter/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -1,5 +1,5 @@ -#ifndef BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ -#define BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ +#ifndef BACKENDS_P4FMT_P4FORMATTER_H_ +#define BACKENDS_P4FMT_P4FORMATTER_H_ #include "frontends/common/resolveReferences/resolveReferences.h" #include "ir/ir.h" @@ -254,4 +254,4 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { std::string toP4(const IR::INode *node); } // namespace P4::P4Fmt -#endif /* BACKENDS_P4FMT_P4FORMATTER_P4FORMATTER_H_ */ +#endif /* BACKENDS_P4FMT_P4FORMATTER_H_ */ From c74bbdb91de3086dbcce86045667d144379a6ebc Mon Sep 17 00:00:00 2001 From: Nitish Date: Sat, 17 Aug 2024 00:52:58 +0530 Subject: [PATCH 10/16] Address PR review suggestions [partial] Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 017156f77f6..0f2ef18e20a 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -21,7 +21,7 @@ Visitor::profile_t P4Formatter::init_apply(const IR::Node *node) { void P4Formatter::end_apply(const IR::Node *) { if (outStream != nullptr) { cstring result = builder.toString(); - *outStream << result.c_str(); + *outStream << result; outStream->flush(); } BUG_CHECK(listTerminators.size() == listTerminators_init_apply_size, @@ -45,12 +45,12 @@ cstring P4Formatter::ifSystemFile(const IR::Node *node) { } bool P4Formatter::preorder(const IR::Node *node) { - P4C_UNIMPLEMENTED("Unhandled IR node type: ", typeid(*node).name()); + P4C_UNIMPLEMENTED("Unhandled IR node type: ", node->node_type_name()); return false; } bool P4Formatter::preorder(const IR::P4Program *program) { - std::set includesEmitted; + std::unordered_set includesEmitted; bool first = true; for (auto a : program->objects) { @@ -66,7 +66,7 @@ bool P4Formatter::preorder(const IR::P4Program *program) { * For now we ignore mainFile and don't emit #includes for any * non-system header */ - if (includesEmitted.find(sourceFile) == includesEmitted.end()) { + if (includesEmitted.count(sourceFile) == 0) { if (sourceFile.startsWith(p4includePath)) { const char *p = sourceFile.c_str() + strlen(p4includePath); if (*p == '/') p++; @@ -414,7 +414,7 @@ bool P4Formatter::process(const IR::Type_StructLike *t, const char *name) { builder.spc(); builder.blockStart(); - std::map type; + std::unordered_map type; size_t len = 0; for (auto f : t->fields) { Util::SourceCodeBuilder builder; @@ -748,14 +748,9 @@ bool P4Formatter::preorder(const IR::SelectExpression *e) { bool P4Formatter::preorder(const IR::ListExpression *e) { using ::P4::literals::operator""_cs; - cstring start, end; - if (listTerminators.empty()) { - start = "{ "_cs; - end = " }"_cs; - } else { - start = listTerminators.back().start; - end = listTerminators.back().end; - } + auto [start, end] = listTerminators.empty() ? std::make_pair("{ "_cs, " }"_cs) + : std::make_pair(listTerminators.back().start, + listTerminators.back().end); builder.append(start); setVecSep(", "); int prec = expressionPrecedence; @@ -1399,7 +1394,7 @@ bool P4Formatter::preorder(const IR::ActionList *v) { bool P4Formatter::preorder(const IR::Key *v) { builder.blockStart(); - std::map kf; + std::unordered_map kf; size_t len = 0; for (auto f : v->keyElements) { Util::SourceCodeBuilder builder; From e9c2c9e2e994b9de796e2054b70a0d94511d15f6 Mon Sep 17 00:00:00 2001 From: Nitish Date: Sat, 17 Aug 2024 01:41:38 +0530 Subject: [PATCH 11/16] Refactor repetitive collection iteration with a reusable `visitCollection` function Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 88 ++++++++-------------------------- backends/p4fmt/p4formatter.h | 14 ++++++ 2 files changed, 35 insertions(+), 67 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 0f2ef18e20a..453cd0f225e 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -202,14 +202,11 @@ bool P4Formatter::preorder(const IR::Type_Newtype *t) { bool P4Formatter::preorder(const IR::Type_BaseList *t) { builder.append("tuple<"); - bool first = true; - for (auto a : t->components) { - if (!first) builder.append(", "); - first = false; + visitCollection(t->components, ", ", [&](const auto *a) { auto p4type = a->getP4Type(); CHECK_NULL(p4type); visit(p4type); - } + }); builder.append(">"); return false; } @@ -265,15 +262,12 @@ bool P4Formatter::preorder(const IR::Type_SerEnum *t) { builder.append(t->name); builder.spc(); builder.blockStart(); - bool first = true; - for (auto a : t->members) { - if (!first) builder.append(",\n"); - first = false; + visitCollection(t->members, ",\n", [&](const auto &a) { builder.emitIndent(); builder.append(a->getName()); builder.append(" = "); visit(a->value); - } + }); builder.newline(); builder.blockEnd(true); return false; @@ -282,14 +276,9 @@ bool P4Formatter::preorder(const IR::Type_SerEnum *t) { bool P4Formatter::preorder(const IR::TypeParameters *t) { if (!t->empty()) { builder.append("<"); - bool first = true; bool decl = isDeclaration; isDeclaration = false; - for (auto a : t->parameters) { - if (!first) builder.append(", "); - first = false; - visit(a); - } + visitCollection(t->parameters, ", ", [&](const auto *a) { visit(a); }); isDeclaration = decl; builder.append(">"); } @@ -774,12 +763,7 @@ bool P4Formatter::preorder(const IR::P4ListExpression *e) { builder.append("{"); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; - bool first = true; - for (auto c : e->components) { - if (!first) builder.append(","); - first = false; - visit(c); - } + visitCollection(e->components, ",", [&](const auto &c) { visit(c); }); expressionPrecedence = prec; builder.append("}"); if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); @@ -803,12 +787,7 @@ bool P4Formatter::preorder(const IR::StructExpression *e) { builder.append("{"); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; - bool first = true; - for (auto c : e->components) { - if (!first) builder.append(","); - first = false; - visit(c); - } + visitCollection(e->components, ",", [&](const auto &c) { visit(c); }); expressionPrecedence = prec; builder.append("}"); if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); @@ -825,12 +804,7 @@ bool P4Formatter::preorder(const IR::HeaderStackExpression *e) { builder.append("{"); int prec = expressionPrecedence; expressionPrecedence = DBPrint::Prec_Low; - bool first = true; - for (auto c : e->components) { - if (!first) builder.append(","); - first = false; - visit(c); - } + visitCollection(e->components, ",", [&](const auto &c) { visit(c); }); expressionPrecedence = prec; builder.append("}"); if (expressionPrecedence > DBPrint::Prec_Prefix) builder.append(")"); @@ -1077,24 +1051,19 @@ bool P4Formatter::preorder(const IR::ForStatement *s) { builder.spc(); } builder.append("for ("); - bool first = true; - for (auto *d : s->init) { - if (!first) builder.append(", "); + visitCollection(s->init, ", ", [&](auto *d) { builder.supressStatementSemi(); visit(d, "init"); - first = false; - } + }); builder.append("; "); visit(s->condition, "condition"); builder.append("; "); - first = true; - for (auto *e : s->updates) { - if (e->is()) continue; - if (!first) builder.append(", "); - builder.supressStatementSemi(); - visit(e, "updates"); - first = false; - } + visitCollection(s->updates, ", ", [&](auto *e) { + if (!e->template is()) { + builder.supressStatementSemi(); + visit(e, "updates"); + } + }); builder.append(") "); if (!s->body->is()) { builder.append("{"); @@ -1177,15 +1146,7 @@ bool P4Formatter::preorder(const IR::SwitchStatement *s) { //////////////////////////////////// bool P4Formatter::preorder(const IR::Annotations *a) { - bool first = true; - for (const auto *anno : a->annotations) { - if (!first) { - builder.spc(); - } else { - first = false; - } - visit(anno); - } + visitCollection(a->annotations, " ", [&](const auto *anno) { visit(anno); }); return false; } @@ -1203,14 +1164,11 @@ bool P4Formatter::preorder(const IR::Annotation *a) { } if (!a->kv.empty()) { builder.append(open); - bool first = true; - for (auto kvp : a->kv) { - if (!first) builder.append(", "); - first = false; + visitCollection(a->kv, ", ", [&](const auto &kvp) { builder.append(kvp->name); builder.append("="); visit(kvp->expression); - } + }); builder.append(close); } if (a->expr.empty() && a->kv.empty() && a->structured) { @@ -1221,17 +1179,13 @@ bool P4Formatter::preorder(const IR::Annotation *a) { // We could be prettier here with smarter logic, but let's do the easy // thing by separating every token with a space. builder.append(open); - bool first = true; - for (auto tok : a->body) { - if (!first) builder.append(" "); - first = false; - + visitCollection(a->body, " ", [&](const auto &tok) { bool haveStringLiteral = tok->token_type == ::P4::P4Parser::token_type::TOK_STRING_LITERAL; if (haveStringLiteral) builder.append("\""); builder.append(tok->text); if (haveStringLiteral) builder.append("\""); - } + }); builder.append(close); } return false; diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index 4e4f7913d30..07880f1ed5d 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -54,6 +54,20 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { BUG_CHECK(!listTerminators.empty(), "Empty listTerminators"); listTerminators.pop_back(); } + + template + void visitCollection(const Collection &collection, const std::string &separator, + Func visitFunc) { + bool first = true; + for (const auto &elem : collection) { + if (!first) { + builder.append(separator); + } + first = false; + visitFunc(elem); + } + } + bool isSystemFile(cstring file); cstring ifSystemFile(const IR::Node *node); // return file containing node if system file From 4b22b49daa6d368fd6092eabe313166dab20bbd4 Mon Sep 17 00:00:00 2001 From: Nitish Date: Sat, 17 Aug 2024 03:37:47 +0530 Subject: [PATCH 12/16] remove top level qualified P4 namespace Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 453cd0f225e..587e616d36a 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -736,7 +736,7 @@ bool P4Formatter::preorder(const IR::SelectExpression *e) { } bool P4Formatter::preorder(const IR::ListExpression *e) { - using ::P4::literals::operator""_cs; + using namespace P4::literals; auto [start, end] = listTerminators.empty() ? std::make_pair("{ "_cs, " }"_cs) : std::make_pair(listTerminators.back().start, listTerminators.back().end); @@ -1091,7 +1091,7 @@ bool P4Formatter::preorder(const IR::ForInStatement *s) { builder.supressStatementSemi(); visit(s->decl, "decl"); } else { - auto *decl = resolveUnique(s->ref->path->name, ::P4::ResolutionType::Any); + auto *decl = resolveUnique(s->ref->path->name, P4::ResolutionType::Any); if (auto *di = decl->to()) { builder.supressStatementSemi(); visit(di, "decl"); @@ -1181,7 +1181,7 @@ bool P4Formatter::preorder(const IR::Annotation *a) { builder.append(open); visitCollection(a->body, " ", [&](const auto &tok) { bool haveStringLiteral = - tok->token_type == ::P4::P4Parser::token_type::TOK_STRING_LITERAL; + tok->token_type == P4::P4Parser::token_type::TOK_STRING_LITERAL; if (haveStringLiteral) builder.append("\""); builder.append(tok->text); if (haveStringLiteral) builder.append("\""); From 197bdd8f1b4bad98d0bb7b7aef9f9b5304251099 Mon Sep 17 00:00:00 2001 From: Nitish Date: Sat, 17 Aug 2024 04:19:24 +0530 Subject: [PATCH 13/16] [`visitCollection`]: deal with the enumerator type Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 21 +++++---------------- backends/p4fmt/p4formatter.h | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 587e616d36a..175c6d79be9 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -239,13 +239,10 @@ bool P4Formatter::preorder(const IR::Type_Enum *t) { builder.append(t->name); builder.spc(); builder.blockStart(); - bool first = true; - for (auto a : *t->getDeclarations()) { - if (!first) builder.append(",\n"); - first = false; + visitCollection(*t->getDeclarations(), ",\n", [this](const auto &a) { builder.emitIndent(); builder.append(a->getName()); - } + }); builder.newline(); builder.blockEnd(true); return false; @@ -582,13 +579,10 @@ bool P4Formatter::preorder(const IR::Type_Error *d) { bool P4Formatter::preorder(const IR::Declaration_MatchKind *d) { builder.append("match_kind "); builder.blockStart(); - bool first = true; - for (auto a : *d->getDeclarations()) { - if (!first) builder.append(",\n"); - first = false; + visitCollection(*d->getDeclarations(), ",\n", [this](const auto &a) { builder.emitIndent(); builder.append(a->getName()); - } + }); builder.newline(); builder.blockEnd(true); return false; @@ -1248,12 +1242,7 @@ bool P4Formatter::preorder(const IR::P4Control *c) { bool P4Formatter::preorder(const IR::ParameterList *p) { builder.append("("); - bool first = true; - for (auto param : *p->getEnumerator()) { - if (!first) builder.append(", "); - first = false; - visit(param); - } + visitCollection(*p->getEnumerator(), ", ", [this](const auto ¶m) { visit(param); }); builder.append(")"); return false; } diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index 07880f1ed5d..d2803ed616c 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -55,6 +55,8 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { listTerminators.pop_back(); } + // For collections which provide support for range based for loops + // e.g. `IndexedVector` or similar collections template void visitCollection(const Collection &collection, const std::string &separator, Func visitFunc) { @@ -68,6 +70,19 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { } } + // For `Enumerator` + template + void visitCollection(Enumerator &enumerator, const std::string &separator, Func visitFunc) { + bool first = true; + while (enumerator.moveNext()) { + if (!first) { + builder.append(separator); + } + first = false; + visitFunc(enumerator.getCurrent()); + } + } + bool isSystemFile(cstring file); cstring ifSystemFile(const IR::Node *node); // return file containing node if system file From e4e1db87956cba8257d5446b815641caa83c16a7 Mon Sep 17 00:00:00 2001 From: Nitish Date: Mon, 19 Aug 2024 16:28:13 +0530 Subject: [PATCH 14/16] use RAII objects for separator management Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 119 ++++++++++++++++++--------------- backends/p4fmt/p4formatter.h | 13 ++++ 2 files changed, 79 insertions(+), 53 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 175c6d79be9..8f992cf9b00 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -158,9 +158,10 @@ bool P4Formatter::preorder(const IR::Type_Stack *t) { bool P4Formatter::preorder(const IR::Type_Specialized *t) { visit(t->baseType); builder.append("<"); - setVecSep(", "); - visit(t->arguments); - doneVec(); + { + WithSeparator comma(*this, ", "); + visit(t->arguments); + } builder.append(">"); return false; } @@ -345,12 +346,13 @@ bool P4Formatter::preorder(const IR::Type_Extern *t) { "in P4-16, and thus are not emitted as P4-16", t); - setVecSep(";\n", ";\n"); - bool decl = isDeclaration; - isDeclaration = true; - preorder(&t->methods); - isDeclaration = decl; - doneVec(); + { + WithSeparator newline(*this, ";\n", ";\n"); + bool decl = isDeclaration; + isDeclaration = true; + preorder(&t->methods); + isDeclaration = decl; + } builder.blockEnd(true); return false; } @@ -519,9 +521,10 @@ bool P4Formatter::preorder(const IR::Declaration_Instance *i) { CHECK_NULL(type); visit(type); builder.append("("); - setVecSep(", "); - visit(i->arguments); - doneVec(); + { + WithSeparator comma(*this, ", "); + visit(i->arguments); + } builder.append(")"); builder.spc(); builder.append(i->name); @@ -679,12 +682,13 @@ bool P4Formatter::preorder(const IR::TypeNameExpression *e) { bool P4Formatter::preorder(const IR::ConstructorCallExpression *e) { visit(e->constructedType); builder.append("("); - setVecSep(", "); - int prec = expressionPrecedence; - expressionPrecedence = DBPrint::Prec_Low; - visit(e->arguments); - expressionPrecedence = prec; - doneVec(); + { + WithSeparator comma(*this, ", "); + int prec = expressionPrecedence; + expressionPrecedence = DBPrint::Prec_Low; + visit(e->arguments); + expressionPrecedence = prec; + } builder.append(")"); return false; } @@ -720,10 +724,11 @@ bool P4Formatter::preorder(const IR::SelectExpression *e) { doneList(); builder.append(") "); builder.blockStart(); - setVecSep(";\n", ";\n"); - expressionPrecedence = DBPrint::Prec_Low; - preorder(&e->selectCases); - doneVec(); + { + WithSeparator newline(*this, ";\n", ";\n"); + expressionPrecedence = DBPrint::Prec_Low; + preorder(&e->selectCases); + } builder.blockEnd(true); expressionPrecedence = prec; return false; @@ -854,19 +859,21 @@ bool P4Formatter::preorder(const IR::MethodCallExpression *e) { bool decl = isDeclaration; isDeclaration = false; builder.append("<"); - setVecSep(", "); - visit(e->typeArguments); - doneVec(); + { + WithSeparator comma(*this, ", "); + visit(e->typeArguments); + } builder.append(">"); isDeclaration = decl; } builder.append("("); - setVecSep(", "); - expressionPrecedence = DBPrint::Prec_Low; - withinArgument = true; - visit(e->arguments); - withinArgument = false; - doneVec(); + { + WithSeparator comma(*this, ", "); + expressionPrecedence = DBPrint::Prec_Low; + withinArgument = true; + visit(e->arguments); + withinArgument = false; + } builder.append(")"); if (useParens) builder.append(")"); expressionPrecedence = prec; @@ -963,9 +970,10 @@ bool P4Formatter::preorder(const IR::BlockStatement *s) { builder.spc(); } builder.blockStart(); - setVecSep("\n", "\n"); - preorder(&s->components); - doneVec(); + { + WithSeparator newline(*this, "\n", "\n"); + preorder(&s->components); + } builder.blockEnd(false); return false; } @@ -1130,9 +1138,10 @@ bool P4Formatter::preorder(const IR::SwitchStatement *s) { visit(s->expression); builder.append(") "); builder.blockStart(); - setVecSep("\n", "\n"); - preorder(&s->cases); - doneVec(); + { + WithSeparator newline(*this, "\n", "\n"); + preorder(&s->cases); + } builder.blockEnd(false); return false; } @@ -1151,9 +1160,10 @@ bool P4Formatter::preorder(const IR::Annotation *a) { const char *close = a->structured ? "]" : ")"; if (!a->expr.empty()) { builder.append(open); - setVecSep(", "); - preorder(&a->expr); - doneVec(); + { + WithSeparator comma(*this, ", "); + preorder(&a->expr); + } builder.append(close); } if (!a->kv.empty()) { @@ -1271,10 +1281,10 @@ bool P4Formatter::preorder(const IR::ParserState *s) { builder.append(s->name); builder.spc(); builder.blockStart(); - setVecSep("\n", "\n"); - preorder(&s->components); - doneVec(); - + { + WithSeparator newline(*this, "\n", "\n"); + preorder(&s->components); + } if (s->selectExpression != nullptr) { builder.emitIndent(); builder.append("transition "); @@ -1296,9 +1306,10 @@ bool P4Formatter::preorder(const IR::P4Parser *c) { if (c->constructorParams->size() != 0) visit(c->constructorParams); builder.spc(); builder.blockStart(); - setVecSep("\n", "\n"); - preorder(&c->parserLocals); - doneVec(); + { + WithSeparator newline(*this, "\n", "\n"); + preorder(&c->parserLocals); + } // explicit visit of parser states for (auto s : c->states) { if (s->isBuiltin()) continue; @@ -1327,9 +1338,10 @@ bool P4Formatter::preorder(const IR::ActionListElement *ale) { bool P4Formatter::preorder(const IR::ActionList *v) { builder.blockStart(); - setVecSep(";\n", ";\n"); - preorder(&v->actionList); - doneVec(); + { + WithSeparator newline(*this, ";\n", ";\n"); + preorder(&v->actionList); + } builder.blockEnd(false); return false; } @@ -1431,9 +1443,10 @@ bool P4Formatter::preorder(const IR::P4Table *c) { builder.append(c->name); builder.spc(); builder.blockStart(); - setVecSep("\n", "\n"); - visit(c->properties); - doneVec(); + { + WithSeparator newline(*this, "\n", "\n"); + visit(c->properties); + } builder.blockEnd(false); return false; } diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index d2803ed616c..65620769bad 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -55,6 +55,19 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { listTerminators.pop_back(); } + // RAII helper class to manage separators + class WithSeparator { + P4Formatter &formatter; + + public: + WithSeparator(P4Formatter &fmt, const char *sep, const char *term = nullptr) + : formatter(fmt) { + formatter.setVecSep(sep, term); + } + + ~WithSeparator() { formatter.doneVec(); } + }; + // For collections which provide support for range based for loops // e.g. `IndexedVector` or similar collections template From 76e121dcfb82704c909f2f75c5828e20554115c0 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 20 Aug 2024 02:45:24 +0530 Subject: [PATCH 15/16] use `std::filesystem::path` for path manipulations Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 26 ++++++++++++-------------- backends/p4fmt/p4formatter.h | 6 ++++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 8f992cf9b00..80bd34b0535 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -31,17 +31,16 @@ void P4Formatter::end_apply(const IR::Node *) { } // Try to guess whether a file is a "system" file -bool P4Formatter::isSystemFile(cstring file) { +bool P4Formatter::isSystemFile(path &file) { if (noIncludes) return false; - if (file.startsWith(p4includePath)) return true; - return false; + return file.parent_path() == p4includePath; } -cstring P4Formatter::ifSystemFile(const IR::Node *node) { - if (!node->srcInfo.isValid()) return nullptr; - auto sourceFile = node->srcInfo.getSourceFile(); +path P4Formatter::ifSystemFile(const IR::Node *node) { + if (!node->srcInfo.isValid()) return {}; + path sourceFile(node->srcInfo.getSourceFile().c_str()); if (isSystemFile(sourceFile)) return sourceFile; - return nullptr; + return {}; } bool P4Formatter::preorder(const IR::Node *node) { @@ -55,9 +54,9 @@ bool P4Formatter::preorder(const IR::P4Program *program) { bool first = true; for (auto a : program->objects) { // Check where this declaration originates - cstring sourceFile = ifSystemFile(a); + path sourceFile = ifSystemFile(a); if (!a->is() && // errors can come from multiple files - sourceFile != nullptr) { + !sourceFile.empty()) { /* FIXME -- when including a user header file (sourceFile != * mainFile), do we want to emit an #include of it or not? Probably * not when translating from P4-14, as that would create a P4-16 @@ -66,10 +65,9 @@ bool P4Formatter::preorder(const IR::P4Program *program) { * For now we ignore mainFile and don't emit #includes for any * non-system header */ - if (includesEmitted.count(sourceFile) == 0) { - if (sourceFile.startsWith(p4includePath)) { - const char *p = sourceFile.c_str() + strlen(p4includePath); - if (*p == '/') p++; + if (includesEmitted.count(sourceFile.string()) == 0) { + if (sourceFile.parent_path() == p4includePath) { + path p = sourceFile.filename(); if (P4V1::V1Model::instance.file.name == p) { P4V1::getV1ModelVersion g; program->apply(g); @@ -559,7 +557,7 @@ bool P4Formatter::preorder(const IR::Declaration_Variable *v) { bool P4Formatter::preorder(const IR::Type_Error *d) { bool first = true; for (auto a : *d->getDeclarations()) { - if (ifSystemFile(a->getNode())) + if (!ifSystemFile(a->getNode()).empty()) // only print if not from a system file continue; if (!first) { diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index 65620769bad..5320b183bb8 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -7,6 +7,7 @@ #include "lib/sourceCodeBuilder.h" namespace P4::P4Fmt { +using std::filesystem::path; /** This pass converts a P4-16 IR into a P4 source (text) program. It can optionally emit as comments a representation of the program IR. @@ -96,8 +97,9 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { } } - bool isSystemFile(cstring file); - cstring ifSystemFile(const IR::Node *node); // return file containing node if system file + bool isSystemFile(std::filesystem::path &file); + std::filesystem::path ifSystemFile( + const IR::Node *node); // return file containing node if system file public: // Output is constructed here From cbfa732c4f4598df5580f5e0961df53a7d96a571 Mon Sep 17 00:00:00 2001 From: Nitish Date: Tue, 20 Aug 2024 13:23:42 +0530 Subject: [PATCH 16/16] nits Signed-off-by: Nitish --- backends/p4fmt/p4formatter.cpp | 10 +++++----- backends/p4fmt/p4formatter.h | 11 ++++------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/backends/p4fmt/p4formatter.cpp b/backends/p4fmt/p4formatter.cpp index 80bd34b0535..73d8f4ee416 100644 --- a/backends/p4fmt/p4formatter.cpp +++ b/backends/p4fmt/p4formatter.cpp @@ -31,14 +31,14 @@ void P4Formatter::end_apply(const IR::Node *) { } // Try to guess whether a file is a "system" file -bool P4Formatter::isSystemFile(path &file) { +bool P4Formatter::isSystemFile(std::filesystem::path &file) { if (noIncludes) return false; return file.parent_path() == p4includePath; } -path P4Formatter::ifSystemFile(const IR::Node *node) { +std::filesystem::path P4Formatter::ifSystemFile(const IR::Node *node) { if (!node->srcInfo.isValid()) return {}; - path sourceFile(node->srcInfo.getSourceFile().c_str()); + std::filesystem::path sourceFile(node->srcInfo.getSourceFile().c_str()); if (isSystemFile(sourceFile)) return sourceFile; return {}; } @@ -54,7 +54,7 @@ bool P4Formatter::preorder(const IR::P4Program *program) { bool first = true; for (auto a : program->objects) { // Check where this declaration originates - path sourceFile = ifSystemFile(a); + std::filesystem::path sourceFile = ifSystemFile(a); if (!a->is() && // errors can come from multiple files !sourceFile.empty()) { /* FIXME -- when including a user header file (sourceFile != @@ -67,7 +67,7 @@ bool P4Formatter::preorder(const IR::P4Program *program) { if (includesEmitted.count(sourceFile.string()) == 0) { if (sourceFile.parent_path() == p4includePath) { - path p = sourceFile.filename(); + std::filesystem::path p = sourceFile.filename(); if (P4V1::V1Model::instance.file.name == p) { P4V1::getV1ModelVersion g; program->apply(g); diff --git a/backends/p4fmt/p4formatter.h b/backends/p4fmt/p4formatter.h index 5320b183bb8..8a0844d89fc 100644 --- a/backends/p4fmt/p4formatter.h +++ b/backends/p4fmt/p4formatter.h @@ -7,7 +7,6 @@ #include "lib/sourceCodeBuilder.h" namespace P4::P4Fmt { -using std::filesystem::path; /** This pass converts a P4-16 IR into a P4 source (text) program. It can optionally emit as comments a representation of the program IR. @@ -104,10 +103,10 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { public: // Output is constructed here Util::SourceCodeBuilder &builder; - /* FIXME -- simplify this by getting rid of the 'builder' object and just emitting - * directly to the ostream. The SourceCodeBuilder object does not appear to add any - * useful functionality the ostream does not already provide; it just serves to - * obfuscate the code */ + // FIXME -- simplify this by getting rid of the 'builder' object and just emitting + // directly to the ostream. The SourceCodeBuilder object does not appear to add any + // useful functionality the ostream does not already provide; it just serves to + // obfuscate the code std::ostream *outStream; /** If this is set to non-nullptr, some declarations that come from libraries and models are not @@ -146,8 +145,6 @@ class P4Formatter : public Inspector, ::P4::ResolutionContext { setName("P4Formatter"); } - using Inspector::preorder; - void setnoIncludesArg(bool condition) { noIncludes = condition; } void setListTerm(const char *start, const char *end) {