Pinpoint plugin update
This commit is contained in:
parent
bba1f15a97
commit
8d1bfb31a1
@ -9,6 +9,16 @@
|
|||||||
#include <plugin-version.h>
|
#include <plugin-version.h>
|
||||||
#include <tree.h>
|
#include <tree.h>
|
||||||
#include <langhooks.h>
|
#include <langhooks.h>
|
||||||
|
#include <gimple.h>
|
||||||
|
#include <gimplify.h>
|
||||||
|
|
||||||
|
#include <tree-pass.h>
|
||||||
|
#include <gimple-iterator.h>
|
||||||
|
#include <gimple-pretty-print.h>
|
||||||
|
#include <tree-pretty-print.h>
|
||||||
|
#include <tree-dump.h>
|
||||||
|
#include <print-tree.h>
|
||||||
|
#include <tree-iterator.h>
|
||||||
|
|
||||||
int plugin_is_GPL_compatible;
|
int plugin_is_GPL_compatible;
|
||||||
|
|
||||||
@ -101,6 +111,10 @@ const Member* Target::get_member(Member::OFF offset) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void log_target(tree node) {
|
static void log_target(tree node) {
|
||||||
|
node = TYPE_MAIN_VARIANT(node);
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
|
||||||
if (TREE_CODE(node) != RECORD_TYPE)
|
if (TREE_CODE(node) != RECORD_TYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -188,7 +202,7 @@ void on_register_attributes(void* event_data, void* data) {
|
|||||||
|
|
||||||
static void on_type_complete(void* event_data, void* user_data) {
|
static void on_type_complete(void* event_data, void* user_data) {
|
||||||
tree type = (tree)event_data;
|
tree type = (tree)event_data;
|
||||||
log_target(TYPE_MAIN_VARIANT(type));
|
log_target(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early hook to make COMPONENT_REF nodes survice front end
|
// Early hook to make COMPONENT_REF nodes survice front end
|
||||||
@ -325,6 +339,174 @@ static void on_build_component_ref(void* event_data, void* user_data) {
|
|||||||
*component_ref_node = repl;
|
*component_ref_node = repl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Identify any missing COMPONENT_REFs (e.g. from CONSTRUCTOR trees)
|
||||||
|
|
||||||
|
static const pass_data log_component_refs_pass_data = {
|
||||||
|
GIMPLE_PASS,
|
||||||
|
"log_component_refs",
|
||||||
|
OPTGROUP_NONE,
|
||||||
|
TV_NONE,
|
||||||
|
0,0,0,0,
|
||||||
|
TODO_update_ssa
|
||||||
|
};
|
||||||
|
|
||||||
|
struct log_component_refs_pass : gimple_opt_pass {
|
||||||
|
log_component_refs_pass(gcc::context *ctxt);
|
||||||
|
unsigned int execute(function* fun) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
log_component_refs_pass::log_component_refs_pass(gcc::context *ctxt) : gimple_opt_pass(log_component_refs_pass_data, ctxt) {}
|
||||||
|
|
||||||
|
static tree gimple_instrument_offsetof_maybe(tree ref, gimple_stmt_iterator* gsi) {
|
||||||
|
SPSLROffsetofCallData call_data;
|
||||||
|
if (!is_relevant_offsetof(ref, call_data.target, call_data.member))
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
// Build call gimple statement
|
||||||
|
|
||||||
|
location_t loc = EXPR_LOCATION(ref);
|
||||||
|
tree result_type = TREE_TYPE(ref);
|
||||||
|
|
||||||
|
if (!require_spslr_offsetof_decl()) {
|
||||||
|
std::cerr << "spslr_pinpoint -> failed to instrument COMPONENT_REF (" << SPSLR_OFFSETOF << " unavailable)" << std::endl;
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
call_data.uid = spslr_offsetof_next_uid++;
|
||||||
|
spslr_offsetof_calls.emplace(call_data.uid, call_data);
|
||||||
|
|
||||||
|
tree call_uid_tree = build_int_cst(long_unsigned_type_node, call_data.uid);
|
||||||
|
|
||||||
|
gimple* call_stmt = gimple_build_call(spslr_offsetof_decl, 1, call_uid_tree);
|
||||||
|
tree offset_tmp = create_tmp_var(size_type_node, NULL);
|
||||||
|
gimple_call_set_lhs(call_stmt, offset_tmp);
|
||||||
|
gsi_insert_before(gsi, call_stmt, GSI_SAME_STMT);
|
||||||
|
|
||||||
|
// Get base as char*
|
||||||
|
tree base = TREE_OPERAND(ref, 0);
|
||||||
|
tree base_addr;
|
||||||
|
|
||||||
|
if (TREE_CODE(base) == ADDR_EXPR) {
|
||||||
|
// base_addr = base;
|
||||||
|
std::cerr << "spslr_pinpoint -> unexpected ADDR_EXPR as COMPONENT_REF base!" << std::endl;
|
||||||
|
return NULL_TREE;
|
||||||
|
} else {
|
||||||
|
base_addr = build_fold_addr_expr(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree char_ptr_type = build_pointer_type(char_type_node);
|
||||||
|
tree field_ptr_type = build_pointer_type(result_type);
|
||||||
|
|
||||||
|
// Temporary variable for base pointer needed for GIMPLE
|
||||||
|
tree base_char_ptr = fold_convert(char_ptr_type, base_addr);
|
||||||
|
tree base_char_ptr_tmp = create_tmp_var(char_ptr_type, NULL);
|
||||||
|
gimple* base_char_ptr_tmp_assignment = gimple_build_assign(base_char_ptr_tmp, base_char_ptr);
|
||||||
|
gsi_insert_before(gsi, base_char_ptr_tmp_assignment, GSI_SAME_STMT);
|
||||||
|
|
||||||
|
// Add result of __spslr_offsetof, cast back to field pointer, then dereference
|
||||||
|
tree plus = build2_loc(loc, POINTER_PLUS_EXPR, char_ptr_type, base_char_ptr_tmp, offset_tmp);
|
||||||
|
|
||||||
|
tree plus_tmp = create_tmp_var(TREE_TYPE(plus), NULL);
|
||||||
|
gimple* plus_tmp_assignment = gimple_build_assign(plus_tmp, plus);
|
||||||
|
gsi_insert_before(gsi, plus_tmp_assignment, GSI_SAME_STMT);
|
||||||
|
|
||||||
|
tree cast_back = fold_convert(field_ptr_type, plus_tmp);
|
||||||
|
|
||||||
|
tree res_ptr_tmp = create_tmp_var(TREE_TYPE(cast_back), NULL);
|
||||||
|
gimple* res_ptr_tmp_assignment = gimple_build_assign(res_ptr_tmp, cast_back);
|
||||||
|
gsi_insert_before(gsi, res_ptr_tmp_assignment, GSI_SAME_STMT);
|
||||||
|
|
||||||
|
tree off0 = build_int_cst(sizetype, 0);
|
||||||
|
tree new_ref = build2_loc(loc, MEM_REF, result_type, res_ptr_tmp, fold_convert(field_ptr_type, off0));
|
||||||
|
return new_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tree log_gimple_operand_component_refs(tree *tp, int *walk_subtrees, void *data) {
|
||||||
|
gimple_stmt_iterator* gsi = (gimple_stmt_iterator*)data;
|
||||||
|
*walk_subtrees = 1;
|
||||||
|
|
||||||
|
if (!tp || !*tp)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
if (TREE_CODE(*tp) != COMPONENT_REF)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
tree repl = gimple_instrument_offsetof_maybe(*tp, gsi);
|
||||||
|
if (!repl)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
// TODO -> Recursively do sub-component-refs
|
||||||
|
// After top level split, the base is in a separate stmt!
|
||||||
|
|
||||||
|
*tp = repl;
|
||||||
|
*walk_subtrees = 0;
|
||||||
|
|
||||||
|
gimple_set_modified(gsi_stmt(*gsi), true);
|
||||||
|
|
||||||
|
walk_tree(tp, log_gimple_operand_component_refs, data, NULL);
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int log_component_refs_pass::execute(function* fun) {
|
||||||
|
const char* funcname = fun->decl && DECL_NAME(fun->decl)
|
||||||
|
? IDENTIFIER_POINTER(DECL_NAME(fun->decl))
|
||||||
|
: "<anonymous>";
|
||||||
|
|
||||||
|
tree fndecl = fun->decl;
|
||||||
|
if (!fndecl)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
gimple_seq body = gimple_body(fndecl);
|
||||||
|
for (gimple_stmt_iterator gsi = gsi_start(body); !gsi_end_p(gsi); gsi_next(&gsi)) {
|
||||||
|
gimple* stmt = gsi_stmt(gsi);
|
||||||
|
|
||||||
|
for (int i = 0; i < gimple_num_ops(stmt); i++) {
|
||||||
|
tree* op = gimple_op_ptr(stmt, i);
|
||||||
|
if (!op || !*op)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
walk_tree(op, log_gimple_operand_component_refs, &gsi, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_gimple_seq(stderr, gimple_body(fun->decl), 0, TDF_NONE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gimple print pass for debugging
|
||||||
|
|
||||||
|
static const pass_data print_pass_data = {
|
||||||
|
GIMPLE_PASS,
|
||||||
|
"gimple_print",
|
||||||
|
OPTGROUP_NONE,
|
||||||
|
TV_NONE,
|
||||||
|
0,0,0,0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct print_pass : gimple_opt_pass {
|
||||||
|
print_pass(gcc::context *ctxt);
|
||||||
|
unsigned int execute(function* fun) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
print_pass::print_pass(gcc::context *ctxt) : gimple_opt_pass(print_pass_data, ctxt) {}
|
||||||
|
|
||||||
|
unsigned int print_pass::execute(function* fun) {
|
||||||
|
const char* funcname = fun->decl && DECL_NAME(fun->decl)
|
||||||
|
? IDENTIFIER_POINTER(DECL_NAME(fun->decl))
|
||||||
|
: "<anonymous>";
|
||||||
|
|
||||||
|
fprintf(stderr, "[spslr_pinpoint] Function: %s\n", funcname);
|
||||||
|
basic_block bb;
|
||||||
|
FOR_EACH_BB_FN(bb, fun) {
|
||||||
|
for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
|
||||||
|
gimple* stmt = gsi_stmt(gsi);
|
||||||
|
print_gimple_stmt(stderr, stmt, 0, TDF_SLIM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Hook everything up in plugin_init
|
// Hook everything up in plugin_init
|
||||||
|
|
||||||
@ -339,5 +521,19 @@ int plugin_init (struct plugin_name_args *plugin_info, struct plugin_gcc_version
|
|||||||
register_callback(plugin_info->base_name, PLUGIN_FINISH_TYPE, on_type_complete, NULL);
|
register_callback(plugin_info->base_name, PLUGIN_FINISH_TYPE, on_type_complete, NULL);
|
||||||
register_callback(plugin_info->base_name, PLUGIN_BUILD_COMPONENT_REF, on_build_component_ref, NULL);
|
register_callback(plugin_info->base_name, PLUGIN_BUILD_COMPONENT_REF, on_build_component_ref, NULL);
|
||||||
|
|
||||||
|
struct register_pass_info log_component_refs_pass_info;
|
||||||
|
log_component_refs_pass_info.pass = new log_component_refs_pass(nullptr);
|
||||||
|
log_component_refs_pass_info.ref_pass_instance_number = 1;
|
||||||
|
log_component_refs_pass_info.reference_pass_name = "cfg";
|
||||||
|
log_component_refs_pass_info.pos_op = PASS_POS_INSERT_BEFORE;
|
||||||
|
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &log_component_refs_pass_info);
|
||||||
|
|
||||||
|
struct register_pass_info print_pass_info;
|
||||||
|
print_pass_info.pass = new print_pass(nullptr);
|
||||||
|
print_pass_info.ref_pass_instance_number = 1;
|
||||||
|
print_pass_info.reference_pass_name = "cfg";
|
||||||
|
print_pass_info.pos_op = PASS_POS_INSERT_AFTER;
|
||||||
|
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &print_pass_info);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user