static void tree_init_edge_profiler (void) { tree interval_profiler_fn_type; tree pow2_profiler_fn_type; tree one_value_profiler_fn_type; tree gcov_type_ptr; if (!gcov_type_node) { gcov_type_node = get_gcov_type (); gcov_type_ptr = build_pointer_type (gcov_type_node); /* void (*) (gcov_type *, gcov_type, int, unsigned) */ interval_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, integer_type_node, unsigned_type_node, NULL_TREE); tree_interval_profiler_fn = build_fn_decl ("__gcov_interval_profiler", interval_profiler_fn_type); /* void (*) (gcov_type *, gcov_type) */ pow2_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", pow2_profiler_fn_type); /* void (*) (gcov_type *, gcov_type) */ one_value_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_one_value_profiler_fn = build_fn_decl ("__gcov_one_value_profiler", one_value_profiler_fn_type); } }
static tree build_function_decl (const char *name, bool external, tree function_type) { tree fndecl = build_fn_decl (name, function_type); SET_DECL_ASSEMBLER_NAME(fndecl, get_identifier(name)); DECL_EXTERNAL (fndecl) = external; DECL_ARTIFICIAL (fndecl) = false; TREE_STATIC (fndecl) = !external; DECL_CONTEXT (fndecl) = NULL_TREE; return fndecl; }
static void init_decls(void) { static unsigned int is_once = 0; tree type; if (is_once) return ; is_once = 1; type = build_function_type_list (ptr_type_node, size_type_node, NULL_TREE); kaapi_pushdata_aligned_decl = build_fn_decl("kaapi_pushdata_aligned", type); type = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); kaapi_pushtask_decl = build_fn_decl("kaapi_pushtask", type); type = build_function_type_list (void_type_node, void_type_node, NULL_TREE); kaapi_barrier_decl = build_fn_decl("kaapi_barrier", type); }
static tree install_builtin (const char *name, tree fntype, enum built_in_function code, bool publish) { tree fndecl = build_fn_decl (name, fntype); DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL; DECL_FUNCTION_CODE (fndecl) = code; if (publish) { tree t = lang_hooks.decls.pushdecl (fndecl); if (t) fndecl = t; } set_builtin_decl (code, fndecl, true); return fndecl; }
static tree build_junk_fn(unsigned id) { char fnname[32] = {0}; tree decl, resdecl, initial, proto; /* Func decl */ snprintf(fnname, 31, "__func%d", id); proto = build_varargs_function_type_list(void_type_node, NULL_TREE); decl = build_fn_decl(fnname, proto); SET_DECL_ASSEMBLER_NAME(decl, get_identifier(fnname)); printf(TAG "Creating junk function: %s\n", fnname); /* Result */ resdecl=build_decl(BUILTINS_LOCATION,RESULT_DECL,NULL_TREE,void_type_node); DECL_ARTIFICIAL(resdecl) = 1; DECL_CONTEXT(resdecl) = decl; DECL_RESULT(decl) = resdecl; /* Initial */ initial = make_node(BLOCK); TREE_USED(initial) = 1; DECL_INITIAL(decl) = initial; DECL_UNINLINABLE(decl) = 1; DECL_EXTERNAL(decl) = 0; DECL_PRESERVE_P(decl) = 1; /* Func decl */ TREE_USED(decl) = 1; TREE_PUBLIC(decl) = 1; TREE_STATIC(decl) = 1; DECL_ARTIFICIAL(decl) = 1; /* Make the function */ push_struct_function(decl); /* DECL_SAVED_TREE(decl) = gen_junk(); */ cfun->function_end_locus = BUILTINS_LOCATION; gimplify_function_tree(decl); /* Update */ cgraph_add_new_function(decl, false); cgraph_mark_needed_node(cgraph_node(decl)); current_function_decl = NULL_TREE; pop_cfun(); return decl; }
// create the function call to a `record_assignment' function and insert it // before the given statement static void insert_instrumentation_fn(gimple curr_stmt, tree var_id, tree new_value) { // build function declaration tree proto = build_function_type_list( void_type_node, /* return type */ integer_type_node, /* first arg's type */ const_ptr_type_node, /* second arg's type */ NULL_TREE); tree decl = build_fn_decl("record_assignment", proto); // build the function call with the new value tree and the variable id tree // and insert it before the statement that was passed as the first argument gimple call = gimple_build_call(decl, 2, var_id, new_value); gimple_stmt_iterator gsi = gsi_for_stmt(curr_stmt); gsi_insert_before(&gsi, call, GSI_NEW_STMT); }
static tree create_dummy_adapter(void) { /* create function type */ static tree type = NULL; static tree decl = NULL; if (decl != NULL) return decl; /* create the type void fu(void)*/ type = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); /* create the function decl */ decl = build_fn_decl("__xkaapi_dummy_adapter", type); return decl; }
/* Insert call to __slimer_init to initalize things at runtime */ static void insert_slimer_init(void) { int i; gimple stmt; tree decl, proto; proto = build_function_type_list(void_type_node, integer_type_node, NULL_TREE); decl = build_fn_decl("__slimer_init", proto); stmt = gsi_stmt(gsi_start_bb(ENTRY_BLOCK_PTR->next_bb)); insert_call(stmt, decl); for (i=0; i<n_funcs; ++i) insert_add_fn(stmt, i); /* Add this fndecl to our list of things we do not process */ VEC_safe_push(tree, gc, analyized_fns, decl); }
static tree make_fndecl (tree return_type, const char *name, vec <tree> ¶m_types, bool is_variadic = false) { tree fn_type; if (is_variadic) fn_type = build_varargs_function_type_array (return_type, param_types.length (), param_types.address ()); else fn_type = build_function_type_array (return_type, param_types.length (), param_types.address ()); /* FIXME: this uses input_location: */ tree fndecl = build_fn_decl (name, fn_type); return fndecl; }
/* Insert a call to the runtime function "__slimer_add_fn" which will add the * "junk" function created at compile-time to an array at runtime */ static void insert_add_fn(gimple stmt, int index) { tree fn; gimple call; gimple_stmt_iterator gsi; static tree decl, proto, idx; if (!decl || !proto) { proto = build_function_type_list(void_type_node, ptr_type_node, integer_type_node, NULL_TREE); decl = build_fn_decl("__slimer_add_fn", proto); /* Add this fndecl to our list of things we do not process */ VEC_safe_push(tree, gc, analyized_fns, decl); } /* Create a constant value and pointer to the function we are to add */ idx = build_int_cst(integer_type_node, index); fn = build_addr(VEC_index(tree, fakes, index), NULL_TREE); call = gimple_build_call(decl, 2, fn, idx); gsi = gsi_for_stmt(stmt); gsi_insert_before(&gsi, call, GSI_NEW_STMT); }
void gimple_init_edge_profiler (void) { tree interval_profiler_fn_type; tree pow2_profiler_fn_type; tree one_value_profiler_fn_type; tree gcov_type_ptr; tree ic_profiler_fn_type; tree average_profiler_fn_type; tree time_profiler_fn_type; if (!gcov_type_node) { gcov_type_node = get_gcov_type (); gcov_type_ptr = build_pointer_type (gcov_type_node); /* void (*) (gcov_type *, gcov_type, int, unsigned) */ interval_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, integer_type_node, unsigned_type_node, NULL_TREE); tree_interval_profiler_fn = build_fn_decl ("__gcov_interval_profiler", interval_profiler_fn_type); TREE_NOTHROW (tree_interval_profiler_fn) = 1; DECL_ATTRIBUTES (tree_interval_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_interval_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ pow2_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", pow2_profiler_fn_type); TREE_NOTHROW (tree_pow2_profiler_fn) = 1; DECL_ATTRIBUTES (tree_pow2_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_pow2_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ one_value_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_one_value_profiler_fn = build_fn_decl ("__gcov_one_value_profiler", one_value_profiler_fn_type); TREE_NOTHROW (tree_one_value_profiler_fn) = 1; DECL_ATTRIBUTES (tree_one_value_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_one_value_profiler_fn)); init_ic_make_global_vars (); /* void (*) (gcov_type, void *) */ ic_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_node, ptr_void, NULL_TREE); tree_indirect_call_profiler_fn = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ? "__gcov_indirect_call_topn_profiler": "__gcov_indirect_call_profiler_v2"), ic_profiler_fn_type); TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); /* void (*) (gcov_type *, gcov_type, void *) */ time_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, NULL_TREE); tree_time_profiler_fn = build_fn_decl ("__gcov_time_profiler", time_profiler_fn_type); TREE_NOTHROW (tree_time_profiler_fn) = 1; DECL_ATTRIBUTES (tree_time_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_time_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ average_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_average_profiler_fn = build_fn_decl ("__gcov_average_profiler", average_profiler_fn_type); TREE_NOTHROW (tree_average_profiler_fn) = 1; DECL_ATTRIBUTES (tree_average_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_average_profiler_fn)); tree_ior_profiler_fn = build_fn_decl ("__gcov_ior_profiler", average_profiler_fn_type); TREE_NOTHROW (tree_ior_profiler_fn) = 1; DECL_ATTRIBUTES (tree_ior_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_ior_profiler_fn)); /* LTO streamer needs assembler names. Because we create these decls late, we need to initialize them by hand. */ DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); DECL_ASSEMBLER_NAME (tree_time_profiler_fn); DECL_ASSEMBLER_NAME (tree_average_profiler_fn); DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); } }
void gimple_init_edge_profiler (void) { tree interval_profiler_fn_type; tree pow2_profiler_fn_type; tree one_value_profiler_fn_type; tree gcov_type_ptr; tree ic_profiler_fn_type; tree average_profiler_fn_type; tree time_profiler_fn_type; if (!gcov_type_node) { gcov_type_node = get_gcov_type (); gcov_type_ptr = build_pointer_type (gcov_type_node); /* void (*) (gcov_type *, gcov_type, int, unsigned) */ interval_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, integer_type_node, unsigned_type_node, NULL_TREE); tree_interval_profiler_fn = build_fn_decl ("__gcov_interval_profiler", interval_profiler_fn_type); TREE_NOTHROW (tree_interval_profiler_fn) = 1; DECL_ATTRIBUTES (tree_interval_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_interval_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ pow2_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_pow2_profiler_fn = build_fn_decl ("__gcov_pow2_profiler", pow2_profiler_fn_type); TREE_NOTHROW (tree_pow2_profiler_fn) = 1; DECL_ATTRIBUTES (tree_pow2_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_pow2_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ one_value_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_one_value_profiler_fn = build_fn_decl ("__gcov_one_value_profiler", one_value_profiler_fn_type); TREE_NOTHROW (tree_one_value_profiler_fn) = 1; DECL_ATTRIBUTES (tree_one_value_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_one_value_profiler_fn)); init_ic_make_global_vars (); /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */ if (flag_lto) { /* void (*) (gcov_type, void *) */ ic_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, ptr_void, ptr_void, NULL_TREE); tree_indirect_call_profiler_fn = build_fn_decl ("__gcov_indirect_call_profiler", ic_profiler_fn_type); } else { /* void (*) (gcov_type, void *) */ ic_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_node, ptr_void, NULL_TREE); tree_indirect_call_profiler_fn = build_fn_decl ("__gcov_indirect_call_profiler_v2", ic_profiler_fn_type); } TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1; DECL_ATTRIBUTES (tree_indirect_call_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); /* void (*) (gcov_type *, gcov_type, void *) */ time_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, NULL_TREE); tree_time_profiler_fn = build_fn_decl ("__gcov_time_profiler", time_profiler_fn_type); TREE_NOTHROW (tree_time_profiler_fn) = 1; DECL_ATTRIBUTES (tree_time_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_time_profiler_fn)); /* void (*) (gcov_type *, gcov_type) */ average_profiler_fn_type = build_function_type_list (void_type_node, gcov_type_ptr, gcov_type_node, NULL_TREE); tree_average_profiler_fn = build_fn_decl ("__gcov_average_profiler", average_profiler_fn_type); TREE_NOTHROW (tree_average_profiler_fn) = 1; DECL_ATTRIBUTES (tree_average_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_average_profiler_fn)); tree_ior_profiler_fn = build_fn_decl ("__gcov_ior_profiler", average_profiler_fn_type); TREE_NOTHROW (tree_ior_profiler_fn) = 1; DECL_ATTRIBUTES (tree_ior_profiler_fn) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_ior_profiler_fn)); /* LTO streamer needs assembler names. Because we create these decls late, we need to initialize them by hand. */ DECL_ASSEMBLER_NAME (tree_interval_profiler_fn); DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); DECL_ASSEMBLER_NAME (tree_time_profiler_fn); DECL_ASSEMBLER_NAME (tree_average_profiler_fn); DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); } }
static void insert_call_to_junk_fn(gimple stmt) { tree tv, rv, fn, rhs, tmp; gimple gimp; gimple_stmt_iterator gsi; static bool has_initted; static tree decl, proto, decl_get_funcs, proto_get_funcs, fn_ptr_type; printf("slimer: Inserting junk function call at line: %d\n", gimple_lineno(stmt)); /* Get random value modulo n_funcs for index into runtime __funcs array of * junk functions: * rv = time % n_funcs; * fn = __funcs + rv; * call fn */ /* Build instances */ if (!has_initted) { proto = build_function_type_list( uint64_type_node, ptr_type_node, NULL_TREE); decl = build_fn_decl("time", proto); DECL_EXTERNAL(decl) = 1; proto_get_funcs = build_function_type_list(ptr_type_node, NULL_TREE); decl_get_funcs = build_fn_decl("__slimer_get_funcs", proto_get_funcs); fn_ptr_type = build_function_type_list( void_type_node, void_type_node, NULL_TREE); has_initted = true; } /* time_tmp = time(NULL); */ tv = create_tmp_var(uint64_type_node, "time_tmp"); tv = make_ssa_name(tv, NULL); gimp = gimple_build_call(decl, 1, null_pointer_node); gimple_set_lhs(gimp, tv); gsi = gsi_for_stmt(stmt); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); /* rv_tmp = time_temp % n_funcs */ rv = create_tmp_var(uint64_type_node, "rv_tmp"); rv = make_ssa_name(rv, NULL); rhs = build_int_cst(integer_type_node, n_funcs); gimp = gimple_build_assign_with_ops(TRUNC_MOD_EXPR, rv, tv, rhs); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); /* tmp = __slimer_get_funcs(); TODO: Get rid of __slimer_get_funcs() * rv = rv * sizeof(void *) * fn_tmp = tmp + rv */ tree pp_type = build_pointer_type(ptr_type_node); tmp = create_tmp_var(pp_type, "tmp"); tmp = make_ssa_name(tmp, NULL); gimp = gimple_build_call(decl_get_funcs, 0); gimple_set_lhs(gimp, tmp); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); /* rv = rv * sizeof(void *)) * FIXME: THIS IS NOT SUFFICIENT FOR CROSS COMPILING FOR ARCHITECTURES THAT * HAVE ADDRESS SIZES sizeof(void *) */ tree addr_size = build_int_cst(integer_type_node, sizeof(void *)); gimp = gimple_build_assign_with_ops(MULT_EXPR, rv, rv, addr_size); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); fn = create_tmp_var(pp_type, "fn_tmp"); fn = make_ssa_name(fn, NULL); gimp = gimple_build_assign_with_ops(PLUS_EXPR, fn, tmp, rv); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); /* the_fn = *fn */ tree f = build_pointer_type(fn_ptr_type); tree the_fn = create_tmp_var(f, "the_func_ptr"); the_fn = make_ssa_name(the_fn, NULL); gimp = gimple_build_assign(the_fn, build_simple_mem_ref(fn)); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); /* call the_fn */ gimp = gimple_build_call(the_fn, 0); gsi_insert_before(&gsi, gimp, GSI_SAME_STMT); #ifdef GOAT_DEBUG debug_function(cfun->decl, 0); #endif }