From: Justin Seyster Date: Tue, 31 Jul 2012 21:18:35 +0000 (-0400) Subject: Supports static inline advice functions. X-Git-Tag: release-v1.1~6 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=a68df257ff33358dd3ea00e5de3a52ff451131f0;p=interaspect.git Supports static inline advice functions. --- diff --git a/src/aop-main.c b/src/aop-main.c index 5277bab..fb866b2 100644 --- a/src/aop-main.c +++ b/src/aop-main.c @@ -225,6 +225,13 @@ register_plugin_attributes(void *event_data, void *data) register_attribute_once(&noinstr_attr); } +static void +remember_function_decl_pass(void *event_data, void *data) +{ + tree fndecl = (tree)event_data; + remember_function_decl(fndecl); +} + /* This pass gets called before any passes that the client plug-in registers. It's here for any administrative details that need to take place before the instrumentation passes can execute. */ @@ -438,13 +445,17 @@ plugin_init (struct plugin_name_args *plugin_info, plugin_argc = plugin_info->argc; plugin_argv = plugin_info->argv; - /* Initialization for aop-type.c and aop-header.c. */ + /* Initialization for aop-type.c, aop-header.c, and aop-weave.c. */ init_type_table (); init_prototype_table (); + init_static_inline_table (); /* Register attributes. */ register_callback(aop_plugin_name, PLUGIN_ATTRIBUTES, register_plugin_attributes, NULL); + /* Register ctree pass. */ + register_callback(aop_plugin_name, PLUGIN_PRE_GENERICIZE, remember_function_decl_pass, NULL); + /* Register our cleanup function. */ register_callback (aop_plugin_name, PLUGIN_FINISH, aop_cleanup, NULL); diff --git a/src/aop-pc-assign.c b/src/aop-pc-assign.c index 39ef293..6f97d21 100644 --- a/src/aop-pc-assign.c +++ b/src/aop-pc-assign.c @@ -291,6 +291,8 @@ op_prepare_assign (struct aop_joinpoint *jp) /* Insert the new assignment. */ new_assign = gimple_build_assign (real_lhs, tmp_lhs); + gimple_set_block (new_assign, gimple_block (jp->stmt)); + gsi_insert_after (jp->gsi, new_assign, GSI_NEW_STMT); jp->stmt = new_assign; } diff --git a/src/aop-weave.c b/src/aop-weave.c index 1fe50bb..28a4c53 100644 --- a/src/aop-weave.c +++ b/src/aop-weave.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,62 @@ is_stmt_advice (gimple stmt) return (slot != NULL); } +/* This table holds the decl for every static inline we enocunter. We + want to remember these decls in case they get inserted as advice, + in which case we need the original decl so that GCC can perform the + inlining. + + NB: At allocation, we store this on the heap (i.e., not in garbage + collected memory) because it doesn't get freed then reallocated + between passes. */ +static htab_t static_inline_decls = NULL; + +static hashval_t +hash_decl_by_name (const void *entry) +{ + tree decl = (tree)entry; + const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); + + return htab_hash_string (name); +} + +static int +hash_decl_name_eq (const void *entry1, const void *entry2) +{ + tree decl1 = (tree)entry1; + tree decl2 = (tree)entry2; + + const char *name1 = IDENTIFIER_POINTER (DECL_NAME (decl1)); + const char *name2 = IDENTIFIER_POINTER (DECL_NAME (decl2)); + + return (strcmp (name1, name2) == 0); +} + +void +init_static_inline_table () +{ + static_inline_decls = htab_create (10, hash_decl_by_name, hash_decl_name_eq, NULL); +} + +void +free_static_inline_table () +{ + htab_delete (static_inline_decls); +} + +void +remember_function_decl(tree fndecl) +{ + /* Check if this is a static inline function. */ + if (DECL_DECLARED_INLINE_P(fndecl) && !TREE_PUBLIC(fndecl)) + { + tree *slot; + + slot = (tree *)htab_find_slot (static_inline_decls, fndecl, INSERT); + *slot = fndecl; + } +} + /* Throw a fatal error if a dynval is not allowed in a before-advice call. */ static void @@ -252,7 +309,7 @@ build_dynval (struct aop_dynval *dv, VEC(gimple, heap) *pre_stmts) The new nodes get stored in arglist. GIMPLE statements that must be inserted before the call are put in the pre_stmts list. */ static gimple -build_gcc_call (const char *func_name, tree return_type, +build_gcc_call (const char *func_name, tree return_type, tree block, enum aop_insert_location location, VEC(gimple, heap) *pre_stmts, va_list argp) { @@ -262,6 +319,7 @@ build_gcc_call (const char *func_name, tree return_type, tree func_type; tree func_decl; + tree inline_decl; gimple func_call; arg_list = VEC_alloc (tree, heap, 2); @@ -334,8 +392,20 @@ build_gcc_call (const char *func_name, tree return_type, func_type = build_function_type (return_type, argtype_list); func_decl = build_fn_decl (func_name, func_type); + + /* Wait, have we encountered a static inline decl with this same + name? */ + inline_decl = htab_find(static_inline_decls, func_decl); + if (inline_decl != NULL) + func_decl = inline_decl; + func_call = gimple_build_call_vec (func_decl, arg_list); + /* GCC caveat, if there's a chance this call will be inlined, make + sure it has a block. */ + if (func_decl == inline_decl) + gimple_set_block(func_call, block); + VEC_free (tree, heap, arg_list); remember_advice (func_call); @@ -400,6 +470,7 @@ aop_insert_advice (struct aop_joinpoint *jp, const char *func_name, va_list argp; gimple func_call; struct aop_pointcut *pc; + tree block = NULL; VEC(gimple, heap) *pre_stmts; pc = jp->pc; @@ -411,11 +482,14 @@ aop_insert_advice (struct aop_joinpoint *jp, const char *func_name, jp->is_prepared = true; } + if (jp->stmt != NULL) + block = gimple_block(jp->stmt); + pre_stmts = VEC_alloc (gimple, heap, 2); va_start (argp, location); - func_call = build_gcc_call (func_name, void_type_node, location, pre_stmts, - argp); + func_call = build_gcc_call (func_name, void_type_node, block, location, + pre_stmts, argp); va_end (argp); va_start (argp, location); @@ -511,6 +585,7 @@ aop_duplicate (struct aop_joinpoint *jp, const char *func_name, ...) { va_list argp; gimple func_call; + tree block = NULL; struct aop_pointcut *pc; VEC(gimple, heap) *pre_stmts; @@ -525,11 +600,14 @@ aop_duplicate (struct aop_joinpoint *jp, const char *func_name, ...) else if (is_current_func_duplicated()) fatal_error ("(InterAspect) Cannot duplicate a function more than once."); + if (jp->stmt != NULL) + block = gimple_block(jp->stmt); + pre_stmts = VEC_alloc (gimple, heap, 2); va_start (argp, func_name); - func_call = build_gcc_call (func_name, integer_type_node, AOP_INSERT_BEFORE, - pre_stmts, argp); + func_call = build_gcc_call (func_name, integer_type_node, block, + AOP_INSERT_BEFORE, pre_stmts, argp); va_end (argp); va_start (argp, func_name); diff --git a/src/aop-weave.h b/src/aop-weave.h index 98f4da6..113f4a0 100644 --- a/src/aop-weave.h +++ b/src/aop-weave.h @@ -31,4 +31,8 @@ extern void clear_advice_table (); extern bool is_stmt_advice (gimple stmt); +extern void init_static_inline_table (); +extern void free_static_inline_table (); +extern void remember_function_decl (tree fndecl); + #endif