From 6b280e477f09bfc16c47b3044522a1d25c07c23c Mon Sep 17 00:00:00 2001 From: "Efimov Alexander/AI Tools Lab/./Samsung Electronics" Date: Wed, 26 Dec 2018 23:30:54 +0300 Subject: [PATCH] [nnc] Add more tests for acl dom to text operations (#2719) Tested entities: - ArtifactIndex - ArtifactRet - ArtifactBreak - ArtifactCont - ArtifactVariable - ArtifactBlock - ArtifactForLoop - ArtifactIf - ArtifactFunction - ArtifactClassVariable - ArtifactClassFunction - ArtifactClass - ArtifactModule Signed-off-by: Efimov Alexander --- .../acl_soft_backend/ArtifactGeneratorCppCode.cpp | 3 + .../acl_soft_backend/ArtifactGeneratorCppDecl.cpp | 2 + contrib/nnc/unittests/acl_backend/CMakeLists.txt | 7 +- contrib/nnc/unittests/acl_backend/DOMToText.cpp | 281 +++++++++++++++++++-- 4 files changed, 265 insertions(+), 28 deletions(-) diff --git a/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp b/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp index 44fb100..d81fdf9 100644 --- a/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp +++ b/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppCode.cpp @@ -184,6 +184,7 @@ void ArtifactGeneratorCppCode::visit(const ArtifactIf* node) { } void ArtifactGeneratorCppCode::visit(const ArtifactFunction* node) { + // TODO implement this function } void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) { @@ -203,6 +204,8 @@ void ArtifactGeneratorCppCode::visit(const ArtifactClass* node) { } } + //TODO add constructors of public variables + node->getConstrBlock()->accept(this); _out << endl; diff --git a/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp b/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp index a65d0b4..d415f48 100644 --- a/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp +++ b/contrib/nnc/passes/acl_soft_backend/ArtifactGeneratorCppDecl.cpp @@ -119,6 +119,8 @@ void ArtifactGeneratorCppDecl::visit(const ArtifactClass* node) { if (!node->privateFunctions().empty()) _out << endl; + // TODO add public variables + for (auto e : node->privateVariables()) { _out << _ind; e->accept(this); diff --git a/contrib/nnc/unittests/acl_backend/CMakeLists.txt b/contrib/nnc/unittests/acl_backend/CMakeLists.txt index afc430b..012ae37 100644 --- a/contrib/nnc/unittests/acl_backend/CMakeLists.txt +++ b/contrib/nnc/unittests/acl_backend/CMakeLists.txt @@ -1,8 +1,11 @@ set(ACL_CPP_BACKEND_UTEST_SOURCES DOMToText.cpp MIRToDOM.cpp) -add_nnc_unit_test(nnc_acl_cpp_backend_test ${ACL_CPP_BACKEND_UTEST_SOURCES} ${OPTIONS_SRC}) +file(GLOB_RECURSE ACL_IN_SOURCES "${NNC_ACL_BACKEND_DIR}/*.in") +make_generated_sources("${ACL_IN_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR} ACL_GENERATED_SOURCES) + +add_nnc_unit_test(nnc_acl_cpp_backend_test ${ACL_CPP_BACKEND_UTEST_SOURCES} ${OPTIONS_SRC} ${ACL_GENERATED_SOURCES}) if (TARGET nnc_acl_cpp_backend_test) nncc_target_link_libraries(nnc_acl_cpp_backend_test nnc_core nnc_support acl_soft_backend_cpp) - target_include_directories(nnc_acl_cpp_backend_test PRIVATE ${NNC_ACL_BACKEND_DIR}) + target_include_directories(nnc_acl_cpp_backend_test PRIVATE ${NNC_ACL_BACKEND_DIR} ${CMAKE_CURRENT_BINARY_DIR}) endif() diff --git a/contrib/nnc/unittests/acl_backend/DOMToText.cpp b/contrib/nnc/unittests/acl_backend/DOMToText.cpp index ee52b3a..d071a01 100644 --- a/contrib/nnc/unittests/acl_backend/DOMToText.cpp +++ b/contrib/nnc/unittests/acl_backend/DOMToText.cpp @@ -27,6 +27,8 @@ #include "ArtifactGeneratorCppCode.h" #include "ArtifactGeneratorCppDecl.h" +#include "AclArtifactUtilities.generated.h" + #include "gtest/gtest.h" using namespace std; @@ -203,54 +205,281 @@ TEST(acl_backend_dom_to_text, ArtifactBinaryExpr) { } } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactIndex) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactIndex) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* arr_name = "a"; + const char* idx_name = "b"; + shared_ptr arr = AF::id(arr_name); + shared_ptr idx = AF::id(idx_name); + shared_ptr indexing = AF::ind(arr, idx); + indexing->accept(&code_gen); + ASSERT_EQ(code_out.str(), "a[b]"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactRet) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactRet) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* result_name = "a"; + shared_ptr result = AF::id(result_name); + ArtifactRet ret(result); + ret.accept(&code_gen); + ASSERT_EQ(code_out.str(), "return a"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactBreak) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactBreak) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactBreak brk; + brk.accept(&code_gen); + ASSERT_EQ(code_out.str(), "break"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactCont) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactCont) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactCont cont; + cont.accept(&code_gen); + ASSERT_EQ(code_out.str(), "continue"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactVariable) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactVariable) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* var_type = "int"; + const char* var_name = "data"; + shared_ptr dim1 = AF::lit("2"); + shared_ptr dim2 = AF::lit("3"); + list> dims{dim1, dim2}; + list> initializers{AF::lit("123")}; + shared_ptr var_decl = AF::var(var_type, var_name, dims, initializers); + var_decl->accept(&code_gen); + // TODO generate initializers in braces + ASSERT_EQ(code_out.str(), "int data[2][3](123)"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactBlock) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactBlock) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* var_name = "var"; + const char* lit_val = "123"; + + shared_ptr id = AF::id(var_name); + shared_ptr lit = AF::lit(lit_val); + const list> args{id, lit}; + + shared_ptr call = AF::call("foo", args); + + ArtifactBlock block; + + block.addStatement(call); + + block.accept(&code_gen); + ASSERT_EQ(code_out.str(), " {\n foo(var, 123);\n}\n"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactForLoop) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactForLoop) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* var_name = "i"; + const char* var_type = "int"; + + shared_ptr iter = AF::var(var_type, var_name, {}, {AF::lit("0")}); + shared_ptr step = AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1")); + shared_ptr cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); + + shared_ptr expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); + + ArtifactForLoop loop(iter, cond, step); + + loop.getBlock()->addStatement(expr); + + loop.accept(&code_gen); + ASSERT_EQ(code_out.str(), "for(int i(0); i <= 123; i += 1) {\n hello += world;\n}\n"); +} + +TEST(acl_backend_dom_to_text, ArtifactIf) { + stringstream code_out; + ArtifactGeneratorCppCode code_gen(code_out); + const char* var_name = "i"; + + shared_ptr cond = AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123")); + + shared_ptr expr = AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world")); + + ArtifactIf if_stmt(cond); + + if_stmt.getBlock()->addStatement(expr); + + if_stmt.accept(&code_gen); + ASSERT_EQ(code_out.str(), "if(i <= 123) {\n hello += world;\n}\n"); +} + +TEST(acl_backend_dom_to_text, ArtifactFunction) { + stringstream code_out; + stringstream decl_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactGeneratorCppDecl decl_gen(decl_out); + const char* ret_type = "int"; + const char* func_name = "foo"; + shared_ptr arg1 = AF::var("int", "a"); + shared_ptr arg2 = AF::var("bool", "b"); + list> args{arg1, arg2}; + + // test public class variable + ArtifactFunction func_decl(ret_type, func_name, args); + + func_decl.accept(&code_gen); + ASSERT_EQ(code_out.str(), ""); + func_decl.accept(&decl_gen); + + ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactIf) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactClassVariable) { + stringstream code_out; + stringstream decl_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactGeneratorCppDecl decl_gen(decl_out); + + const char* var_type = "int"; + const char* var_name = "data"; + + ArtifactClass cls("Class"); + + shared_ptr dim1 = AF::lit("2"); + shared_ptr dim2 = AF::lit("3"); + list> dims{dim1, dim2}; + list> list_of_initializer{AF::lit("123")}; + ArtifactClassVariable var_decl(&cls, var_type, var_name, dims, list_of_initializer); + + var_decl.accept(&code_gen); + ASSERT_EQ(code_out.str(), "data(123)"); + var_decl.accept(&decl_gen); + // fixme dimensions are not taken into account, remove ';' + ASSERT_EQ(decl_out.str(), "int data;\n"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactFunction) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactClassFunction) { + stringstream code_out; + stringstream decl_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactGeneratorCppDecl decl_gen(decl_out); + const char* ret_type = "int"; + const char* func_name = "foo"; + shared_ptr arg1 = AF::var("int", "a"); + shared_ptr arg2 = AF::var("bool", "b"); + list> args{arg1, arg2}; + + ArtifactClass cls("Class"); + + // test public class variable + shared_ptr cls_func_decl = cls.func(true, ret_type, func_name, args); + + cls_func_decl->accept(&code_gen); + // FIXME do not print new line in this visitor + ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n"); + cls_func_decl->accept(&decl_gen); + + ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n"); + + decl_out.str(""); + code_out.str(""); + + // test private class variable + cls_func_decl = cls.func(false, ret_type, func_name, args); + + cls_func_decl->accept(&code_gen); + // FIXME do not print new line in this visitor + ASSERT_EQ(code_out.str(), "int Class::foo(int a, bool b) {\n}\n\n"); + cls_func_decl->accept(&decl_gen); + + ASSERT_EQ(decl_out.str(), "int foo(int a, bool b);\n"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactClassVariable) { - //TODO +static shared_ptr createClsVariable(ArtifactClass& cls, + const char* var_name, + bool is_public) { + const char* var_type = "int"; + shared_ptr dim1 = AF::lit("2"); + shared_ptr dim2 = AF::lit("3"); + list> dims{dim1, dim2}; + list> initializers{AF::lit("123")}; + shared_ptr var_decl = + cls.var(is_public, var_type, var_name, dims, initializers); + return var_decl; } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactClassFunction) { - //TODO +static shared_ptr createClsFunction(ArtifactClass& cls, + const char* func_name, + bool is_public) { + const char* var_type = "int"; + const char* func_type = "void"; + shared_ptr var1 = AF::var(var_type, "a"); + shared_ptr var2 = AF::var(var_type, "b"); + list> args{var1, var2}; + shared_ptr func_decl = cls.func(is_public, func_type, func_name, args); + return func_decl; } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactClass) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactClass) { + stringstream code_out; + stringstream decl_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactGeneratorCppDecl decl_gen(decl_out); + + ArtifactClass cls("Class"); + + createClsFunction(cls, "public_foo", true); + createClsFunction(cls, "private_bar", false); + + createClsVariable(cls, "visible", true); + createClsVariable(cls, "invisible", false); + + // Test cpp file generation + cls.accept(&code_gen); + ASSERT_EQ(code_out.str(), "Class::Class() : invisible(123) {\n}\n\n" + "void Class::public_foo(int a, int b) {\n}\n\n" + "void Class::private_bar(int a, int b) {\n}\n\n"); + + // Test header file generation + cls.accept(&decl_gen); + + ASSERT_EQ(decl_out.str(), "class Class {\npublic:\n Class();\n" + " void public_foo(int a, int b);" + "\n\nprivate:\n void private_bar(int a, int b);\n\n" + " int invisible;\n};\n"); } -TEST(acl_backend_dom_to_text, DISABLED_ArtifactModule) { - //TODO +TEST(acl_backend_dom_to_text, ArtifactModule) { + stringstream code_out; + stringstream decl_out; + ArtifactGeneratorCppCode code_gen(code_out); + ArtifactGeneratorCppDecl decl_gen(decl_out); + + ArtifactModule m("module"); + + m.addHeaderInclude("foo.h"); + m.addHeaderSysInclude("vector"); + m.addSourceInclude("bar.h"); + m.addSourceSysInclude("list"); + + shared_ptr cls = m.createClass("Class"); + + // test cpp file generation + // We use snippet code to encode some common functions + // This snippet is wrapped in prefix and postfix code + const char* code_prefix = "#include \"module.h\"\n\n#include \n\n#include \"bar.h\"\n\n"; + const char* code_suffix = "\nClass::Class() {\n}\n\n"; + + string ref_data = string(code_prefix) + + string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix; + m.accept(&code_gen); + ASSERT_EQ(code_out.str(), ref_data); + + // test header code generation + const char* ref_decl_data = "#include \"foo.h\"\n#include \"vector\"\n\nclass Class {\npublic:\n Class();\n\nprivate:\n};\n"; + m.accept(&decl_gen); + + ASSERT_EQ(decl_out.str(), ref_decl_data); } -- 2.7.4