From 84a415830624e4bba9c618e7774feb855532af3b Mon Sep 17 00:00:00 2001 From: Nicholas Chaimov Date: Fri, 3 Jan 2025 15:32:23 -0800 Subject: [PATCH] Read file specific in $SALT_FORTRAN_SELECT_FILE in Flang plugin Read and parse select files. Not yet acting on the directives. --- CMakeLists.txt | 1 + include/selectfile.hpp | 2 +- src/salt_instrument_flang_plugin.cpp | 73 ++++++++++++++++++++-------- src/selectfile.cpp | 11 ++++- 4 files changed, 64 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 35a861c..06711b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,6 +284,7 @@ if(MLIR_FOUND AND Flang_FOUND) list(TRANSFORM SALT_FLANG_PLUGIN_HEADER_FILES PREPEND "${CMAKE_SOURCE_DIR}/include/") set(SALT_FLANG_PLUGIN_SRCS + selectfile.cpp salt_instrument_flang_plugin.cpp ) list(TRANSFORM SALT_FLANG_PLUGIN_SRCS PREPEND "${CMAKE_SOURCE_DIR}/src/") diff --git a/include/selectfile.hpp b/include/selectfile.hpp index 5b56759..a6b8124 100644 --- a/include/selectfile.hpp +++ b/include/selectfile.hpp @@ -72,6 +72,6 @@ extern std::list fileincludelist; extern std::list fileexcludelist; // void parseInstrumentationCommand(char *line, int lineno); -void processInstrumentationRequests(const char *fname); +bool processInstrumentationRequests(const char *fname); #endif diff --git a/src/salt_instrument_flang_plugin.cpp b/src/salt_instrument_flang_plugin.cpp index 83599b1..b844c0b 100644 --- a/src/salt_instrument_flang_plugin.cpp +++ b/src/salt_instrument_flang_plugin.cpp @@ -44,12 +44,16 @@ limitations under the License. #include "flang/Parser/source.h" #include "flang/Common/indirection.h" +#include "selectfile.hpp" + // TODO Split declarations into a separate header file. // TODO Put debug output behind verbose flag #define SALT_FORTRAN_CONFIG_FILE_VAR "SALT_FORTRAN_CONFIG_FILE" #define SALT_FORTRAN_CONFIG_DEFAULT_PATH "config_files/tau_config.yaml" +#define SALT_FORTRAN_SELECT_FILE_VAR "SALT_FORTRAN_SELECT_FILE" + #define SALT_FORTRAN_KEY "Fortran" #define SALT_FORTRAN_PROGRAM_BEGIN_KEY "program_insert" #define SALT_FORTRAN_PROCEDURE_BEGIN_KEY "procedure_begin_insert" @@ -68,11 +72,11 @@ using namespace Fortran::frontend; */ class SaltInstrumentAction final : public PluginParseTreeAction { enum class SaltInstrumentationPointType { - PROGRAM_BEGIN, // Declare profiler, initialize TAU, set node, start timer - PROCEDURE_BEGIN, // Declare profiler, start timer - PROCEDURE_END, // Stop timer on the line after - RETURN_STMT, // Stop timer on the line before - IF_RETURN // Transform if to if-then-endif, stop timer before return + PROGRAM_BEGIN, // Declare profiler, initialize TAU, set node, start timer + PROCEDURE_BEGIN, // Declare profiler, start timer + PROCEDURE_END, // Stop timer on the line after + RETURN_STMT, // Stop timer on the line before + IF_RETURN // Transform if to if-then-endif, stop timer before return }; using InstrumentationMap = std::map; @@ -219,7 +223,7 @@ class SaltInstrumentAction final : public PluginParseTreeAction { // for examples of getting source position for a parse tree node // Never descend into InterfaceSpecification nodes, they can't contain executable statements. - bool Pre(const Fortran::parser::InterfaceSpecification &) { return false; } + static bool Pre(const Fortran::parser::InterfaceSpecification &) { return false; } bool Pre(const Fortran::parser::MainProgram &) { isInMainProgram_ = true; @@ -572,18 +576,21 @@ class SaltInstrumentAction final : public PluginParseTreeAction { std::holds_alternative >(ifAction.statement.u)) { const auto startPos{ - locationFromSource(std::get(ifStmt.t).thing.thing.value().source, - false).value() + locationFromSource( + std::get(ifStmt.t).thing.thing.value().source, + false).value() }; const auto endPos{ - locationFromSource(std::get(ifStmt.t).thing.thing.value().source, - true).value() + locationFromSource( + std::get(ifStmt.t).thing.thing.value().source, + true).value() }; llvm::outs() << "If-return, conditional: (" << startPos.line << "," << startPos.column << ") - " - << "(" << endPos.line << "," << endPos.column << ")\n"; + << "(" << endPos.line << "," << endPos.column << ")\n"; // TODO this assumes that the conditional fits on one list // make more robust, test with more cases - addInstrumentationPoint(SaltInstrumentationPointType::IF_RETURN, startPos.line, std::nullopt, endPos.column); + addInstrumentationPoint(SaltInstrumentationPointType::IF_RETURN, startPos.line, std::nullopt, + endPos.column); } return true; } @@ -744,7 +751,7 @@ class SaltInstrumentAction final : public PluginParseTreeAction { } auto instIter{instPts.cbegin()}; - bool shouldOutputLine{true}; + bool shouldOutputLine{}; while (std::getline(inputStream, line)) { ++lineNum; shouldOutputLine = true; @@ -756,13 +763,13 @@ class SaltInstrumentAction final : public PluginParseTreeAction { // TODO handle multi-line // TODO handle line continuation if too long if (instIter->instrumentationPointType == SaltInstrumentationPointType::IF_RETURN) { - shouldOutputLine = false; - line.erase(instIter->conditionalColumn); - line.insert(instIter->conditionalColumn, " then"); - outputStream << line << "\n"; - outputStream << getInstrumentationPointString(*instIter, instMap) << "\n"; - outputStream << " return\n"; - outputStream << " endif\n"; + shouldOutputLine = false; + line.erase(instIter->conditionalColumn); + line.insert(instIter->conditionalColumn, " then"); + outputStream << line << "\n"; + outputStream << getInstrumentationPointString(*instIter, instMap) << "\n"; + outputStream << " return\n"; + outputStream << " endif\n"; } else { outputStream << getInstrumentationPointString(*instIter, instMap) << "\n"; } @@ -789,6 +796,15 @@ class SaltInstrumentAction final : public PluginParseTreeAction { return SALT_FORTRAN_CONFIG_DEFAULT_PATH; } + [[nodiscard]] static std::optional getSelectFilePath() { + if (const char *val = getenv(SALT_FORTRAN_SELECT_FILE_VAR)) { + if (std::string selectFile{val}; !selectFile.empty()) { + return selectFile; + } + } + return std::nullopt; + } + [[nodiscard]] static ryml::Tree getConfigYamlTree(const std::string &configPath) { std::ifstream inputStream{configPath}; if (!inputStream) { @@ -882,6 +898,23 @@ class SaltInstrumentAction final : public PluginParseTreeAction { const ryml::Tree yamlTree = getConfigYamlTree(configPath); const InstrumentationMap instMap = getInstrumentationMap(yamlTree); + if (const auto selectPath{getSelectFilePath()}; selectPath.has_value()) { + if (processInstrumentationRequests(selectPath->c_str())) { + const auto printStr = [&](const auto &a) { llvm::outs() << a << "\n"; }; + llvm::outs() << "File include list:\n"; + std::for_each(fileincludelist.cbegin(), fileincludelist.cend(), printStr); + llvm::outs() << "File exclude list:\n"; + std::for_each(fileexcludelist.cbegin(), fileexcludelist.cend(), printStr); + llvm::outs() << "Include list:\n"; + std::for_each(includelist.cbegin(), includelist.cend(), printStr); + llvm::outs() << "Exclude list:\n"; + std::for_each(excludelist.cbegin(), excludelist.cend(), printStr); + } else { + llvm::errs() << "ERROR: Unable to read selective instrumentation file at " << selectPath << "\n"; + std::exit(-4); + } + } + // Get the extension of the input file // For input file 'filename.ext' we will output to 'filename.inst.Ext' // Since we are adding preprocessor directives in the emitted code, diff --git a/src/selectfile.cpp b/src/selectfile.cpp index 49a4e8b..aa790dc 100644 --- a/src/selectfile.cpp +++ b/src/selectfile.cpp @@ -9,6 +9,10 @@ #include "selectfile.hpp" #include "dprint.hpp" +// TODO support all selective instrumentation types +// TODO refactor this to class instead of using global variables +// TODO modernize C++ + std::list excludelist; std::list includelist; std::list fileincludelist; @@ -684,7 +688,7 @@ void parseError(const char *message, char *line, int lineno, int column) #define SALT_UNUSED(expr) do { (void)(expr); } while (0) -void processInstrumentationRequests(const char *fname) +bool processInstrumentationRequests(const char *fname) { std::ifstream input(fname); @@ -695,7 +699,8 @@ void processInstrumentationRequests(const char *fname) if (!input) { - std::cerr << "ERROR: Cannot open file: " << fname << std::endl; + std::cerr << "ERROR: Cannot open selective instrumentation file: " << fname << std::endl; + return false; } @@ -883,4 +888,6 @@ void processInstrumentationRequests(const char *fname) DPRINT0("fileexcludelist\n"); dump_list(fileexcludelist); + + return true; }