From 7d9d01fcc1f250b1a71bf18101256bf9bda11901 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Wed, 2 Feb 2022 17:19:25 +0200 Subject: [PATCH 01/17] remove unnecessary checking for saving argument of log_msg --- backends/bmv2/simple_switch/simpleSwitch.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index f939cdd0e4..6ca72a61f6 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -858,11 +858,6 @@ Util::IJson* ExternConverter_log_msg::convertExternFunction( auto arr = new Util::JsonArray(); for (auto v : le->components) { auto tf = ctxt->typeMap->getType(v); - if (!tf->is() && !tf->is()) { - ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, - "%1%: only integral values supported for logged values", mc); - return primitive; - } auto val = ctxt->conv->convert(v, false, true, true); arr->append(val); } From e8f7749d07cbe3545f8033a0a5611e3d42ea6ebc Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 11 Feb 2022 18:42:36 +0200 Subject: [PATCH 02/17] initial commit for flatten log_msg --- backends/bmv2/simple_switch/simpleSwitch.cpp | 7 ++ midend/CMakeLists.txt | 1 + midend/flattenLogMsg.cpp | 104 +++++++++++++++++++ midend/flattenLogMsg.h | 29 ++++++ 4 files changed, 141 insertions(+) create mode 100644 midend/flattenLogMsg.cpp create mode 100644 midend/flattenLogMsg.h diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 6ca72a61f6..9afa86e3fc 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -24,6 +24,7 @@ limitations under the License. #include "backends/bmv2/common/annotations.h" #include "frontends/p4/fromv1.0/v1model.h" #include "frontends/p4/cloner.h" +#include "midend/flattenLogMsg.h" #include "simpleSwitch.h" #include "backends/bmv2/simple_switch/options.h" @@ -858,6 +859,11 @@ Util::IJson* ExternConverter_log_msg::convertExternFunction( auto arr = new Util::JsonArray(); for (auto v : le->components) { auto tf = ctxt->typeMap->getType(v); + if (!tf->is() && !tf->is()) { + ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, + "%1%: only integral values supported for logged values", mc); + return primitive; + } auto val = ctxt->conv->convert(v, false, true, true); arr->append(val); } @@ -1164,6 +1170,7 @@ SimpleSwitchBackend::convert(const IR::ToplevelBlock* tlb) { new ProcessControls(&structure->pipeline_controls)), new P4::SimplifyControlFlow(refMap, typeMap), new P4::RemoveAllUnusedDeclarations(refMap), + new P4::FlattenLogMsg(refMap, typeMap), // Converts the DAG into a TREE (at least for expressions) // This is important later for conversion to JSON. new P4::ClonePathExpressions(), diff --git a/midend/CMakeLists.txt b/midend/CMakeLists.txt index 5ba3c6431c..e2635335af 100644 --- a/midend/CMakeLists.txt +++ b/midend/CMakeLists.txt @@ -27,6 +27,7 @@ set (MIDEND_SRCS fillEnumMap.cpp flattenHeaders.cpp flattenInterfaceStructs.cpp + flattenLogMsg.cpp hsIndexSimplify.cpp interpreter.cpp global_copyprop.cpp diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp new file mode 100644 index 0000000000..32a745229d --- /dev/null +++ b/midend/flattenLogMsg.cpp @@ -0,0 +1,104 @@ +#include "midend/flattenLogMsg.h" +#include "flattenLogMsg.h" + +namespace P4 { + +FlattenLogMsg::FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) : + refMap(refMap), typeMap(typeMap) { +} + +const IR::Node* FlattenLogMsg::preorder(IR::BlockStatement* blockStatement) { + IR::IndexedVector components; + for (auto i : blockStatement->components) { + FlattenLogMsg flattenLogMsg(refMap, typeMap); + auto* newStatement = i->apply(flattenLogMsg); + if (auto* block = newStatement->to()) { + components.insert(components.end(), block->components.begin(), + block->components.end()); + } else { + components.push_back(newStatement->to()); + } + } + auto* block = blockStatement->clone(); + block->components = components; + return block; +} + +std::pair, std::string> FlattenLogMsg::unfoldStruct( + const IR::Expression* expr, const IR::Type_StructLike* typeStruct, std::string& strParam) { + IR::Vector result; + std::string strResult; + for (auto field : typeStruct->fields) { + size_t n = strParam.find("{}"); + if (n != std::string::npos) { + strResult += strParam.substr(0, n); + strParam = strParam.substr(n + 2); + } + auto* newMember = new IR::Member(expr->srcInfo, field->type, expr, field->name); + std::cout << "member : " << newMember << "\n type : " << newMember->type << std::endl; + if (auto *fieldTypeStruct = field->type->to()) { + std::string curRes; + auto innerFields = unfoldStruct(newMember, fieldTypeStruct, curRes); + result.insert(result.end(), innerFields.first.begin(), innerFields.first.end()); + strResult += "("; + strResult += innerFields.second; + strResult += ")"; + } else { + if (expr->is()) { + strResult += field->name; + strResult += "="; + } + strResult += "{}"; + if (expr->is()) { + strResult += " "; + } + result.push_back(newMember); + } + } + return std::make_pair(result, strResult); +} + +const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { + if (auto* path = methodCallStatement->methodCall->method->to()) { + if (path->path->name.name == "log_msg") { + auto* param1 = methodCallStatement->methodCall->arguments->at(0)->expression; + auto* param2 = methodCallStatement->methodCall->arguments->at(1)->expression; + if (!param1->is() || !param2->is()) { + return methodCallStatement; + } + std::string strParam1 = param1->to()->value.c_str(); + auto* argType = + typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); + std::cout << argType << " : " << argType->node_type_name() << std::endl; + if (argType->is()) { + std::cout << methodCallStatement->methodCall->arguments->at(0)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(0)->expression->type << std::endl; + std::cout << methodCallStatement->methodCall->arguments->at(1)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; + auto exprVector = + unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, + argType->to(), strParam1); + auto* newBlock = new IR::BlockStatement(); + for (auto newExpr : exprVector.first) { + std::cout << "expr : " << newExpr << "\ntype : " << newExpr->type << std::endl; + auto* newMethodCall = methodCallStatement->methodCall->clone(); + auto* newTypeArguments = newMethodCall->typeArguments->clone(); + newTypeArguments->clear(); + newTypeArguments->push_back(newExpr->type); + newMethodCall->typeArguments = newTypeArguments; + auto* newArguments = newMethodCall->arguments->clone(); + auto* newArgument = newMethodCall->arguments->at(1)->clone(); + newArgument->expression = newExpr; + newArguments->at(1) = newArgument; + newMethodCall->arguments = newArguments; + auto* newMethodCallStatement = methodCallStatement->clone(); + newMethodCallStatement->methodCall = newMethodCall; + std::cout << "new st : " << newMethodCallStatement << std::endl; + newBlock->components.push_back(newMethodCallStatement); + } + return newBlock; + } + } + } + return methodCallStatement; +} + +} // namespace P4 diff --git a/midend/flattenLogMsg.h b/midend/flattenLogMsg.h new file mode 100644 index 0000000000..165a9e8ec5 --- /dev/null +++ b/midend/flattenLogMsg.h @@ -0,0 +1,29 @@ +#ifndef _MIDEND_FLATTENILOGMSG_H_ +#define _MIDEND_FLATTENILOGMSG_H_ + +#include "ir/ir.h" +#include "frontends/p4/typeChecking/typeChecker.h" + +namespace P4 { + +/** +This pass translates all occuarence of log_msg function with non-flattend arguments into +set of the flatten calls of log_smg. +*/ +class FlattenLogMsg : public Transform { + P4::ReferenceMap* refMap; + P4::TypeMap* typeMap; + + public: + FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap); + const IR::Node* preorder(IR::BlockStatement* blockStatement) override; + const IR::Node* postorder(IR::MethodCallStatement* methodCallStatement) override; + + protected: + std::pair, std::string> unfoldStruct(const IR::Expression* expr, + const IR::Type_StructLike* typeStruct, std::string& strParam); +}; + +} // namespace P4 + +#endif /* _MIDEND_FLATTENILOGMSG_H_ */ \ No newline at end of file From d488c3a85db155bb60c0740daf57d38bf177a0bd Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Mon, 14 Feb 2022 18:31:33 +0200 Subject: [PATCH 03/17] refactoring of generation new log_msg functions --- midend/flattenLogMsg.cpp | 131 ++++++++++++++++++++++++++------------- midend/flattenLogMsg.h | 8 ++- 2 files changed, 95 insertions(+), 44 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index 32a745229d..8ae25e8b46 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -24,38 +24,77 @@ const IR::Node* FlattenLogMsg::preorder(IR::BlockStatement* blockStatement) { return block; } -std::pair, std::string> FlattenLogMsg::unfoldStruct( - const IR::Expression* expr, const IR::Type_StructLike* typeStruct, std::string& strParam) { - IR::Vector result; +TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::string strParam, + std::string curName) { + TypeLogMsgParams result; + if (auto structType = expr->type->to()) { + result.second += "("; + for (auto field : structType->fields) { + std::string nm = curName + std::string("."); + nm += field->name.name + std::string(" : "); + auto* newMember = new IR::Member(field->type, expr, field->name); + if (field->type->is()) { + auto curResult = unfoldStruct(newMember, strParam, nm); + nm += curResult.second; + result.first.insert(result.first.end(), curResult.first.begin(), + curResult.first.end()); + } else { + nm += "{}"; + result.first.push_back(new IR::NamedExpression(expr->srcInfo, IR::ID(nm), + newMember)); + } + result.second += nm + std::string(") "); + } + return result; + } + if (!expr->is()) { + result.first.push_back(new IR::NamedExpression(expr->srcInfo, IR::ID(curName), expr)); + result.second = curName + std::string(" : {}"); + return result; + } + auto* structExpr = expr->to(); std::string strResult; - for (auto field : typeStruct->fields) { + for (auto namedExpr : structExpr->components) { + std::cout << namedExpr->name << ":" << namedExpr->expression << ":" << namedExpr->expression->type->node_type_name() << std::endl; size_t n = strParam.find("{}"); if (n != std::string::npos) { strResult += strParam.substr(0, n); strParam = strParam.substr(n + 2); } - auto* newMember = new IR::Member(expr->srcInfo, field->type, expr, field->name); - std::cout << "member : " << newMember << "\n type : " << newMember->type << std::endl; - if (auto *fieldTypeStruct = field->type->to()) { - std::string curRes; - auto innerFields = unfoldStruct(newMember, fieldTypeStruct, curRes); - result.insert(result.end(), innerFields.first.begin(), innerFields.first.end()); + if (namedExpr->expression->type->is()) { + std::string nm; + if (curName.length()) { + nm = curName + std::string("."); + } + nm += namedExpr->name.name.c_str(); + auto innerFields = unfoldStruct(namedExpr->expression, "", nm); + result.first.insert(result.first.end(), innerFields.first.begin(), innerFields.first.end()); strResult += "("; strResult += innerFields.second; strResult += ")"; } else { - if (expr->is()) { - strResult += field->name; - strResult += "="; - } strResult += "{}"; - if (expr->is()) { - strResult += " "; - } - result.push_back(newMember); + result.first.push_back(namedExpr); } } - return std::make_pair(result, strResult); + result.second = strResult; + return result; +} + +const IR::Type_StructLike* FlattenLogMsg::generateNewStructType( + const IR::Type_StructLike* structType, IR::IndexedVector &v) { + IR::IndexedVector fields; + size_t index = 1; + for (auto namedExpr : v) { + //StructField(Util::SourceInfo srcInfo, IR::ID name, const IR::Type* type); + std::string nm = std::string("f") + std::to_string(index++); + fields.push_back(new IR::StructField(namedExpr->srcInfo, IR::ID(nm), + namedExpr->expression->type)); + } + auto* newStructType = structType->clone(); + newStructType->fields = fields; + newStructType->name.name = newStructType->name.name + cstring("_1"); + return newStructType; } const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { @@ -72,29 +111,37 @@ const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStat std::cout << argType << " : " << argType->node_type_name() << std::endl; if (argType->is()) { std::cout << methodCallStatement->methodCall->arguments->at(0)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(0)->expression->type << std::endl; - std::cout << methodCallStatement->methodCall->arguments->at(1)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; - auto exprVector = - unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, - argType->to(), strParam1); - auto* newBlock = new IR::BlockStatement(); - for (auto newExpr : exprVector.first) { - std::cout << "expr : " << newExpr << "\ntype : " << newExpr->type << std::endl; - auto* newMethodCall = methodCallStatement->methodCall->clone(); - auto* newTypeArguments = newMethodCall->typeArguments->clone(); - newTypeArguments->clear(); - newTypeArguments->push_back(newExpr->type); - newMethodCall->typeArguments = newTypeArguments; - auto* newArguments = newMethodCall->arguments->clone(); - auto* newArgument = newMethodCall->arguments->at(1)->clone(); - newArgument->expression = newExpr; - newArguments->at(1) = newArgument; - newMethodCall->arguments = newArguments; - auto* newMethodCallStatement = methodCallStatement->clone(); - newMethodCallStatement->methodCall = newMethodCall; - std::cout << "new st : " << newMethodCallStatement << std::endl; - newBlock->components.push_back(newMethodCallStatement); - } - return newBlock; + std::cout << methodCallStatement->methodCall->arguments->at(1)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; + auto* structType = argType->to(); + auto exprVector = + unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, + strParam1); + if (structType->fields.size() == exprVector.first.size()) { + return methodCallStatement; + } + structType = generateNewStructType(structType, exprVector.first); + auto* newMethodCall = methodCallStatement->methodCall->clone(); + auto* newTypeArguments = newMethodCall->typeArguments->clone(); + newTypeArguments->clear(); + newTypeArguments->push_back(structType); + newMethodCall->typeArguments = newTypeArguments; + auto* newArguments = newMethodCall->arguments->clone(); + auto* newArgument = newMethodCall->arguments->at(0)->clone(); + auto* newString = newArgument->expression->to()->clone(); + newString->value = exprVector.second; + newArgument->expression = newString; + newArguments->at(0) = newArgument; + newArgument = newMethodCall->arguments->at(1)->clone(); + auto newStructExpression = newArgument->expression->to()->clone(); + newStructExpression->type = structType; + newStructExpression->components = exprVector.first; + newArgument->expression = newStructExpression; + newArguments->at(1) = newArgument; + newMethodCall->arguments = newArguments; + auto* newMethodCallStatement = methodCallStatement->clone(); + newMethodCallStatement->methodCall = newMethodCall; + std::cout << "new st : " << newMethodCallStatement << std::endl; + return newMethodCallStatement; } } } diff --git a/midend/flattenLogMsg.h b/midend/flattenLogMsg.h index 165a9e8ec5..fd3bef474d 100644 --- a/midend/flattenLogMsg.h +++ b/midend/flattenLogMsg.h @@ -6,6 +6,8 @@ namespace P4 { +using TypeLogMsgParams = std::pair, std::string>; + /** This pass translates all occuarence of log_msg function with non-flattend arguments into set of the flatten calls of log_smg. @@ -20,8 +22,10 @@ class FlattenLogMsg : public Transform { const IR::Node* postorder(IR::MethodCallStatement* methodCallStatement) override; protected: - std::pair, std::string> unfoldStruct(const IR::Expression* expr, - const IR::Type_StructLike* typeStruct, std::string& strParam); + TypeLogMsgParams unfoldStruct(const IR::Expression* expr, std::string strParam, + std::string curName = ""); + const IR::Type_StructLike* generateNewStructType(const IR::Type_StructLike* structType, + IR::IndexedVector &v); }; } // namespace P4 From 5acb02b637e847037cf4d98828377db7d830c42f Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 15 Feb 2022 17:35:51 +0200 Subject: [PATCH 04/17] refactoring --- midend/flattenLogMsg.cpp | 106 +++++++++++++++++++-------------------- midend/flattenLogMsg.h | 3 +- 2 files changed, 55 insertions(+), 54 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index 8ae25e8b46..f20aea2150 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -7,61 +7,51 @@ FlattenLogMsg::FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) : refMap(refMap), typeMap(typeMap) { } -const IR::Node* FlattenLogMsg::preorder(IR::BlockStatement* blockStatement) { - IR::IndexedVector components; - for (auto i : blockStatement->components) { - FlattenLogMsg flattenLogMsg(refMap, typeMap); - auto* newStatement = i->apply(flattenLogMsg); - if (auto* block = newStatement->to()) { - components.insert(components.end(), block->components.begin(), - block->components.end()); - } else { - components.push_back(newStatement->to()); - } - } - auto* block = blockStatement->clone(); - block->components = components; - return block; -} - TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::string strParam, std::string curName) { TypeLogMsgParams result; - if (auto structType = expr->type->to()) { - result.second += "("; - for (auto field : structType->fields) { - std::string nm = curName + std::string("."); - nm += field->name.name + std::string(" : "); - auto* newMember = new IR::Member(field->type, expr, field->name); - if (field->type->is()) { - auto curResult = unfoldStruct(newMember, strParam, nm); - nm += curResult.second; - result.first.insert(result.first.end(), curResult.first.begin(), - curResult.first.end()); - } else { - nm += "{}"; - result.first.push_back(new IR::NamedExpression(expr->srcInfo, IR::ID(nm), - newMember)); + auto* exprType = typeMap->getType(expr, true); + if (!expr->is()) { + std::cout << exprType << std::endl; + if (auto structType = exprType->to()) { + result.second += "("; + for (auto field : structType->fields) { + std::string nm = field->name.name + std::string(":"); + std::cout << expr << ":" << typeMap->getType(expr) << std::endl; + auto* newMember = new IR::Member(field->type, expr, field->name); + if (field->type->is()) { + auto curResult = unfoldStruct(newMember, strParam, field->name.name.c_str()); + nm += curResult.second; + result.first.insert(result.first.end(), curResult.first.begin(), + curResult.first.end()); + } else { + result.first.push_back(new IR::NamedExpression(expr->srcInfo, newName(), + newMember)); + nm += std::string("{}"); + } + if (result.second.length() > 1) + result.second += ","; + result.second += nm; } - result.second += nm + std::string(") "); + result.second += std::string(")"); + return result; } - return result; - } - if (!expr->is()) { - result.first.push_back(new IR::NamedExpression(expr->srcInfo, IR::ID(curName), expr)); + result.first.push_back(new IR::NamedExpression(expr->srcInfo, newName(), expr)); result.second = curName + std::string(" : {}"); return result; } auto* structExpr = expr->to(); std::string strResult; for (auto namedExpr : structExpr->components) { - std::cout << namedExpr->name << ":" << namedExpr->expression << ":" << namedExpr->expression->type->node_type_name() << std::endl; + std::cout << namedExpr->name << ":" << namedExpr->expression << ":" << namedExpr->expression->node_type_name() << std::endl; size_t n = strParam.find("{}"); if (n != std::string::npos) { strResult += strParam.substr(0, n); strParam = strParam.substr(n + 2); } - if (namedExpr->expression->type->is()) { + exprType = typeMap->getType(namedExpr->expression, true); + std::cout << exprType << std::endl; + if (exprType->is()) { std::string nm; if (curName.length()) { nm = curName + std::string("."); @@ -69,32 +59,32 @@ TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::st nm += namedExpr->name.name.c_str(); auto innerFields = unfoldStruct(namedExpr->expression, "", nm); result.first.insert(result.first.end(), innerFields.first.begin(), innerFields.first.end()); - strResult += "("; strResult += innerFields.second; - strResult += ")"; } else { strResult += "{}"; - result.first.push_back(namedExpr); + result.first.push_back( + new IR::NamedExpression(namedExpr->srcInfo, newName(), namedExpr->expression)); } } - result.second = strResult; + result.second = strResult + strParam; return result; } +IR::ID FlattenLogMsg::newName() { + std::ostringstream ostr; + ostr << "f" << index++; + return IR::ID(ostr.str()); +} + const IR::Type_StructLike* FlattenLogMsg::generateNewStructType( const IR::Type_StructLike* structType, IR::IndexedVector &v) { IR::IndexedVector fields; - size_t index = 1; for (auto namedExpr : v) { - //StructField(Util::SourceInfo srcInfo, IR::ID name, const IR::Type* type); - std::string nm = std::string("f") + std::to_string(index++); - fields.push_back(new IR::StructField(namedExpr->srcInfo, IR::ID(nm), + fields.push_back(new IR::StructField(namedExpr->srcInfo, namedExpr->name, namedExpr->expression->type)); } - auto* newStructType = structType->clone(); - newStructType->fields = fields; - newStructType->name.name = newStructType->name.name + cstring("_1"); - return newStructType; + return new IR::Type_Struct(structType->srcInfo, + IR::ID(refMap->newName(structType->name.originalName)), fields); } const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { @@ -105,6 +95,7 @@ const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStat if (!param1->is() || !param2->is()) { return methodCallStatement; } + std::cout << "call : " << methodCallStatement << std::endl; std::string strParam1 = param1->to()->value.c_str(); auto* argType = typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); @@ -113,6 +104,7 @@ const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStat std::cout << methodCallStatement->methodCall->arguments->at(0)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(0)->expression->type << std::endl; std::cout << methodCallStatement->methodCall->arguments->at(1)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; auto* structType = argType->to(); + index = 0; auto exprVector = unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, strParam1); @@ -132,15 +124,23 @@ const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStat newArgument->expression = newString; newArguments->at(0) = newArgument; newArgument = newMethodCall->arguments->at(1)->clone(); - auto newStructExpression = newArgument->expression->to()->clone(); - newStructExpression->type = structType; + auto* oldType = newArgument->expression->to()->structType; + auto newStructExpression =new IR::StructExpression(oldType->srcInfo, structType, + new IR::Type_Name(structType->name), exprVector.first); newStructExpression->components = exprVector.first; + typeMap->setType(structType, structType); + typeMap->setType(newStructExpression, structType); + typeMap->setType(new IR::Type_Name(structType->name), structType); + refMap->setDeclaration(new IR::Path(structType->name), structType); newArgument->expression = newStructExpression; newArguments->at(1) = newArgument; + std::cout << newArguments->at(1)->expression->type << std::endl; newMethodCall->arguments = newArguments; + std::cout << newMethodCall->arguments->at(1)->expression->type << std::endl; auto* newMethodCallStatement = methodCallStatement->clone(); newMethodCallStatement->methodCall = newMethodCall; std::cout << "new st : " << newMethodCallStatement << std::endl; + std::cout << newMethodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; return newMethodCallStatement; } } diff --git a/midend/flattenLogMsg.h b/midend/flattenLogMsg.h index fd3bef474d..f92429e8b1 100644 --- a/midend/flattenLogMsg.h +++ b/midend/flattenLogMsg.h @@ -15,10 +15,10 @@ set of the flatten calls of log_smg. class FlattenLogMsg : public Transform { P4::ReferenceMap* refMap; P4::TypeMap* typeMap; + size_t index; public: FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap); - const IR::Node* preorder(IR::BlockStatement* blockStatement) override; const IR::Node* postorder(IR::MethodCallStatement* methodCallStatement) override; protected: @@ -26,6 +26,7 @@ class FlattenLogMsg : public Transform { std::string curName = ""); const IR::Type_StructLike* generateNewStructType(const IR::Type_StructLike* structType, IR::IndexedVector &v); + IR::ID newName(); }; } // namespace P4 From e20297c36bb02a5b130efe3f0230c3ccce875cc5 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 17 Feb 2022 17:13:33 +0200 Subject: [PATCH 05/17] Implementation finished, left : integration tests with behavioral_model --- midend/flattenLogMsg.cpp | 205 ++++++++++++++++++++++++--------------- midend/flattenLogMsg.h | 80 ++++++++++++--- 2 files changed, 195 insertions(+), 90 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index f20aea2150..b3b42e1cf1 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -3,21 +3,101 @@ namespace P4 { -FlattenLogMsg::FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) : - refMap(refMap), typeMap(typeMap) { +const IR::Type_StructLike* FindTypeInLogMsgForReplace::hasStructInParameter( + const IR::MethodCallStatement* methodCallStatement) { + if (auto* path = methodCallStatement->methodCall->method->to()) { + if (path->path->name.name == "log_msg") { + auto* param1 = methodCallStatement->methodCall->arguments->at(0)->expression; + auto* param2 = methodCallStatement->methodCall->arguments->at(1)->expression; + if (!param1->is() || !param2->is()) { + return nullptr; + } + auto* type = + typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); + if (auto* typeStruct = type->to()) { + for (auto field : typeStruct->fields) { + if (field->type->is()) { + return typeStruct; + } + } + } + } + } + return nullptr; +} + +const IR::MethodCallStatement* FindTypeInLogMsgForReplace::prepareLogMsgStatement( + const IR::MethodCallStatement* methodCallStatement) { + if (auto* newMethod = getReplacementMethodCall(methodCallStatement->id)) { + return newMethod; + } + // Create new statement + auto* param1 = methodCallStatement->methodCall->arguments->at(0)->expression; + std::string strParam1 = param1->to()->value.c_str(); + auto* argType = + typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); + auto* structType = argType->to(); + index = 0; + auto exprVector = + unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, strParam1); + structType = generateNewStructType(structType, exprVector.first); + auto* newMethodCall = methodCallStatement->methodCall->clone(); + auto* newTypeArguments = newMethodCall->typeArguments->clone(); + newTypeArguments->clear(); + newTypeArguments->push_back(structType); + newMethodCall->typeArguments = newTypeArguments; + auto* newArguments = newMethodCall->arguments->clone(); + auto* newArgument = newMethodCall->arguments->at(0)->clone(); + auto* newString = newArgument->expression->to()->clone(); + newString->value = exprVector.second; + newArgument->expression = newString; + newArguments->at(0) = newArgument; + newArgument = newMethodCall->arguments->at(1)->clone(); + auto* oldType = newArgument->expression->to()->structType; + auto newStructExpression =new IR::StructExpression(oldType->srcInfo, structType, + structType->getP4Type()->template to(), exprVector.first); + newStructExpression->components = exprVector.first; + typeMap->setType(structType, structType); + typeMap->setType(newStructExpression, structType); + newArgument->expression = newStructExpression; + newArguments->at(1) = newArgument; + newMethodCall->arguments = newArguments; + auto* newMethodCallStatement = methodCallStatement->clone(); + newMethodCallStatement->methodCall = newMethodCall; + logMsgReplacament.emplace(methodCallStatement->clone_id, newMethodCallStatement); + return newMethodCallStatement; +} + + +IR::ID FindTypeInLogMsgForReplace::newName() { + std::ostringstream ostr; + ostr << "f" << index++; + return IR::ID(ostr.str()); +} + +const IR::Type_StructLike* FindTypeInLogMsgForReplace::generateNewStructType( + const IR::Type_StructLike* structType, IR::IndexedVector &v) { + IR::IndexedVector fields; + for (auto namedExpr : v) { + auto* structField = new IR::StructField(namedExpr->srcInfo, namedExpr->name, + namedExpr->expression->type); + typeMap->setType(structField, structField->type); + fields.push_back(structField); + } + auto* newType = structType->clone(); + newType->fields = fields; + return newType; } -TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::string strParam, - std::string curName) { +TypeLogMsgParams FindTypeInLogMsgForReplace::unfoldStruct(const IR::Expression* expr, + std::string strParam, std::string curName) { TypeLogMsgParams result; auto* exprType = typeMap->getType(expr, true); if (!expr->is()) { - std::cout << exprType << std::endl; if (auto structType = exprType->to()) { result.second += "("; for (auto field : structType->fields) { std::string nm = field->name.name + std::string(":"); - std::cout << expr << ":" << typeMap->getType(expr) << std::endl; auto* newMember = new IR::Member(field->type, expr, field->name); if (field->type->is()) { auto curResult = unfoldStruct(newMember, strParam, field->name.name.c_str()); @@ -43,14 +123,12 @@ TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::st auto* structExpr = expr->to(); std::string strResult; for (auto namedExpr : structExpr->components) { - std::cout << namedExpr->name << ":" << namedExpr->expression << ":" << namedExpr->expression->node_type_name() << std::endl; size_t n = strParam.find("{}"); if (n != std::string::npos) { strResult += strParam.substr(0, n); - strParam = strParam.substr(n + 2); + strParam = strParam.substr(n + 2); } exprType = typeMap->getType(namedExpr->expression, true); - std::cout << exprType << std::endl; if (exprType->is()) { std::string nm; if (curName.length()) { @@ -58,7 +136,8 @@ TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::st } nm += namedExpr->name.name.c_str(); auto innerFields = unfoldStruct(namedExpr->expression, "", nm); - result.first.insert(result.first.end(), innerFields.first.begin(), innerFields.first.end()); + result.first.insert(result.first.end(), innerFields.first.begin(), + innerFields.first.end()); strResult += innerFields.second; } else { strResult += "{}"; @@ -70,80 +149,48 @@ TypeLogMsgParams FlattenLogMsg::unfoldStruct(const IR::Expression* expr, std::st return result; } -IR::ID FlattenLogMsg::newName() { - std::ostringstream ostr; - ostr << "f" << index++; - return IR::ID(ostr.str()); +bool FindTypeInLogMsgForReplace::preorder(const IR::MethodCallStatement* methodCallStatement) { + if (hasStructInParameter(methodCallStatement)) { + auto* newMethodCall = prepareLogMsgStatement(methodCallStatement); + createReplacement(newMethodCall->methodCall->typeArguments->at(0)-> + to()); + } + return false; } -const IR::Type_StructLike* FlattenLogMsg::generateNewStructType( - const IR::Type_StructLike* structType, IR::IndexedVector &v) { - IR::IndexedVector fields; - for (auto namedExpr : v) { - fields.push_back(new IR::StructField(namedExpr->srcInfo, namedExpr->name, - namedExpr->expression->type)); +void FindTypeInLogMsgForReplace::createReplacement(const IR::Type_StructLike* type) { + if (replacement.count(type->name)) { + return; } - return new IR::Type_Struct(structType->srcInfo, - IR::ID(refMap->newName(structType->name.originalName)), fields); + replacement.emplace(type->name, type); } -const IR::Node* FlattenLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { - if (auto* path = methodCallStatement->methodCall->method->to()) { - if (path->path->name.name == "log_msg") { - auto* param1 = methodCallStatement->methodCall->arguments->at(0)->expression; - auto* param2 = methodCallStatement->methodCall->arguments->at(1)->expression; - if (!param1->is() || !param2->is()) { - return methodCallStatement; - } - std::cout << "call : " << methodCallStatement << std::endl; - std::string strParam1 = param1->to()->value.c_str(); - auto* argType = - typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); - std::cout << argType << " : " << argType->node_type_name() << std::endl; - if (argType->is()) { - std::cout << methodCallStatement->methodCall->arguments->at(0)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(0)->expression->type << std::endl; - std::cout << methodCallStatement->methodCall->arguments->at(1)->expression->node_type_name() << " : " << methodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; - auto* structType = argType->to(); - index = 0; - auto exprVector = - unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, - strParam1); - if (structType->fields.size() == exprVector.first.size()) { - return methodCallStatement; - } - structType = generateNewStructType(structType, exprVector.first); - auto* newMethodCall = methodCallStatement->methodCall->clone(); - auto* newTypeArguments = newMethodCall->typeArguments->clone(); - newTypeArguments->clear(); - newTypeArguments->push_back(structType); - newMethodCall->typeArguments = newTypeArguments; - auto* newArguments = newMethodCall->arguments->clone(); - auto* newArgument = newMethodCall->arguments->at(0)->clone(); - auto* newString = newArgument->expression->to()->clone(); - newString->value = exprVector.second; - newArgument->expression = newString; - newArguments->at(0) = newArgument; - newArgument = newMethodCall->arguments->at(1)->clone(); - auto* oldType = newArgument->expression->to()->structType; - auto newStructExpression =new IR::StructExpression(oldType->srcInfo, structType, - new IR::Type_Name(structType->name), exprVector.first); - newStructExpression->components = exprVector.first; - typeMap->setType(structType, structType); - typeMap->setType(newStructExpression, structType); - typeMap->setType(new IR::Type_Name(structType->name), structType); - refMap->setDeclaration(new IR::Path(structType->name), structType); - newArgument->expression = newStructExpression; - newArguments->at(1) = newArgument; - std::cout << newArguments->at(1)->expression->type << std::endl; - newMethodCall->arguments = newArguments; - std::cout << newMethodCall->arguments->at(1)->expression->type << std::endl; - auto* newMethodCallStatement = methodCallStatement->clone(); - newMethodCallStatement->methodCall = newMethodCall; - std::cout << "new st : " << newMethodCallStatement << std::endl; - std::cout << newMethodCallStatement->methodCall->arguments->at(1)->expression->type << std::endl; - return newMethodCallStatement; - } - } +///////////////////////////////// + +const IR::Node* ReplaceLogMsg::preorder(IR::P4Program* program) { + if (findTypeInLogMsgForReplace->empty()) { + // nothing to do + prune(); + } + return program; +} + +const IR::Node* ReplaceLogMsg::postorder(IR::Type_Struct* typeStruct) { + auto canon = typeMap->getTypeType(getOriginal(), true); + auto name = canon->to()->name; + auto repl = findTypeInLogMsgForReplace->getReplacement(name); + if (repl != nullptr) { + LOG3("Replace " << typeStruct << " with " << repl); + BUG_CHECK(repl->is(), "%1% not a struct", typeStruct); + return repl; + } + return typeStruct; +} + +const IR::Node* ReplaceLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { + if (auto* newMethod = + findTypeInLogMsgForReplace->getReplacementMethodCall(methodCallStatement->clone_id)) { + return newMethod; } return methodCallStatement; } diff --git a/midend/flattenLogMsg.h b/midend/flattenLogMsg.h index f92429e8b1..d299362262 100644 --- a/midend/flattenLogMsg.h +++ b/midend/flattenLogMsg.h @@ -8,27 +8,85 @@ namespace P4 { using TypeLogMsgParams = std::pair, std::string>; -/** -This pass translates all occuarence of log_msg function with non-flattend arguments into -set of the flatten calls of log_smg. +/* + Find types in log_msg function for replace. */ -class FlattenLogMsg : public Transform { - P4::ReferenceMap* refMap; - P4::TypeMap* typeMap; - size_t index; +class FindTypeInLogMsgForReplace : public Inspector { + P4::TypeMap* typeMap; + ordered_map replacement; + ordered_map logMsgReplacament; + size_t index; public: - FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap); - const IR::Node* postorder(IR::MethodCallStatement* methodCallStatement) override; + explicit FindTypeInLogMsgForReplace(P4::TypeMap *typeMap) : typeMap(typeMap) { + setName("FindTypeInLogMsgForReplace"); + CHECK_NULL(typeMap); + } + bool preorder(const IR::MethodCallStatement* methodCallStatement) override; + void createReplacement(const IR::Type_StructLike* type); + const IR::MethodCallStatement* prepareLogMsgStatement( + const IR::MethodCallStatement* methodCallStatement); + const IR::Type_StructLike* getReplacement(const cstring name) const { + return ::get(replacement, name); } + const IR::MethodCallStatement* getReplacementMethodCall(unsigned id) const { + return ::get(logMsgReplacament, id); + } + bool empty() const { return replacement.empty(); } + const IR::Type_StructLike* hasStructInParameter( + const IR::MethodCallStatement* methodCallStatement); protected: TypeLogMsgParams unfoldStruct(const IR::Expression* expr, std::string strParam, - std::string curName = ""); + std::string curName = ""); const IR::Type_StructLike* generateNewStructType(const IR::Type_StructLike* structType, - IR::IndexedVector &v); + IR::IndexedVector &v); IR::ID newName(); }; +/** +This pass translates all occuarence of log_msg function with non-flattend arguments into +set of the flatten calls of log_smg. +For example, +struct alt_t { + bit<1> valid; + bit<7> port; +} +... +t : slt_t; +... +log_msg("t={}", {t}); + +The flattened log_msg is shown below. + +log_msg("t=(valid:{},port:{})", {t.valid, t.port}); +*/ +class ReplaceLogMsg : public Transform, P4WriteContext { + P4::TypeMap* typeMap; + FindTypeInLogMsgForReplace* findTypeInLogMsgForReplace; + public: + explicit ReplaceLogMsg(P4::TypeMap* typeMap, + FindTypeInLogMsgForReplace* findTypeInLogMsgForReplace) + : typeMap(typeMap), findTypeInLogMsgForReplace(findTypeInLogMsgForReplace) { + CHECK_NULL(typeMap); CHECK_NULL(findTypeInLogMsgForReplace); + setName("ReplaceLogMsg"); + } + const IR::Node* preorder(IR::P4Program* program); + const IR::Node* postorder(IR::MethodCallStatement* methodCallStatement) override; + const IR::Node* postorder(IR::Type_Struct* typeStruct) override; +}; + +class FlattenLogMsg final : public PassManager { + public: + FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) { + auto findTypeInLogMsgForReplace = new FindTypeInLogMsgForReplace(typeMap); + passes.push_back(new TypeChecking(refMap, typeMap)); + passes.push_back(findTypeInLogMsgForReplace); + passes.push_back(new ReplaceLogMsg(typeMap, findTypeInLogMsgForReplace)); + passes.push_back(new ClearTypeMap(typeMap)); + setName("FlattenLogMsg"); + } +}; + } // namespace P4 #endif /* _MIDEND_FLATTENILOGMSG_H_ */ \ No newline at end of file From 45852776ab47f9240933bc4dc59d0160959217d6 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 17 Feb 2022 17:14:25 +0200 Subject: [PATCH 06/17] implementation was finished --- backends/bmv2/simple_switch/simpleSwitch.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 9afa86e3fc..68ad9f6556 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -859,7 +859,8 @@ Util::IJson* ExternConverter_log_msg::convertExternFunction( auto arr = new Util::JsonArray(); for (auto v : le->components) { auto tf = ctxt->typeMap->getType(v); - if (!tf->is() && !tf->is()) { + if (!tf->is() && !tf->is() && + !tf->is()) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: only integral values supported for logged values", mc); return primitive; From 8d33056fc1d5a081d13623597abdad4bcbb735d7 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 18 Feb 2022 17:07:48 +0200 Subject: [PATCH 07/17] restore --- backends/bmv2/simple_switch/simpleSwitch.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 68ad9f6556..9afa86e3fc 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -859,8 +859,7 @@ Util::IJson* ExternConverter_log_msg::convertExternFunction( auto arr = new Util::JsonArray(); for (auto v : le->components) { auto tf = ctxt->typeMap->getType(v); - if (!tf->is() && !tf->is() && - !tf->is()) { + if (!tf->is() && !tf->is()) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: only integral values supported for logged values", mc); return primitive; From 9e8b84afb465735035960e8c2f0ffa5b3af1f92a Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Mon, 21 Feb 2022 17:25:01 +0200 Subject: [PATCH 08/17] add elimination of errors --- backends/bmv2/simple_switch/simpleSwitch.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 9afa86e3fc..1ad49df08d 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -24,6 +24,7 @@ limitations under the License. #include "backends/bmv2/common/annotations.h" #include "frontends/p4/fromv1.0/v1model.h" #include "frontends/p4/cloner.h" +#include "midend/convertErrors.h" #include "midend/flattenLogMsg.h" #include "simpleSwitch.h" #include "backends/bmv2/simple_switch/options.h" @@ -36,6 +37,21 @@ using BMV2::stringRepr; namespace BMV2 { +/** +This class implements a policy suitable for the ConvertErrors pass. +The policy is: convert all errors to specified width +*/ +class ErrorWidth : public P4::ChooseErrorRepresentation { + unsigned width; + bool convert(const IR::Type_Error *) const override { + return true; + } + + unsigned errorSize(unsigned) const override { return width;} + public: + explicit ErrorWidth(unsigned width): width(width) {} +}; + void ParseV1Architecture::modelError(const char* format, const IR::Node* node) { ::error(ErrorType::ERR_MODEL, (cstring(format) + "\nAre you using an up-to-date v1model.p4?").c_str(), node); @@ -1153,6 +1169,8 @@ SimpleSwitchBackend::convert(const IR::ToplevelBlock* tlb) { new ParseAnnotations(), }); } + auto convertErrors = + new P4::ConvertErrors(refMap, typeMap, new ErrorWidth(16)); simplify.addPasses({ // Because --fromJSON flag is used, input sources are empty // and ParseAnnotations should be skipped @@ -1170,6 +1188,8 @@ SimpleSwitchBackend::convert(const IR::ToplevelBlock* tlb) { new ProcessControls(&structure->pipeline_controls)), new P4::SimplifyControlFlow(refMap, typeMap), new P4::RemoveAllUnusedDeclarations(refMap), + convertErrors, + new P4::EliminateSerEnums(refMap, typeMap), new P4::FlattenLogMsg(refMap, typeMap), // Converts the DAG into a TREE (at least for expressions) // This is important later for conversion to JSON. From 8735fbf0043f99ba88960aa691c926c4ecd3a64b Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Mon, 21 Feb 2022 17:33:00 +0200 Subject: [PATCH 09/17] add header --- backends/bmv2/simple_switch/simpleSwitch.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 1ad49df08d..2a027101b0 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -25,6 +25,7 @@ limitations under the License. #include "frontends/p4/fromv1.0/v1model.h" #include "frontends/p4/cloner.h" #include "midend/convertErrors.h" +#include "midend/eliminateSerEnums.h" #include "midend/flattenLogMsg.h" #include "simpleSwitch.h" #include "backends/bmv2/simple_switch/options.h" From 0a6ee7e79e125c196f19f5dfaba2d9740d3c5850 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Mon, 28 Feb 2022 13:06:21 +0200 Subject: [PATCH 10/17] add stf test --- testdata/p4_16_samples/issue1062-1-bmv2_0.stf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 testdata/p4_16_samples/issue1062-1-bmv2_0.stf diff --git a/testdata/p4_16_samples/issue1062-1-bmv2_0.stf b/testdata/p4_16_samples/issue1062-1-bmv2_0.stf new file mode 100644 index 0000000000..1ca8b89703 --- /dev/null +++ b/testdata/p4_16_samples/issue1062-1-bmv2_0.stf @@ -0,0 +1,13 @@ +# STF test for /home/vpeschax/networking.switching.barefoot.bf-p4c-tools/res/issue1062-1-bmv2 +# p4testgen seed: 1000 + +# Traces +# p: [Parser] p +# [State] start +# [Event]: Extract Reject +# [Event]: Extract Cond: p4t*zombie.const.0.*packetLen_bits >= 48; +# [Expression]: Invalid emit: h.h.*valid;: = 0; +# [Event]: Prepending the emit buffer to the program packet. + +packet 0 00000000 +expect 0 00000000$ From 4188fbee27aa50a795d1ae9a1502ab4cfdefb182 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Mon, 28 Feb 2022 18:50:21 +0200 Subject: [PATCH 11/17] update failed tests --- backends/bmv2/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/backends/bmv2/CMakeLists.txt b/backends/bmv2/CMakeLists.txt index ceb0d59099..269d43b64f 100644 --- a/backends/bmv2/CMakeLists.txt +++ b/backends/bmv2/CMakeLists.txt @@ -164,7 +164,6 @@ set (XFAIL_TESTS testdata/p4_16_samples/issue986-bmv2.p4 # These tests use a table key with type 'error' testdata/p4_16_samples/issue1062-bmv2.p4 - testdata/p4_16_samples/issue1062-1-bmv2.p4 # This test uses an undefined extern testdata/p4_16_samples/issue1193-bmv2.p4 # This test also uses a custom extern @@ -182,8 +181,6 @@ set (XFAIL_TESTS testdata/p4_16_samples/issue1882-bmv2.p4 testdata/p4_16_samples/issue1882-1-bmv2.p4 testdata/p4_16_samples/issue2664-bmv2.p4 - # This one uses arguments of incorrect types to log_msg - testdata/p4_16_samples/issue2201-bmv2.p4 ) set (BMV2_PARSER_INLINE_TESTS "${P4C_SOURCE_DIR}/testdata/p4_16_samples/parser-inline/*.p4") From 3a96a0831d57dd77f688135697b7de1d6dd6f7de Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 1 Mar 2022 14:40:34 +0200 Subject: [PATCH 12/17] remove elimination of errors --- backends/bmv2/simple_switch/simpleSwitch.cpp | 24 ++------------------ 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/backends/bmv2/simple_switch/simpleSwitch.cpp b/backends/bmv2/simple_switch/simpleSwitch.cpp index 2a027101b0..dddce6ef4b 100644 --- a/backends/bmv2/simple_switch/simpleSwitch.cpp +++ b/backends/bmv2/simple_switch/simpleSwitch.cpp @@ -24,8 +24,6 @@ limitations under the License. #include "backends/bmv2/common/annotations.h" #include "frontends/p4/fromv1.0/v1model.h" #include "frontends/p4/cloner.h" -#include "midend/convertErrors.h" -#include "midend/eliminateSerEnums.h" #include "midend/flattenLogMsg.h" #include "simpleSwitch.h" #include "backends/bmv2/simple_switch/options.h" @@ -38,21 +36,6 @@ using BMV2::stringRepr; namespace BMV2 { -/** -This class implements a policy suitable for the ConvertErrors pass. -The policy is: convert all errors to specified width -*/ -class ErrorWidth : public P4::ChooseErrorRepresentation { - unsigned width; - bool convert(const IR::Type_Error *) const override { - return true; - } - - unsigned errorSize(unsigned) const override { return width;} - public: - explicit ErrorWidth(unsigned width): width(width) {} -}; - void ParseV1Architecture::modelError(const char* format, const IR::Node* node) { ::error(ErrorType::ERR_MODEL, (cstring(format) + "\nAre you using an up-to-date v1model.p4?").c_str(), node); @@ -876,7 +859,8 @@ Util::IJson* ExternConverter_log_msg::convertExternFunction( auto arr = new Util::JsonArray(); for (auto v : le->components) { auto tf = ctxt->typeMap->getType(v); - if (!tf->is() && !tf->is()) { + if (!tf->is() && !tf->is() && + !tf->is()) { ::error(ErrorType::ERR_UNSUPPORTED_ON_TARGET, "%1%: only integral values supported for logged values", mc); return primitive; @@ -1170,8 +1154,6 @@ SimpleSwitchBackend::convert(const IR::ToplevelBlock* tlb) { new ParseAnnotations(), }); } - auto convertErrors = - new P4::ConvertErrors(refMap, typeMap, new ErrorWidth(16)); simplify.addPasses({ // Because --fromJSON flag is used, input sources are empty // and ParseAnnotations should be skipped @@ -1189,8 +1171,6 @@ SimpleSwitchBackend::convert(const IR::ToplevelBlock* tlb) { new ProcessControls(&structure->pipeline_controls)), new P4::SimplifyControlFlow(refMap, typeMap), new P4::RemoveAllUnusedDeclarations(refMap), - convertErrors, - new P4::EliminateSerEnums(refMap, typeMap), new P4::FlattenLogMsg(refMap, typeMap), // Converts the DAG into a TREE (at least for expressions) // This is important later for conversion to JSON. From 7fcc7ee9ed924d028ea1508abb349f6cf2e3ec36 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Tue, 1 Mar 2022 16:40:09 +0200 Subject: [PATCH 13/17] add support for errors --- backends/bmv2/common/control.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backends/bmv2/common/control.h b/backends/bmv2/common/control.h index 6c14f94e69..c418e80419 100644 --- a/backends/bmv2/common/control.h +++ b/backends/bmv2/common/control.h @@ -61,9 +61,10 @@ class ControlConverter : public Inspector { for (auto ke : key->keyElements) { auto expr = ke->expression; auto ket = ctxt->typeMap->getType(expr, true); - if (!ket->is() && !ket->is()) + if (!ket->is() && !ket->is() && + !ket->is()) ::error(ErrorType::ERR_UNSUPPORTED, "%1%: unsupporded key type %2%. " - "Supported key types are be bit<> or boolean.", expr, ket); + "Supported key types are be bit<> or boolean, or error.", expr, ket); auto match_type = getKeyMatchType(ke); if (match_type == BMV2::MatchImplementation::selectorMatchTypeName) From 22fb575d52c525e0239bd4081cf041752a5a38fa Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 3 Mar 2022 12:52:55 +0200 Subject: [PATCH 14/17] changes according review --- midend/flattenLogMsg.cpp | 41 ++++++++++++++++++++-------------------- midend/flattenLogMsg.h | 30 +++++++++++++++-------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index b3b42e1cf1..34049bac21 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -3,30 +3,31 @@ namespace P4 { -const IR::Type_StructLike* FindTypeInLogMsgForReplace::hasStructInParameter( +bool FindTypesInLogMsgInvocationToReplace::hasStructInParameter( const IR::MethodCallStatement* methodCallStatement) { if (auto* path = methodCallStatement->methodCall->method->to()) { - if (path->path->name.name == "log_msg") { + if (methodCallStatement->methodCall->arguments->size() == 2 && + path->path->name.name == "log_msg") { auto* param1 = methodCallStatement->methodCall->arguments->at(0)->expression; auto* param2 = methodCallStatement->methodCall->arguments->at(1)->expression; if (!param1->is() || !param2->is()) { - return nullptr; + return false; } auto* type = typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); if (auto* typeStruct = type->to()) { for (auto field : typeStruct->fields) { if (field->type->is()) { - return typeStruct; + return true; } } } } } - return nullptr; + return false; } -const IR::MethodCallStatement* FindTypeInLogMsgForReplace::prepareLogMsgStatement( +const IR::MethodCallStatement* FindTypesInLogMsgInvocationToReplace::prepareLogMsgStatement( const IR::MethodCallStatement* methodCallStatement) { if (auto* newMethod = getReplacementMethodCall(methodCallStatement->id)) { return newMethod; @@ -36,7 +37,7 @@ const IR::MethodCallStatement* FindTypeInLogMsgForReplace::prepareLogMsgStatemen std::string strParam1 = param1->to()->value.c_str(); auto* argType = typeMap->getTypeType(methodCallStatement->methodCall->typeArguments->at(0), true); - auto* structType = argType->to(); + auto* structType = argType->checkedTo(); index = 0; auto exprVector = unfoldStruct(methodCallStatement->methodCall->arguments->at(1)->expression, strParam1); @@ -48,8 +49,7 @@ const IR::MethodCallStatement* FindTypeInLogMsgForReplace::prepareLogMsgStatemen newMethodCall->typeArguments = newTypeArguments; auto* newArguments = newMethodCall->arguments->clone(); auto* newArgument = newMethodCall->arguments->at(0)->clone(); - auto* newString = newArgument->expression->to()->clone(); - newString->value = exprVector.second; + auto* newString = new IR::StringLiteral(newArgument->expression->srcInfo, exprVector.second); newArgument->expression = newString; newArguments->at(0) = newArgument; newArgument = newMethodCall->arguments->at(1)->clone(); @@ -57,25 +57,23 @@ const IR::MethodCallStatement* FindTypeInLogMsgForReplace::prepareLogMsgStatemen auto newStructExpression =new IR::StructExpression(oldType->srcInfo, structType, structType->getP4Type()->template to(), exprVector.first); newStructExpression->components = exprVector.first; - typeMap->setType(structType, structType); - typeMap->setType(newStructExpression, structType); newArgument->expression = newStructExpression; newArguments->at(1) = newArgument; newMethodCall->arguments = newArguments; auto* newMethodCallStatement = methodCallStatement->clone(); newMethodCallStatement->methodCall = newMethodCall; - logMsgReplacament.emplace(methodCallStatement->clone_id, newMethodCallStatement); + logMsgReplacement.emplace(getOriginal()->id, newMethodCallStatement); return newMethodCallStatement; } -IR::ID FindTypeInLogMsgForReplace::newName() { +IR::ID FindTypesInLogMsgInvocationToReplace::newName() { std::ostringstream ostr; ostr << "f" << index++; return IR::ID(ostr.str()); } -const IR::Type_StructLike* FindTypeInLogMsgForReplace::generateNewStructType( +const IR::Type_StructLike* FindTypesInLogMsgInvocationToReplace::generateNewStructType( const IR::Type_StructLike* structType, IR::IndexedVector &v) { IR::IndexedVector fields; for (auto namedExpr : v) { @@ -89,7 +87,7 @@ const IR::Type_StructLike* FindTypeInLogMsgForReplace::generateNewStructType( return newType; } -TypeLogMsgParams FindTypeInLogMsgForReplace::unfoldStruct(const IR::Expression* expr, +TypeLogMsgParams FindTypesInLogMsgInvocationToReplace::unfoldStruct(const IR::Expression* expr, std::string strParam, std::string curName) { TypeLogMsgParams result; auto* exprType = typeMap->getType(expr, true); @@ -127,6 +125,8 @@ TypeLogMsgParams FindTypeInLogMsgForReplace::unfoldStruct(const IR::Expression* if (n != std::string::npos) { strResult += strParam.substr(0, n); strParam = strParam.substr(n + 2); + } else { + BUG("Can't find '{}' in '%1%'", expr); } exprType = typeMap->getType(namedExpr->expression, true); if (exprType->is()) { @@ -149,7 +149,8 @@ TypeLogMsgParams FindTypeInLogMsgForReplace::unfoldStruct(const IR::Expression* return result; } -bool FindTypeInLogMsgForReplace::preorder(const IR::MethodCallStatement* methodCallStatement) { +bool FindTypesInLogMsgInvocationToReplace::preorder( + const IR::MethodCallStatement* methodCallStatement) { if (hasStructInParameter(methodCallStatement)) { auto* newMethodCall = prepareLogMsgStatement(methodCallStatement); createReplacement(newMethodCall->methodCall->typeArguments->at(0)-> @@ -158,7 +159,7 @@ bool FindTypeInLogMsgForReplace::preorder(const IR::MethodCallStatement* methodC return false; } -void FindTypeInLogMsgForReplace::createReplacement(const IR::Type_StructLike* type) { +void FindTypesInLogMsgInvocationToReplace::createReplacement(const IR::Type_StructLike* type) { if (replacement.count(type->name)) { return; } @@ -168,7 +169,7 @@ void FindTypeInLogMsgForReplace::createReplacement(const IR::Type_StructLike* ty ///////////////////////////////// const IR::Node* ReplaceLogMsg::preorder(IR::P4Program* program) { - if (findTypeInLogMsgForReplace->empty()) { + if (findTypesInLogMsgInvocationToReplace->empty()) { // nothing to do prune(); } @@ -178,7 +179,7 @@ const IR::Node* ReplaceLogMsg::preorder(IR::P4Program* program) { const IR::Node* ReplaceLogMsg::postorder(IR::Type_Struct* typeStruct) { auto canon = typeMap->getTypeType(getOriginal(), true); auto name = canon->to()->name; - auto repl = findTypeInLogMsgForReplace->getReplacement(name); + auto repl = findTypesInLogMsgInvocationToReplace->getReplacement(name); if (repl != nullptr) { LOG3("Replace " << typeStruct << " with " << repl); BUG_CHECK(repl->is(), "%1% not a struct", typeStruct); @@ -189,7 +190,7 @@ const IR::Node* ReplaceLogMsg::postorder(IR::Type_Struct* typeStruct) { const IR::Node* ReplaceLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { if (auto* newMethod = - findTypeInLogMsgForReplace->getReplacementMethodCall(methodCallStatement->clone_id)) { + findTypesInLogMsgInvocationToReplace->getReplacementMethodCall(methodCallStatement->clone_id)) { return newMethod; } return methodCallStatement; diff --git a/midend/flattenLogMsg.h b/midend/flattenLogMsg.h index d299362262..3b239c2d37 100644 --- a/midend/flattenLogMsg.h +++ b/midend/flattenLogMsg.h @@ -11,15 +11,16 @@ using TypeLogMsgParams = std::pair, std:: /* Find types in log_msg function for replace. */ -class FindTypeInLogMsgForReplace : public Inspector { +class FindTypesInLogMsgInvocationToReplace : public Inspector { P4::TypeMap* typeMap; ordered_map replacement; - ordered_map logMsgReplacament; + // Map with new log_msg methods where is each key is a original identifier of IR::Node. + ordered_map logMsgReplacement; size_t index; public: - explicit FindTypeInLogMsgForReplace(P4::TypeMap *typeMap) : typeMap(typeMap) { - setName("FindTypeInLogMsgForReplace"); + explicit FindTypesInLogMsgInvocationToReplace(P4::TypeMap *typeMap) : typeMap(typeMap) { + setName("FindTypesInLogMsgInvocationToReplace"); CHECK_NULL(typeMap); } bool preorder(const IR::MethodCallStatement* methodCallStatement) override; @@ -29,11 +30,10 @@ class FindTypeInLogMsgForReplace : public Inspector { const IR::Type_StructLike* getReplacement(const cstring name) const { return ::get(replacement, name); } const IR::MethodCallStatement* getReplacementMethodCall(unsigned id) const { - return ::get(logMsgReplacament, id); + return ::get(logMsgReplacement, id); } bool empty() const { return replacement.empty(); } - const IR::Type_StructLike* hasStructInParameter( - const IR::MethodCallStatement* methodCallStatement); + bool hasStructInParameter(const IR::MethodCallStatement* methodCallStatement); protected: TypeLogMsgParams unfoldStruct(const IR::Expression* expr, std::string strParam, @@ -62,12 +62,13 @@ log_msg("t=(valid:{},port:{})", {t.valid, t.port}); */ class ReplaceLogMsg : public Transform, P4WriteContext { P4::TypeMap* typeMap; - FindTypeInLogMsgForReplace* findTypeInLogMsgForReplace; + FindTypesInLogMsgInvocationToReplace* findTypesInLogMsgInvocationToReplace; public: explicit ReplaceLogMsg(P4::TypeMap* typeMap, - FindTypeInLogMsgForReplace* findTypeInLogMsgForReplace) - : typeMap(typeMap), findTypeInLogMsgForReplace(findTypeInLogMsgForReplace) { - CHECK_NULL(typeMap); CHECK_NULL(findTypeInLogMsgForReplace); + FindTypesInLogMsgInvocationToReplace* findTypesInLogMsgInvocationToReplace) + : typeMap(typeMap), + findTypesInLogMsgInvocationToReplace(findTypesInLogMsgInvocationToReplace) { + CHECK_NULL(typeMap); CHECK_NULL(findTypesInLogMsgInvocationToReplace); setName("ReplaceLogMsg"); } const IR::Node* preorder(IR::P4Program* program); @@ -78,10 +79,11 @@ class ReplaceLogMsg : public Transform, P4WriteContext { class FlattenLogMsg final : public PassManager { public: FlattenLogMsg(P4::ReferenceMap* refMap, P4::TypeMap* typeMap) { - auto findTypeInLogMsgForReplace = new FindTypeInLogMsgForReplace(typeMap); + auto findTypesInLogMsgInvocationToReplace = + new FindTypesInLogMsgInvocationToReplace(typeMap); passes.push_back(new TypeChecking(refMap, typeMap)); - passes.push_back(findTypeInLogMsgForReplace); - passes.push_back(new ReplaceLogMsg(typeMap, findTypeInLogMsgForReplace)); + passes.push_back(findTypesInLogMsgInvocationToReplace); + passes.push_back(new ReplaceLogMsg(typeMap, findTypesInLogMsgInvocationToReplace)); passes.push_back(new ClearTypeMap(typeMap)); setName("FlattenLogMsg"); } From afc5b5f479916c2a6e9c2c33f49299a36c805644 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 3 Mar 2022 13:47:05 +0200 Subject: [PATCH 15/17] bug of cpplint was fixed --- midend/flattenLogMsg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index 34049bac21..16eaf82ee8 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -189,8 +189,8 @@ const IR::Node* ReplaceLogMsg::postorder(IR::Type_Struct* typeStruct) { } const IR::Node* ReplaceLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { - if (auto* newMethod = - findTypesInLogMsgInvocationToReplace->getReplacementMethodCall(methodCallStatement->clone_id)) { + if (auto* newMethod = findTypesInLogMsgInvocationToReplace-> + getReplacementMethodCall(methodCallStatement->clone_id)) { return newMethod; } return methodCallStatement; From 3f70c29dcb620abb1ae2a82da1b8136f8eec263d Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Thu, 3 Mar 2022 15:36:21 +0200 Subject: [PATCH 16/17] fixing a bug --- midend/flattenLogMsg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index 16eaf82ee8..9da0b79f93 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -190,7 +190,7 @@ const IR::Node* ReplaceLogMsg::postorder(IR::Type_Struct* typeStruct) { const IR::Node* ReplaceLogMsg::postorder(IR::MethodCallStatement* methodCallStatement) { if (auto* newMethod = findTypesInLogMsgInvocationToReplace-> - getReplacementMethodCall(methodCallStatement->clone_id)) { + getReplacementMethodCall(getOriginal()->id)) { return newMethod; } return methodCallStatement; From e24b50c2820ce25dfd6fe2e993a3d1d44ca31070 Mon Sep 17 00:00:00 2001 From: VolodymyrPeschanenkoIntel Date: Fri, 4 Mar 2022 12:05:11 +0200 Subject: [PATCH 17/17] remove bug generation if {} was not found --- midend/flattenLogMsg.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/midend/flattenLogMsg.cpp b/midend/flattenLogMsg.cpp index 9da0b79f93..55e11e9c7d 100644 --- a/midend/flattenLogMsg.cpp +++ b/midend/flattenLogMsg.cpp @@ -125,8 +125,6 @@ TypeLogMsgParams FindTypesInLogMsgInvocationToReplace::unfoldStruct(const IR::Ex if (n != std::string::npos) { strResult += strParam.substr(0, n); strParam = strParam.substr(n + 2); - } else { - BUG("Can't find '{}' in '%1%'", expr); } exprType = typeMap->getType(namedExpr->expression, true); if (exprType->is()) {