Can macros be used to simulate C++ templated functions? - c

I have a C program in which I need to create a whole family of functions which have the same signatures and bodies, and differ only in their types. What I would like to do is define a macro which generates all of those functions for me, as otherwise I will spend a long time copying and modifying the original functions. As an example, one of the functions I need to generate looks like this:
int copy_key__sint_(void *key, void **args, int argc, void **out {
if ((*out = malloc(sizeof(int))) {
return 1;
}
**((_int_ **) out) = *((_int_ *) key);
return 0;
}
The idea is that I could call a macro, GENERATE_FUNCTIONS("int", "sint") or something like this, and have it generate this function. The italicized parts are what need to be plugged in.
Is this possible?

I don't understand the example function that you are giving very well, but using macros for the task is relatively easy. Just you wouldn't give strings to the macro as arguments but tokens:
#define DECLARE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg)
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
}
You may then use this to declare the functions in a header file
DECLARE_MY_COPY_FUNCTION(unsigned, toto);
DECLARE_MY_COPY_FUNCTION(double, hui);
and define them in a .c file:
DEFINE_MY_COPY_FUNCTION(unsigned, toto);
DEFINE_MY_COPY_FUNCTION(double, hui);
In this version as stated here you might get warnings on superfluous `;'. But you can get rid of them by adding dummy declarations in the macros like this
#define DEFINE_MY_COPY_FUNCTION(TYPE, SUFFIX) \
int copy_function_ ## SUFFIX(unsigned count, TYPE* arg) { \
/* do something with TYPE */ \
return whatever; \
} \
enum { dummy_enum_for_copy_function_ ## SUFFIX }

Try something like this (I just tested the compilation, but not the result in an executed program):
#include "memory.h"
#define COPY_KEY(type, name) \
type name(void *key, void **args, int argc, void **out) { \
if (*out = malloc(sizeof(type))) { \
return 1; \
} \
**((type **) out) = *((type *) key); \
return 0; \
} \
COPY_KEY(int, copy_key_sint)
For more on the subject of generic programming in C, read this blog wich contains a few examples and also this book which contains interesting solutions to the problem for basic data structures and algorithm.

That should work. To create copy_key_sint, use copy_key_ ## sint.
If you can't get this to work with CPP, then write a small C program which generates a C source file.

Wouldn't a macro which just takes sizeof(*key) and calls a single function that uses memcpy be a lot cleaner (less preprocessor abuse and code bloat) than making a new function for each type just so it can do a native assignment rather than memcpy?
My view is that the whole problem is your attempt to apply C++ thinking to C. C has memcpy for a very good reason.

Related

C Macros function definition syntax question

I've been looking through a program called hickit, and at one point (count.c, function starts at line 105), and they call a macros function (kavl_insert) from the Klib library as follows:
static void hk_count_nei2_core(int32_t n_pairs, struct cnt_nei2_aux *a, int r1, int r2)
{
struct cnt_nei2_aux *root = 0;
int32_t i, j, left;
unsigned cl;
left = 0;
kavl_insert(nei2, &root, &a[0], 0);
...
Looking at the Klib library (more specifically, in kavl.h), this function (I think) is defined as follows:
#define __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \
__scope __type *kavl_insert_##suf(__type **root_, __type *x, unsigned *cnt_) { \
Later on in the kavl.h file there is this standalone line (line 322):
#define kavl_insert(suf, proot, x, cnt) kavl_insert_##suf(proot, x, cnt)
I don't have much technical knowledge with C (just learned parts as they were relevant), and I'm wondering how this works. The casing is different, and there is the "__" precursor in the #define line. How does this work?
The first __KAVL_INSERT macro is used to declare functions which all start with the same prefix (kavl_insert_) and end with the specified suffix (parameter suf).
So, when you see this:
__KAVL_INSERT(foo, static, int, null, null)
preprocessor will replace it with a function with the appropriate name, scope, and parameter types:
static int *kavl_insert_foo(int **root_, int *x, unsigned *cnt_) { \
/* actual function body ... */ \
/* with lots of trailing backshashes ... */ \
/* because it's the only way to create ... */ \
/* a multiline macro in C */ \
}
The lowercase kavl_insert macro, on the other hand:
kavl_insert(foo, &something, &whatever, 0);
simply expands to the actual function call, i.e. it's equivalent to calling the function defined above:
kavl_insert_foo(&something, &whatever, 0);
The idea behind this kind of macros is usually to create a generic type-safe data structure in C, using the preprocessor, like the klib library of various generic data structures.

Multiple definition of function in the same place

I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
When I try to compile, I get the following errors:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.
Also I need to compile with -std=c99 if that matters in this case.
A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.
An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).
The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.
This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.
Another way (relative to the proposed by Groo) is to create two macros.
__matrix_allocator_declare with just prototype of function -- for h-file(s)
__matrix_allocator_define with function body -- for one (selected by you) c-file
This way requires to handle two macros and to not forget add function-body macro in some file, but (and it is more important for embedded applications on small microcontrollers) it guarantees that only one function instance will consume memory.

Any trick for simpler definition of multiline C macros?

I am trying to write some reusable generic type-safe code in C, using macros, similar to how klib works:
#define Fifo_define(TYPE) \
\
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE; \
\
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) { \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
// define macros
#define Fifo(TYPE) Fifo_##TYPE
#define Fifo_init(TYPE, capacity) Fifo_##TYPE_init(capacity)
And then I just use it with any type parameter:
Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);
However, writing this is rather convoluted and error prone, with no IDE editor support (IntelliSense), so I wondered if there are any tricks which might allow me to (perhaps) add a few defines and then include the file, without having to end each line with \?
Something like:
// no idea how to do this, just checking if similar concept is possible
#define FIFO_TYPE int
#define FIFO_NAME Fifo_int
#include <generic-fifo.h>
#undef FIFO_NAME
#undef FIFO_TYPE
And I would somehow get all the right structs and functions. The problem is that there is a lot of parameter concatenation in these macros, so I am not sure if this can be done in a simpler manner than the first snippet?
Not really recommended in this case, but you can do something like what you want to achieve with X-macros:
#define SUPPORTED_TYPES \
X(int) \
X(double) \
X(char)
#define X(TYPE) \
typedef struct { \
TYPE *head; \
TYPE *tail; \
size_t capacity; \
} Fifo_##TYPE, *pFifo_##TYPE;
SUPPORTED_TYPES
#undef X
#define X(TYPE) \
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) \
{ \
Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
TYPE * data = calloc(capacity, sizeof(TYPE)); \
fifo->head = data; \
fifo->tail = data; \
fifo->capacity = capacity; \
}
SUPPORTED_TYPES
#undef X
But this didn't really improve the situation all that much. It got rid of the need for a single, ugly Fifo_define macro, so you can split up the code in several sections. But the macro mess remains.
I would recommend some completely different approach. Two suggestions:
Handle the type-generic things in the classic C way, in run-time. Use callbacks. Keep track of the used type with an enum, if needed.
C11 _Generic allows all kinds of type safety tricks and can be used to phase out such messy macros. Example that implements "functors". The macro itself is kept minimal and the different implementations for various types is typed out. (That's usually what you end up doing anyway, when you do type-generic programming.)
If you are using complex macros, consider using m4 instead of the C pre-processor. m4 is similar to the C pre-processor but is much more powerful and can do things like have multiple lines without a line continuation character.
Using code generators like m4 is called meta-programming.
Using m4 in C can be accomplished by treating it as a pre-pre-processor like this:
% grep -v '#include' file1 file2 | m4 > outfile
% m4 file1 file2 | cc
Since m4 works in a similar way to the C pre-processor at the basic level, it will generally convert any ordinary C macros correctly in addition to supporting its own advanced features.

How to implement a generic macro in C?

FUNC(param);
When param is char *,dispatch to func_string.
when it's int,dispatch to func_int
I think there may be a solution to this,as variable types are known at compile time..
This will be possible with C1X but not in the current standard.
It will look like this:
#define cbrt(X) _Generic((X), long double: cbrtl, \
default: cbrt, \
float: cbrtf)(X)
Variable types are known to the compiler, but not to the preprocessor (which sees the code simply as unstructured text a stream of tokens, and performs only simple replacement operations on it). So I am afraid you can't achieve this with C macros.
In C++, they invented templates to solve such problems (and more).
You can test for the characteristics of the types.
For example, int can hold a negative value, while char* can't. So if ((typeof(param))-1) < 0, param is unsigned:
if (((typeof(param))-1) < 0) {
do_something_with_int();
} else {
do_something_with_char_p();
}
The compiler obviously optimizes this out.
Try it here: http://ideone.com/et0v1
This would be even easier if the types had different sizes. For example, if you want to write a generic macro than can handle different character sizes:
if (sizeof(param) == sizeof(char)) {
/* ... */
} else if (sizeof(param) == sizeof(char16_t)) {
/* ... */
} else if (sizeof(param) == sizeof(char32_t)) {
/* ... */
} else {
assert("incompatible type" && 0);
}
GCC has a __builtin_types_compatible_p() builtin function that can check for types compatibility:
if (__builtin_types_compatible_p(typeof(param), int)) {
func_int(param);
} else if (__builtin_types_compatible_p(typeof(param), char*)) {
func_string(param);
}
Try it here: http://ideone.com/lEmYE
You can put this in a macro to achieve what you are trying to do:
#define FUNC(param) ({ \
if (__builtin_types_compatible_p(typeof(param), int)) { \
func_int(param); \
} else if (__builtin_types_compatible_p(typeof(param), char*)) { \
func_string(param); \
} \
})
(The ({...}) is a GCC's statement expression, it allows a group of statements to be a rvalue.
The __builtin_choose_expr() builtin can choose the expression to compile. With __builtin_types_compatible_p this allows to trigger an error at compile-time if the type of param is not compatible with both int and char*: (by compiling somehting invalid in this case)
#define FUNC(param) \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \
, func_int(param) \
, __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \
, func_string(param) \
, /* The void expression results in a compile-time error \
when assigning the result to something. */ \
((void)0) \
) \
)
This is actually a slightly modified example from __builtin_choose_expr docs.
There is no possibility to run time check types in C89 / ANSI C, but there is an extension to gcc which allows it. typeof or something along those lines if I remember. I saw it in the Linux Kernel once.
In kernel.h:
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
Take a look at this article: GCC hacks in the Linux kernel
When I first saw this I actually asked a question here on SO about:
min macro in kernel.h
I'm not quite sure exactly how you would use it to solve your problem, but it's something worth taking a look at.
You can't do this with a macro. Macro's value are substituted at compile time and are not intepreted. They are just substitutions.
Variable types are indeed known at compile time, however macro expansion takes place before compilation. I suggest you implement 2 overloaded functions instead of a macro.
my definition of a generic:
a structured abstract type which can only be fully defined with an input of other concrete types
this sounds exactly like a macro to me
pardon the psudo c code, my c is rusty
#include <stdio.h>
// todo: ret=self needs vec3##generic_t##_copy(self, ret);
// not to mention we should probably be using __builtin_add_overflow
// __builtin_add_overflow might actually itself be a reasonably generics method example
// please bear with me
#define GENERIC_VEC3_ADD(generic_t) \
generic_t vec3##generic_t##_add(generic_t self, generic_t other) {\
generic_t ret = self;\
ret[0] += other [0];;\
ret[1] += other [1];\
ret[2] += other [2];\
return ret;\
}
#define GENERIC_VEC3_FREPR(generic_t, printf_ts) \
int vec3##generic_t##_frepr(generic_t self, FILE fd)\
rerurn fprintf(fd, "<vec3##generic_t (##printf_ts##, printf_ts##, printf_ts##)>", \
self[0], self[1], self[2]);\
}
// here is the generic typedef, with some methods
#define GENERIC_VEC3(genetic_t, printf_ts) \
typedef vec3##generic_t generic_t[3];\
GENERIC_VEC3_ADD(generic_t) \
GENERIC_VEC3_FREPR(generic_t, printf_ts)
// later we decide what types we want this genic for
GENERIC_VEC3(int, %ul)
// and use our generic
int main()
{
vec3int foo = { 1, 2, 3 };;
vec3int bar = { 1, 2, 3 };;
vec3int sum = vec3int_add(foo, bar);
vec3int_frepr(sum, stderr);
fprintf(stderr, "\n");
exit EXIT_SUCCESS;
}

Get a pointer to the current function in C (gcc)?

is there a magic variable in gcc holding a pointer to the current function ?
I would like to have a kind of table containing for each function pointer a set of information.
I know there's a __func__ variable containing the name of the current function as a string but not as a function pointer.
This is not to call the function then but just to be used as an index.
EDIT
Basically what i would like to do is being able to run nested functions just before the execution of the current function (and also capturing the return to perform some things.)
Basically, this is like __cyg_profile_func_enter and __cyg_profile_func_exit (the instrumentation functions)... But the problem is that these instrumentation functions are global and not function-dedicated.
EDIT
In the linux kernel, you can use unsigned long kallsyms_lookup_name(const char *name) from include/linux/kallsyms.h ... Note that the CONFIG_KALLSYMS option must be activated.
void f() {
void (*fpointer)() = &f;
}
Here's a trick that gets the address of the caller, it can probably be cleaned up a bit.
Relies on a GCC extension for getting a label's value.
#include <stdio.h>
#define MKLABEL2(x) label ## x
#define MKLABEL(x) MKLABEL2(x)
#define CALLFOO do { MKLABEL(__LINE__): foo(&&MKLABEL(__LINE__));} while(0)
void foo(void *addr)
{
printf("Caller address %p\n", addr);
}
int main(int argc, char **argv)
{
CALLFOO;
return 0;
}
#define FUNC_ADDR (dlsym(dlopen(NULL, RTLD_NOW), __func__))
And compile your program like
gcc -rdynamic -o foo foo.c -ldl
I think you could build your table using strings (the function names) as keys, then look up by comparing with the __func__ builtin variable.
To enforce having a valid function name, you could use a macro that gets the function pointer, does some dummy operation with it (e.g. assigning it to a compatible function type temporary variable) to check that it's indeed a valid function identifier, and then stringifies (with #) the function name before being used as a key.
UPDATE:
What I mean is something like:
typedef struct {
char[MAX_FUNC_NAME_LENGTH] func_name;
//rest of the info here
} func_info;
func_info table[N_FUNCS];
#define CHECK_AND_GET_FUNC_NAME(f) ({void (*tmp)(int); tmp = f; #f})
void fill_it()
{
int i = -1;
strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(foo));
strcpy(table[++i].func_name, CHECK_AND_GET_FUNC_NAME(bar));
//fill the rest
}
void lookup(char *name) {
int i = -1;
while(strcmp(name, table[++i]));
//now i points to your entry, do whatever you need
}
void foo(int arg) {
lookup(__func__);
//do something
}
void bar(int arg) {
lookup(__func__);
//do something
}
(the code might need some fixes, I haven't tried to compile it, it's just to illustrate the idea)
I also had the problem that I needed the current function's address when I created a macro template coroutine abstraction that people can use like modern coroutine language features (await and async). It compensates for a missing RTOS when there is a central loop which schedules different asynchronous functions as (cooperative) tasks. Turning interrupt handlers into asynchronous functions even causes race conditions like in a preemptive multi-tasking system.
I noticed that I need to know the caller function's address for the final return address of a coroutine (which is not return address of the initial call of course). Only asynchronous functions need to know their own address so that they can pass it as hidden first argument in an AWAIT() macro. Since instrumenting the code with a macro solution is as simple as just defining the function it suffices to have an async-keyword-like macro.
This is a solution with GCC extensions:
#define _VARGS(...) _VARGS0(__VA_ARGS__)
#define _VARGS0(...) ,##__VA_ARGS__
typedef union async_arg async_arg_t;
union async_arg {
void (*caller)(void*);
void *retval;
};
#define ASYNC(FUNCNAME, FUNCARGS, ...) \
void FUNCNAME (async_arg_t _arg _VARGS FUNCARGS) \
GENERATOR( \
void (*const THIS)(void*) = (void*) &FUNCNAME;\
static void (*CALLER)(void*), \
CALLER = _arg.caller; \
__VA_ARGS__ \
)
#define GENERATOR(INIT,...) { \
__label__ _entry, _start, _end; \
static void *_state = (void*)0; \
INIT; \
_entry:; \
if (_state - &&_start <= &&_end - &&_start) \
goto *_state; \
_state = &&_start; \
_start:; \
__VA_ARGS__; \
_end: _state = &&_entry; \
}
#define AWAIT(FUNCNAME,...) ({ \
__label__ _next; \
_state = &&_next; \
return FUNCNAME((async_arg_t)THIS,##__VA_ARGS__);\
_next: _arg.retval; \
})
#define _I(...) __VA_ARGS__
#define IF(COND,THEN) _IF(_I(COND),_I(THEN))
#define _IF(COND,THEN) _IF0(_VARGS(COND),_I(THEN))
#define _IF0(A,B) _IF1(A,_I(B),)
#define _IF1(A,B,C,...) C
#define IFNOT(COND,ELSE) _IFNOT(_I(COND),_I(ELSE))
#define _IFNOT(COND,ELSE) _IFNOT0(_VARGS(COND),_I(ELSE))
#define _IFNOT0(A,B) _IFNOT1(A,,_I(B))
#define _IFNOT1(A,B,C,...) C
#define IF_ELSE(COND,THEN,ELSE) IF(_I(COND),_I(THEN))IFNOT(_I(COND),_I(ELSE))
#define WAIT(...) ({ \
__label__ _next; \
_state = &&_next; \
IF_ELSE(_I(__VA_ARGS__), \
static __typeof__(__VA_ARGS__) _value;\
_value = (__VA_ARGS__); \
return; \
_next: _value; \
, return; _next:;) \
})
#define YIELD(...) do { \
__label__ _next; \
_state = &&_next; \
return IF(_I(__VA_ARGS__),(__VA_ARGS__));\
_next:; \
} while(0)
#define RETURN(VALUE) do { \
_state = &&_entry; \
if (CALLER != 0) \
CALLER((void*)(VALUE +0));\
return; \
} while(0)
#define ASYNCALL(FUNC, ...) FUNC ((void*)0,__VA_ARGS__)
I know, a more portable (and maybe secure) solution would use the switch-case statement instead of label addresses but I think, gotos are more efficient than switch-case-statements. It also has the advantage that you can use the macros within any other control structures easily and break will have no unexpected effects.
You can use it like this:
#include <stdint.h>
int spi_start_transfer(uint16_t, void *, uint16_t, void(*)());
#define SPI_ADDR_PRESSURE 0x24
ASYNC(spi_read_pressure, (void* dest, uint16_t num),
void (*callback)(void) = (void*)THIS; //see here! THIS == &spi_read_pressure
int status = WAIT(spi_start_transfer(SPI_ADDR_PRESSURE,dest,num,callback));
RETURN(status);
)
int my_gen() GENERATOR(static int i,
while(1) {
for(i=0; i<5; i++)
YIELD(i);
}
)
extern volatile int a;
ASYNC(task_read, (uint16_t threshold),
while(1) {
static uint16_t pressure;
int status = (int)AWAIT(spi_read_pressure, &pressure, sizeof pressure);
if (pressure > threshold) {
a = my_gen();
}
}
)
You must use AWAIT to call asynchronous functions for return value and ASYNCALL without return value. AWAIT can only be called by ASYNC-functions. You can use WAIT with or without value. WAIT results in the expression which was given as argument, which is returned AFTER the function is resumed. WAIT can be used in ASYNC-functions only. Keeping the argument with WAIT wastes one new piece of static memory for each WAIT() call with argument though so it is recommended to use WAIT() without argument. It could be improved, if all WAIT calls would use the same single static variable for the entire function.
It is only a very simple version of a coroutine abstraction. This implementation cannot have nested or intertwinned calls of the same function because all static variables comprise one static stack frame.
If you want to solve this problem, you also need to distinguish resuming an old and starting a new function call. You can add details like a stack-frame queue at the function start in the ASYNC macro. Create a custom struct for each function's stack frame (which also can be done within the macro and an additional macro argument). This custom stack frame type is loaded from a queue when entering the macro, is stored back when exiting it or is removed when the call finishes.
You could use a stack frame index as alternative argument in the async_arg_t union. When the argument is an address, it starts a new call or when given a stack frame index it resumes an old call. The stack frame index or continuation must be passed as user-defined argument to the callback that resumes the coroutine.
If you went for C++ the following information might help you:
Objects are typed, functors are functions wrapped as objects, RTTI allows the identification of type at runtime.
Functors carry a runtime overhead with them, and if this is a problem for you I would suggest hard-coding the knowledge using code-generation or leveraging a OO-heirarchy of functors.
No, the function is not aware of itself. You will have to build the table you are talking about yourself, and then if you want a function to be aware of itself you will have to pass the index into the global table (or the pointer of the function) as a parameter.
Note: if you want to do this you should have a consistent naming scheme of the parameter.
If you want to do this in a 'generic' way, then you should use the facilities you already mention (__cyg_profile_func*) since that is what they are designed for. Anything else will have to be as ad hoc as your profile.
Honestly, doing things the generic way (with a filter) is probably less error prone than any new method that you will insert on-the-fly.
You can capture this information with setjmp(). Since it saves enough information to return to your current function, it must include that information in the provided jmp_buf.
This structure is highly nonportable, but you mention GCC explicitly so that's probably not a blocking issue. See this GCC/x86 example to get an idea how it roughly works.
If you want to do code generation I would recomend GSLGen from Imatix. It uses XML to structure a model of your code and then a simple PHP like top-down generation language to spit out the code -- it has been used to generate C code.
I have personally been toying arround with lua to generate code.
static const char * const cookie = __FUNCTION__;
__FUNCTION__ will be stored at the text segment at your binary and a pointer will always be unique and valid.
Another option, if portability is not an issue, would be to tweak the GCC source-code... any volunteers?!
If all you need is a unique identifier for each function, then at the start of every function, put this:
static const void * const cookie = &cookie;
The value of cookie is then guaranteed to be a value uniquely identifying that function.

Resources