Updated pinpoint plugin
This commit is contained in:
parent
8d1bfb31a1
commit
85ca5b9775
@ -358,6 +358,11 @@ struct log_component_refs_pass : gimple_opt_pass {
|
|||||||
log_component_refs_pass::log_component_refs_pass(gcc::context *ctxt) : gimple_opt_pass(log_component_refs_pass_data, ctxt) {}
|
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) {
|
static tree gimple_instrument_offsetof_maybe(tree ref, gimple_stmt_iterator* gsi) {
|
||||||
|
// TODO -> nested COMPONENT_REFs!
|
||||||
|
|
||||||
|
if (!ref || TREE_CODE(ref) != COMPONENT_REF)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
SPSLROffsetofCallData call_data;
|
SPSLROffsetofCallData call_data;
|
||||||
if (!is_relevant_offsetof(ref, call_data.target, call_data.member))
|
if (!is_relevant_offsetof(ref, call_data.target, call_data.member))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
@ -421,30 +426,85 @@ static tree gimple_instrument_offsetof_maybe(tree ref, gimple_stmt_iterator* gsi
|
|||||||
return new_ref;
|
return new_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tree log_gimple_operand_component_refs(tree *tp, int *walk_subtrees, void *data) {
|
static void instrument_tree(const std::list<tree*>& path, gimple_stmt_iterator* gsi, unsigned& cancel_levels) {
|
||||||
gimple_stmt_iterator* gsi = (gimple_stmt_iterator*)data;
|
if (path.empty() || !gsi)
|
||||||
*walk_subtrees = 1;
|
return;
|
||||||
|
|
||||||
if (!tp || !*tp)
|
tree instrumented_ref = gimple_instrument_offsetof_maybe(*path.back(), gsi);
|
||||||
return NULL_TREE;
|
if (!instrumented_ref)
|
||||||
|
return;
|
||||||
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);
|
gimple_set_modified(gsi_stmt(*gsi), true);
|
||||||
|
|
||||||
walk_tree(tp, log_gimple_operand_component_refs, data, NULL);
|
*path.back() = instrumented_ref;
|
||||||
return NULL_TREE;
|
cancel_levels = 1;
|
||||||
|
|
||||||
|
// At this point, instrumented_ref is a MEM_REF node (off=0). A wrapping ADDR_EXPR cancels it out.
|
||||||
|
|
||||||
|
if (path.size() < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tree* parent = *(++path.rbegin());
|
||||||
|
|
||||||
|
if (TREE_CODE(*parent) == ADDR_EXPR) {
|
||||||
|
// Note -> the base of the MEM_REF is expected to have the same type as the ADDR_EXPR
|
||||||
|
*parent = TREE_OPERAND(instrumented_ref, 0);
|
||||||
|
cancel_levels++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TreeWalkData {
|
||||||
|
std::list<tree*> path;
|
||||||
|
gimple_stmt_iterator* gsi;
|
||||||
|
unsigned cancel_levels;
|
||||||
|
};
|
||||||
|
|
||||||
|
static tree walk_tree_level(tree* tp, int* walk_subtrees, void* data) {
|
||||||
|
TreeWalkData* twd = (TreeWalkData*)data;
|
||||||
|
if (!twd)
|
||||||
|
return NULL_TREE;
|
||||||
|
|
||||||
|
if (!twd->path.empty() && twd->path.back() == tp)
|
||||||
|
return NULL_TREE; // root of this level
|
||||||
|
|
||||||
|
if (walk_subtrees)
|
||||||
|
*walk_subtrees = 0;
|
||||||
|
|
||||||
|
twd->cancel_levels = 0;
|
||||||
|
twd->path.push_back(tp);
|
||||||
|
|
||||||
|
instrument_tree(twd->path, twd->gsi, twd->cancel_levels);
|
||||||
|
|
||||||
|
if (twd->cancel_levels == 0)
|
||||||
|
walk_tree(tp, walk_tree_level, data, NULL);
|
||||||
|
|
||||||
|
twd->path.pop_back();
|
||||||
|
|
||||||
|
if (twd->cancel_levels > 0)
|
||||||
|
twd->cancel_levels--;
|
||||||
|
|
||||||
|
// Cancel current level if there are still cancel_levels due
|
||||||
|
return twd->cancel_levels == 0 ? NULL_TREE : *tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool walk_gimple_stmt(gimple_stmt_iterator* gsi) {
|
||||||
|
if (!gsi || gsi_end_p(*gsi))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
TreeWalkData twd;
|
||||||
|
twd.gsi = gsi;
|
||||||
|
|
||||||
|
walk_tree_level(op, NULL, &twd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int log_component_refs_pass::execute(function* fun) {
|
unsigned int log_component_refs_pass::execute(function* fun) {
|
||||||
@ -457,17 +517,7 @@ unsigned int log_component_refs_pass::execute(function* fun) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gimple_seq body = gimple_body(fndecl);
|
gimple_seq body = gimple_body(fndecl);
|
||||||
for (gimple_stmt_iterator gsi = gsi_start(body); !gsi_end_p(gsi); gsi_next(&gsi)) {
|
for (gimple_stmt_iterator gsi = gsi_start(body); walk_gimple_stmt(&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);
|
// print_gimple_seq(stderr, gimple_body(fun->decl), 0, TDF_NONE);
|
||||||
return 0;
|
return 0;
|
||||||
@ -519,7 +569,7 @@ int plugin_init (struct plugin_name_args *plugin_info, struct plugin_gcc_version
|
|||||||
|
|
||||||
register_callback(plugin_info->base_name, PLUGIN_ATTRIBUTES, on_register_attributes, NULL);
|
register_callback(plugin_info->base_name, PLUGIN_ATTRIBUTES, on_register_attributes, NULL);
|
||||||
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);
|
// TODO register_callback(plugin_info->base_name, PLUGIN_BUILD_COMPONENT_REF, on_build_component_ref, NULL);
|
||||||
|
|
||||||
struct register_pass_info log_component_refs_pass_info;
|
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.pass = new log_component_refs_pass(nullptr);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user