diff --git a/pinpoint/CMakeLists.txt b/pinpoint/CMakeLists.txt index 3ff5228..b6711c4 100644 --- a/pinpoint/CMakeLists.txt +++ b/pinpoint/CMakeLists.txt @@ -9,3 +9,4 @@ message(STATUS "GCC plugin path: ${GCC_PLUGIN_PATH}") target_include_directories(spslr_pinpoint PRIVATE ${GCC_PLUGIN_PATH}/include ${CMAKE_CURRENT_SOURCE_DIR}/safegcc ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(stage0) +add_subdirectory(stage1) diff --git a/pinpoint/pinpoint.cpp b/pinpoint/pinpoint.cpp index 863ade2..e812438 100644 --- a/pinpoint/pinpoint.cpp +++ b/pinpoint/pinpoint.cpp @@ -4,6 +4,7 @@ #include #include +#include int plugin_is_GPL_compatible; @@ -26,7 +27,14 @@ int plugin_init(struct plugin_name_args* plugin_info, struct plugin_gcc_version* separate_offset_pass_info.pos_op = PASS_POS_INSERT_AFTER; register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &separate_offset_pass_info); - // Stage 1 -> TODO + // Stage 1 -> stage 0 separators are replaced with inline assembly + + struct register_pass_info asm_offset_pass_info; + asm_offset_pass_info.pass = new asm_offset_pass(nullptr); + asm_offset_pass_info.ref_pass_instance_number = 1; + asm_offset_pass_info.reference_pass_name = "separate_offset"; + asm_offset_pass_info.pos_op = PASS_POS_INSERT_AFTER; + register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &asm_offset_pass_info); return 0; } diff --git a/pinpoint/safegcc/safe-gimple.h b/pinpoint/safegcc/safe-gimple.h index ad6e0a9..9181c77 100644 --- a/pinpoint/safegcc/safe-gimple.h +++ b/pinpoint/safegcc/safe-gimple.h @@ -1,4 +1,5 @@ #include +#include #ifndef SAFEGCC_GIMPLE_H #define SAFEGCC_GIMPLE_H diff --git a/pinpoint/stage0/separator.cpp b/pinpoint/stage0/separator.cpp index 39b22bb..b940411 100644 --- a/pinpoint/stage0/separator.cpp +++ b/pinpoint/stage0/separator.cpp @@ -1,5 +1,6 @@ #include #include +#include static tree separator_decl = NULL_TREE; @@ -62,8 +63,40 @@ gimple* make_stage0_gimple_separator(tree lhs, UID target, std::size_t offset) { return call; } -bool is_stage0_separator(gimple* stmt, UID& target, std::size_t& offset) { - // TODO - return false; +static bool decl_is_separator(tree fndecl) { + if (!fndecl) + return false; + + tree name_tree = DECL_NAME(fndecl); + if (!name_tree) + return false; + + const char* name = IDENTIFIER_POINTER(name_tree); + if (!name) + return false; + + return strcmp(name, SPSLR_PINPOINT_STAGE0_SEPARATOR) == 0; +} + +bool is_stage0_separator(gimple* stmt, UID& target, std::size_t& offset) { + if (!stmt || !is_gimple_call(stmt)) + return false; + + tree fndecl = gimple_call_fndecl(stmt); + if (!decl_is_separator(fndecl)) + return false; + + tree arg0 = gimple_call_arg (stmt, 0); + tree arg1 = gimple_call_arg (stmt, 1); + + if (!arg0 || TREE_CODE(arg0) != INTEGER_CST) + pinpoint_fatal("is_state0_separator failed to get target UID from separator"); + + if (!arg1 || TREE_CODE(arg1) != INTEGER_CST) + pinpoint_fatal("is_state0_separator failed to get field offset from separator"); + + target = static_cast(tree_to_uhwi(arg0)); + offset = static_cast(tree_to_uhwi(arg1)); + return true; } diff --git a/pinpoint/stage1/CMakeLists.txt b/pinpoint/stage1/CMakeLists.txt new file mode 100644 index 0000000..88aeb12 --- /dev/null +++ b/pinpoint/stage1/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(spslr_pinpoint PRIVATE asm_offset_pass.cpp) +target_include_directories(spslr_pinpoint PRIVATE .) diff --git a/pinpoint/stage1/asm_offset_pass.cpp b/pinpoint/stage1/asm_offset_pass.cpp new file mode 100644 index 0000000..399fb23 --- /dev/null +++ b/pinpoint/stage1/asm_offset_pass.cpp @@ -0,0 +1,31 @@ +#include +#include + +static void separator_assemble_maybe(gimple_stmt_iterator* gsi) { + // TODO +} + +static const pass_data asm_offset_pass_data = { + GIMPLE_PASS, + "asm_offset", + OPTGROUP_NONE, + TV_NONE, + 0,0,0,0, + TODO_update_ssa +}; + +asm_offset_pass::asm_offset_pass(gcc::context* ctxt) : gimple_opt_pass(asm_offset_pass_data, ctxt) {} + +unsigned int asm_offset_pass::execute(function* fn) { + if (!fn) + return 0; + + basic_block bb; + FOR_EACH_BB_FN(bb, fn) { + for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + separator_assemble_maybe(&gsi); + } + + return 0; +} + diff --git a/pinpoint/stage1/stage1.h b/pinpoint/stage1/stage1.h new file mode 100644 index 0000000..b6d9236 --- /dev/null +++ b/pinpoint/stage1/stage1.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct asm_offset_pass : gimple_opt_pass { + asm_offset_pass(gcc::context* ctxt); + unsigned int execute(function* fn) override; +};