From 3c47c146731db8a1fe50e899c26e879931473378 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 29 Nov 2022 16:19:43 +0530 Subject: [PATCH 1/2] done --- .gitignore | 1 + integration_tests/CMakeLists.txt | 25 +++++++++---- .../test_c_custom_postprocessor.py | 9 +++++ src/bin/lpython.cpp | 36 ++++++++++++++++++- src/libasr/utils.h | 1 + 5 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 integration_tests/test_c_custom_postprocessor.py diff --git a/.gitignore b/.gitignore index da0bcebc84..3bb974d953 100644 --- a/.gitignore +++ b/.gitignore @@ -217,3 +217,4 @@ integration_tests/array_02_decl integration_tests/array_02_decl.c integration_tests/expr_12 integration_tests/expr_12.c +integration_tests/expr_07_generated.c diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 726c555dbd..d950d9927d 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -46,12 +46,13 @@ message("LPYTHON_RTLIB_LIBRARY: ${LPYTHON_RTLIB_LIBRARY}") macro(RUN) set(options FAIL) - set(oneValueArgs NAME IMPORT_PATH) + set(oneValueArgs NAME IMPORT_PATH CUSTOM_C_POSTPROCESSOR) set(multiValueArgs LABELS EXTRAFILES) cmake_parse_arguments(RUN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) set(name ${RUN_NAME}) set(import_path ${RUN_IMPORT_PATH}) + set(custom_c_postprocessor ${RUN_CUSTOM_C_POSTPROCESSOR}) if (NOT name) message(FATAL_ERROR "Must specify the NAME argument") endif() @@ -82,11 +83,20 @@ macro(RUN) set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE) endif() elseif(KIND STREQUAL "c") - add_custom_command( - OUTPUT ${name}.c - COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py > ${name}.c - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py - VERBATIM) + if (custom_c_postprocessor) + add_custom_command( + OUTPUT ${name}.c + COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + --custom-c-postprocessor ${CMAKE_CURRENT_SOURCE_DIR}/${custom_c_postprocessor} > ${name}.c + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + VERBATIM) + else () + add_custom_command( + OUTPUT ${name}.c + COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py > ${name}.c + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py + VERBATIM) + endif() add_executable(${name} ${name}.c ${RUN_EXTRAFILES}) set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C) target_link_libraries(${name} lpython_rtlib) @@ -209,7 +219,8 @@ RUN(NAME expr_03 LABELS cpython llvm c wasm) RUN(NAME expr_04 LABELS cpython llvm c) RUN(NAME expr_05 LABELS cpython llvm c) RUN(NAME expr_06 LABELS cpython llvm c) -RUN(NAME expr_07 LABELS cpython llvm c) +RUN(NAME expr_07 CUSTOM_C_POSTPROCESSOR test_c_custom_postprocessor.py + LABELS cpython llvm c) RUN(NAME expr_08 LABELS llvm c) RUN(NAME expr_09 LABELS cpython llvm c) RUN(NAME expr_10 LABELS cpython llvm c) diff --git a/integration_tests/test_c_custom_postprocessor.py b/integration_tests/test_c_custom_postprocessor.py new file mode 100644 index 0000000000..8525d0a7cc --- /dev/null +++ b/integration_tests/test_c_custom_postprocessor.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + +import sys + +filename = sys.argv[1] + +f = open(filename).read() + +open(filename, "w").write(f) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 53248156e7..7b689858a2 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -60,6 +60,12 @@ std::string remove_extension(const std::string& filename) { return filename.substr(0, lastdot); } +std::string extract_extension(const std::string& filename) { + size_t lastdot = filename.find_last_of("."); + if (lastdot == std::string::npos) return ""; + return filename.substr(lastdot); +} + std::string remove_path(const std::string& filename) { size_t lastslash = filename.find_last_of("/"); if (lastslash == std::string::npos) return filename; @@ -289,7 +295,22 @@ int emit_c(const std::string &infile, LFORTRAN_ASSERT(diagnostics.has_error()) return 3; } - std::cout << res.result; + if( !compiler_options.c_postprocessor_script.empty() ) { + std::string ccode_file = remove_extension(infile) + "_generated.c"; + std::ofstream ccode_out(ccode_file); + ccode_out << res.result; + std::string command = "python " + compiler_options.c_postprocessor_script + " " + ccode_file; + system(command.c_str()); + ccode_out.close(); + std::ifstream ccode_in(ccode_file); + std::string modified_result = ""; + while( std::getline(ccode_in, modified_result) ) { + std::cout << modified_result << "\n"; + } + ccode_in.close(); + } else { + std::cout << res.result; + } return 0; } @@ -1297,6 +1318,7 @@ int main(int argc, char *argv[]) bool show_errors = false; bool with_intrinsic_modules = false; std::string arg_pass; + std::string script_path; bool arg_no_color = false; bool show_llvm = false; bool show_asm = false; @@ -1363,6 +1385,7 @@ int main(int argc, char *argv[]) app.add_flag("--indent", compiler_options.indent, "Indented print ASR/AST"); app.add_flag("--tree", compiler_options.tree, "Tree structure print ASR/AST"); app.add_option("--pass", arg_pass, "Apply the ASR pass and show ASR (implies --show-asr)"); + app.add_option("--custom-c-postprocessor", script_path, "The script for processing the C code generated by --show-c command."); app.add_flag("--disable-main", compiler_options.disable_main, "Do not generate any code for the `main` function"); app.add_flag("--symtab-only", compiler_options.symtab_only, "Only create symbol tables in ASR (skip executable stmt)"); app.add_flag("--time-report", time_report, "Show compilation time report"); @@ -1485,6 +1508,17 @@ int main(int argc, char *argv[]) return 1; } + if( !script_path.empty() && extract_extension(script_path) != ".py" ) { + std::cerr << "Only a Python script is supported as a postprocessor for generated C code." << std::endl; + return 1; + } + + if( !script_path.empty() && !LFortran::path_exists(script_path) ) { + std::cerr << script_path << " is inaccessible or doesn't exist on your system." << std::endl; + return 1; + } + + compiler_options.c_postprocessor_script = script_path; if (arg_backend == "llvm") { backend = Backend::llvm; } else if (arg_backend == "cpp") { diff --git a/src/libasr/utils.h b/src/libasr/utils.h index bdec5e00fb..95b8d42a58 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -52,6 +52,7 @@ struct CompilerOptions { bool emit_debug_info = false; bool emit_debug_line_column = false; std::string import_path = ""; + std::string c_postprocessor_script = ""; Platform platform; CompilerOptions () : platform{get_platform()} {}; From 004a1af901078e7ebe324ca9bd0db441afba074a Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Mon, 5 Dec 2022 11:22:46 +0530 Subject: [PATCH 2/2] Write to a file if -o provided --show-c option --- .gitignore | 6 ++++ integration_tests/CMakeLists.txt | 4 +-- .../test_c_custom_postprocessor.py | 8 +++-- src/bin/lpython.cpp | 33 +++++++++++++------ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 3bb974d953..8112fcc926 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,9 @@ integration_tests/array_02_decl.c integration_tests/expr_12 integration_tests/expr_12.c integration_tests/expr_07_generated.c +integration_tests/expr_07.c +expr_07.c +tests/c_interop1.c +tests/expr7.c +tests/loop1.c +tests/loop2.c diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index d950d9927d..57f5103a42 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -87,13 +87,13 @@ macro(RUN) add_custom_command( OUTPUT ${name}.c COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py - --custom-c-postprocessor ${CMAKE_CURRENT_SOURCE_DIR}/${custom_c_postprocessor} > ${name}.c + --custom-c-postprocessor ${CMAKE_CURRENT_SOURCE_DIR}/${custom_c_postprocessor} -o ${name}.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py VERBATIM) else () add_custom_command( OUTPUT ${name}.c - COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py > ${name}.c + COMMAND lpython --show-c ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py -o ${name}.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py VERBATIM) endif() diff --git a/integration_tests/test_c_custom_postprocessor.py b/integration_tests/test_c_custom_postprocessor.py index 8525d0a7cc..b43df435c1 100644 --- a/integration_tests/test_c_custom_postprocessor.py +++ b/integration_tests/test_c_custom_postprocessor.py @@ -4,6 +4,10 @@ filename = sys.argv[1] -f = open(filename).read() +file = open(filename, "r") +f = file.read() +file.close() -open(filename, "w").write(f) +file = open(filename, "w") +file.write(f) +file.close() diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 7b689858a2..2089cfc2e4 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -295,21 +295,34 @@ int emit_c(const std::string &infile, LFORTRAN_ASSERT(diagnostics.has_error()) return 3; } + + std::string output_file; + bool print_to_std = true; + if( !compiler_options.arg_o.empty() ) { + output_file = compiler_options.arg_o; + print_to_std = false; + } else { + output_file = remove_extension(infile) + ".c"; + } + std::string ccode_file = output_file; + std::ofstream ccode_out(ccode_file); + ccode_out << res.result; + ccode_out.close(); if( !compiler_options.c_postprocessor_script.empty() ) { - std::string ccode_file = remove_extension(infile) + "_generated.c"; - std::ofstream ccode_out(ccode_file); - ccode_out << res.result; std::string command = "python " + compiler_options.c_postprocessor_script + " " + ccode_file; system(command.c_str()); - ccode_out.close(); - std::ifstream ccode_in(ccode_file); - std::string modified_result = ""; - while( std::getline(ccode_in, modified_result) ) { - std::cout << modified_result << "\n"; + if( print_to_std ) { + std::ifstream ccode_in(ccode_file); + std::string modified_result = ""; + while( std::getline(ccode_in, modified_result) ) { + std::cout << modified_result << "\n"; + } + ccode_in.close(); } - ccode_in.close(); } else { - std::cout << res.result; + if( print_to_std ) { + std::cout << res.result; + } } return 0; }