Pinpoint plugin asm_offset pass - ssa trouble
This commit is contained in:
parent
6c1183edc5
commit
ef755456da
@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
#define SPSLR_ATTRIBUTE "spslr"
|
#define SPSLR_ATTRIBUTE "spslr"
|
||||||
#define SPSLR_PINPOINT_STAGE0_SEPARATOR "__spslr_offsetof"
|
#define SPSLR_PINPOINT_STAGE0_SEPARATOR "__spslr_offsetof"
|
||||||
|
#define SPSLR_PINPOINT_STAGE1_SEPARATOR "__spslr_pin" /* suffixed with "_<uid>" */
|
||||||
|
|||||||
@ -1,8 +1,95 @@
|
|||||||
#include <stage1.h>
|
#include <stage1.h>
|
||||||
#include <stage0.h>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <pinpoint_error.h>
|
||||||
|
#include <pinpoint_config.h>
|
||||||
|
|
||||||
|
static UID next_separator_uid = 0;
|
||||||
|
static std::unordered_map<UID, S1Separator> separators;
|
||||||
|
|
||||||
|
static char asm_str_buf[1024];
|
||||||
|
|
||||||
|
static const char* make_asm_noarch(UID uid) {
|
||||||
|
snprintf(asm_str_buf, sizeof(asm_str_buf), SPSLR_PINPOINT_STAGE1_SEPARATOR "_%lu:", uid);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* make_asm_x86_64(UID uid) {
|
||||||
|
// Asm has 1 output (%0) and 2 inputs for target (%1) and offset (%2)
|
||||||
|
snprintf(asm_str_buf, sizeof(asm_str_buf), SPSLR_PINPOINT_STAGE1_SEPARATOR "_%lu: mov %2, %0", uid);
|
||||||
|
return asm_str_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* make_asm(UID uid, S1Separator::ARCH& arch) {
|
||||||
|
#if defined(__x86_64__) || defined(__amd64__)
|
||||||
|
arch = S1Separator::X86_64;
|
||||||
|
return make_asm_x86_64(uid);
|
||||||
|
#else
|
||||||
|
arch = S1Separator::NONE;
|
||||||
|
return make_asm_noarch(uid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static tree make_asm_operand(const char* constraint_text, tree operand_tree) {
|
||||||
|
tree constraint_str = build_string(strlen (constraint_text) + 1, constraint_text);
|
||||||
|
tree inner_list = build_tree_list(integer_zero_node, constraint_str);
|
||||||
|
tree outer_list = build_tree_list(inner_list, operand_tree);
|
||||||
|
return outer_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gimple* make_stage1_separator(tree lhs, UID target, std::size_t offset) {
|
||||||
|
if (!lhs)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
UID uid = next_separator_uid++;
|
||||||
|
|
||||||
|
S1Separator separator;
|
||||||
|
separator.target = target;
|
||||||
|
separator.offset = offset;
|
||||||
|
|
||||||
|
const char* asm_str = make_asm(uid, separator.arch);
|
||||||
|
if (!asm_str)
|
||||||
|
pinpoint_fatal("make_stage1_separator failed to generate asm string");
|
||||||
|
|
||||||
|
tree arg0 = build_int_cst(size_type_node, target);
|
||||||
|
tree arg1 = build_int_cst(size_type_node, offset);
|
||||||
|
|
||||||
|
vec<tree, va_gc>* outputs = NULL;
|
||||||
|
vec<tree, va_gc>* inputs = NULL;
|
||||||
|
|
||||||
|
vec_safe_push(outputs, make_asm_operand("=r", lhs));
|
||||||
|
vec_safe_push(inputs, make_asm_operand("i", arg0));
|
||||||
|
vec_safe_push(inputs, make_asm_operand("i", arg1));
|
||||||
|
|
||||||
|
gasm* new_gasm = gimple_build_asm_vec(ggc_strdup(asm_str), inputs, outputs, NULL, NULL);
|
||||||
|
if (!new_gasm)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
SSA_NAME_DEF_STMT(lhs) = new_gasm;
|
||||||
|
|
||||||
|
separators.emplace(uid, separator);
|
||||||
|
return new_gasm;
|
||||||
|
}
|
||||||
|
|
||||||
static void separator_assemble_maybe(gimple_stmt_iterator* gsi) {
|
static void separator_assemble_maybe(gimple_stmt_iterator* gsi) {
|
||||||
// TODO
|
if (!gsi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gimple* stmt = gsi_stmt(*gsi);
|
||||||
|
if (!stmt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UID target;
|
||||||
|
std::size_t offset;
|
||||||
|
|
||||||
|
if (!is_stage0_separator(stmt, target, offset))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gimple* replacement = make_stage1_separator(gimple_call_lhs(stmt), target, offset);
|
||||||
|
if (!replacement)
|
||||||
|
pinpoint_fatal();
|
||||||
|
|
||||||
|
gsi_replace(gsi, replacement, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const pass_data asm_offset_pass_data = {
|
static const pass_data asm_offset_pass_data = {
|
||||||
|
|||||||
@ -1,7 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stage0.h>
|
||||||
#include <safe-gimple.h>
|
#include <safe-gimple.h>
|
||||||
|
|
||||||
|
struct S1Separator {
|
||||||
|
enum ARCH {
|
||||||
|
NONE, X86_64
|
||||||
|
} arch;
|
||||||
|
|
||||||
|
UID target;
|
||||||
|
std::size_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
struct asm_offset_pass : gimple_opt_pass {
|
struct asm_offset_pass : gimple_opt_pass {
|
||||||
asm_offset_pass(gcc::context* ctxt);
|
asm_offset_pass(gcc::context* ctxt);
|
||||||
unsigned int execute(function* fn) override;
|
unsigned int execute(function* fn) override;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
add_executable(subject main.c)
|
add_executable(subject main.c)
|
||||||
add_dependencies(subject spslr_pinpoint spslr_finalize spslr_selfpatch)
|
add_dependencies(subject spslr_pinpoint spslr_finalize spslr_selfpatch)
|
||||||
target_link_libraries(subject PRIVATE spslr_selfpatch)
|
target_link_libraries(subject PRIVATE spslr_selfpatch)
|
||||||
target_compile_options(subject PRIVATE -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset)
|
target_compile_options(subject PRIVATE -fplugin=$<TARGET_FILE:spslr_pinpoint> -fdump-tree-separate_offset -fdump-tree-asm_offset)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user