From: Justin Seyster Date: Wed, 14 Jul 2010 23:57:29 +0000 (-0400) Subject: Store prototype for each advice function. X-Git-Tag: release-v1.0~48^2~17 X-Git-Url: https://git.fsl.cs.stonybrook.edu/?a=commitdiff_plain;h=f8e59ffe59a76519ae4b8b45952ad26f28bdb72e;p=interaspect.git Store prototype for each advice function. --- diff --git a/src/Makefile.am b/src/Makefile.am index e353f15..de2564c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,6 @@ lib_LTLIBRARIES = libinteraspect.la -libinteraspect_la_SOURCES = aop-pc-assign.c aop-main.c aop-type.c aop-weave.c aop-pc-entry.c aop-pc-exit.c aop-pc-fun-call.c +libinteraspect_la_SOURCES = aop-pc-assign.c aop-main.c aop-type.c aop-weave.c \ + aop-pc-entry.c aop-pc-exit.c aop-pc-fun-call.c aop-header.c libinteraspect_la_CFLAGS = -Wall -Werror -fvisibility=hidden -prefer-pic libinteraspect_la_LDFLAGS = -static -prefer-pic -version-info 1:0:0 libinteraspect_la_CPPFLAGS = -DHAVE_CONFIG_H -DIN_GCC -I$(gcc_includes) diff --git a/src/aop-header.c b/src/aop-header.c new file mode 100644 index 0000000..9ca2c61 --- /dev/null +++ b/src/aop-header.c @@ -0,0 +1,216 @@ +/* This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* aop-header.c: Functions for storing the advice function prototypes + we have seen and later outputing those prototypes to an + auto-generated header file. */ + +/* Whether we want them or not (we don't), Autoconf _insists_ on + defining these. Since GCC's config.h (which we must include) also + defines them, we have to undef them here. */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + +#include +#include + +#include +#include +#include +#include +#include + +#include "aop.h" +#include "aop-dynval.h" +#include "aop-header.h" +#include "aop-type.h" + +/* An aop_prototype struct represents the prototype of an advice + function, including its name, return type and parameters. */ +struct aop_prototype { + /* Users should not create multiple prototypes with the same name + but different return/parameter types, but if they do, we can + chain them together in this list. */ + struct aop_prototype *next; + + /* True if the prototype has return type int. False if the + prototype has a void return type. */ + bool has_return_value; + + const char *name; + + int num_params; + const struct aop_type *param_types[]; +}; + +/* This table matches function name to function prototype. Where + there are multiple prototypes with the same name (an error case), + those prototypes are chained together in a linked list. */ +static htab_t prototype_table = NULL; + +/* This is the equality function that the hashtable uses to determine + if a prototype entry in the table matches a key. */ +static int +htab_str_eq (const void *table_entry, const void *key) +{ + const struct aop_prototype *prototype = + (const struct aop_prototype *)table_entry; + + return (strcmp (prototype->name, key) == 0); +} + +/* Return true if a prototype has the same return value and parameters + as a potential new prototype. */ +static bool +is_compatible_prototype (struct aop_prototype *prototype, + bool has_return_value, int num_params, + const struct aop_type *param_types[]) +{ + int i; + + /* The prototypes do not match if one returns a value and the other + does not. */ + if ((prototype->has_return_value && !has_return_value) || + (!prototype->has_return_value && has_return_value)) + return false; + + if (prototype->num_params != num_params) + return false; + + for (i = 0; i < num_params; i++) + { + if (!are_types_equal (prototype->param_types[i], param_types[i])) + return false; + } + + /* These prototypes match. */ + return true; +} + +static void +get_param_types (va_list argp, int num_params, + const struct aop_type *param_types[]) +{ + int i; + enum aop_argkind kind; + struct aop_dynval *dv; + + for (i = 0; i < num_params; i++) + { + kind = va_arg (argp, enum aop_argkind); + switch (kind) + { + case ATA_STR_CST: + aop_assert (0); + break; + case ATA_INT_CST: + va_arg (argp, int); + param_types[i] = aop_t_all_signed (); + break; + case ATA_FLOAT_CST: + va_arg (argp, double); + param_types[i] = aop_t_all_fp (); + break; + case ATA_VOIDP_CST: + va_arg (argp, void *); + param_types[i] = aop_t_all_pointer (); + break; + case ATA_DYNVAL: + dv = va_arg (argp, struct aop_dynval *); + param_types[i] = dv->type; + break; + default: + aop_assert (0); + } + } + + aop_assert (va_arg (argp, enum aop_argkind) == AOP_TERM_ARG); +} + +/* If there is no entry in the list of advice function prototypes for + this advice function, create one. If a prototype already exists + with conflicting types, issue a warning. */ +void +insert_prototype (bool has_return_value, const char *name, int num_params, + va_list argp) +{ + size_t param_types_size; + const struct aop_type **param_types; + + struct aop_prototype **hash_slot; + struct aop_prototype *prototype; + + param_types_size = num_params * sizeof (const struct aop_type *); + param_types = alloca (param_types_size); + get_param_types (argp, num_params, param_types); + + /* Check the hash table for a prototype with this name. */ + hash_slot = + (struct aop_prototype **)htab_find_slot (prototype_table, name, INSERT); + if (*hash_slot != NULL) + { + /* We already have at least one prototype with this name. Make + sure one of them is compatible. */ + while (*hash_slot != NULL) + { + prototype = *hash_slot; + + if (is_compatible_prototype (prototype, has_return_value, num_params, + param_types)) + { + /* Found one! Nothing else to do. */ + return; + } + + hash_slot = &prototype->next; + } + + /* None of the prototypes we have already seen matches this one. + First, we issue a warning. */ + warning (0, "(InterAspect) Calls to advice function %s with different " + "prototypes", name); + + /* Then we fall through to the code to allocate and initialize a + new prototype object. */ + } + + /* Allocate the new prototype and insert it in the hash table (or in + the linked list if we happened to find a hash table entry + already). */ + prototype = xmalloc (sizeof (struct aop_prototype *) + + (num_params * sizeof (const struct aop_type *))); + *hash_slot = prototype; + + prototype->has_return_value = has_return_value; + prototype->name = xstrdup (name); + prototype->num_params = num_params; + memcpy (prototype->param_types, param_types, param_types_size); +} + +void +init_prototype_table() +{ + prototype_table = htab_create_alloc (16, htab_hash_string, htab_str_eq, NULL, + xcalloc, free); +} + +void +free_prototype_table() +{ + /* TODO: Free the contents as well. */ + htab_delete (prototype_table); +} diff --git a/src/aop-header.h b/src/aop-header.h new file mode 100644 index 0000000..d21d4bb --- /dev/null +++ b/src/aop-header.h @@ -0,0 +1,27 @@ +#ifndef __AOP_HEADER_H__ +#define __AOP_HEADER_H__ + +/* This program is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* This is a private header. Do not include it in source file for + client plug-ins. */ + +void insert_prototype (bool has_return_value, const char *name, int num_params, + va_list argp); + +void init_prototype_table(); +void free_prototype_table(); + +#endif diff --git a/src/aop-main.c b/src/aop-main.c index 0acac47..83c76f5 100644 --- a/src/aop-main.c +++ b/src/aop-main.c @@ -51,6 +51,7 @@ #include #include "aop.h" +#include "aop-header.h" #include "aop-pointcut.h" //#define PAUSE_ON_START @@ -159,6 +160,7 @@ cleanup_passes () static void aop_cleanup (void *event_date, void *data) { + free_prototype_table (); cleanup_passes (); } @@ -186,6 +188,8 @@ plugin_init (struct plugin_name_args *plugin_info, aop_plugin_name = plugin_info->base_name; + init_prototype_table (); + /* Register our cleanup function. */ register_callback (aop_plugin_name, PLUGIN_FINISH, aop_cleanup, NULL); diff --git a/src/aop-type.c b/src/aop-type.c index f0b4aef..52eb022 100644 --- a/src/aop-type.c +++ b/src/aop-type.c @@ -110,3 +110,10 @@ does_type_match (tree gcc_type, const struct aop_type *aop_type) aop_assert (0); } + +/* Return true if two aop_type objects are equal. */ +bool +are_types_equal (const struct aop_type *a, const struct aop_type *b) +{ + return (a == b); +} diff --git a/src/aop-type.h b/src/aop-type.h index 7b88c8b..aa8d379 100644 --- a/src/aop-type.h +++ b/src/aop-type.h @@ -36,5 +36,6 @@ struct aop_type { }; bool does_type_match (tree gcc_type, const struct aop_type *aop_type); +bool are_types_equal (const struct aop_type *a, const struct aop_type *b); #endif diff --git a/src/aop-weave.c b/src/aop-weave.c index 4928666..c8edaa8 100644 --- a/src/aop-weave.c +++ b/src/aop-weave.c @@ -41,6 +41,7 @@ #include "aop.h" #include "aop-dynval.h" +#include "aop-header.h" #include "aop-pointcut.h" /* Throw a fatal error if a dynval is not allowed in a before-advice @@ -255,10 +256,14 @@ aop_insert_advice (struct aop_joinpoint *jp, const char *func_name, va_start (argp, location); func_call = build_gcc_call (func_name, void_type_node, location, argp); va_end (argp); + + va_start (argp, location); + insert_prototype (false /* void return type */, func_name, + gimple_call_num_args (func_call), argp); + va_end (argp); if(location == AOP_INSERT_BEFORE) pc->insert_before(jp, func_call); else if(location == AOP_INSERT_AFTER) pc->insert_after(jp, func_call); - }