inlining callbacks question

Christopher Layne clayne@anodized.com
Sun Feb 11 14:02:00 GMT 2007


Given this simple toy code:

/* */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct cbt__ cbt;
typedef void (*cbt_cb_display)(cbt *);

struct cbt__ {
        char *text;
        cbt_cb_display display;
};

static void cbt_display(cbt *c)
{
        fprintf(stdout, "c->text == %s\n", c->text);

        return;
}

extern cbt *cbt_new(void)
{
        cbt *c;

        c = malloc(sizeof *c);
        c->text = NULL;
        c->display = cbt_display;

        return c;
}

int main(int argc, char **argv)
{
        cbt *c;

        if (argc <= 1) return EXIT_FAILURE;

        c = cbt_new();
        c->text = argv[1];
#ifdef CB
        c->display(c);
#else
        cbt_display(c);
#endif

        return 0;
}
/* */

I notice that it seems impossible to get that callback to ever be inlined.

$ gcc -DCB -W -Wall -pedantic -O2 -S -o /dev/stdout cb.c
[...]
        movl    %eax, (%esp)
        call    *4(%eax)
        xorl    %eax, %eax
[...]

$ gcc -DCB -W -Wall -pedantic -O3 -S -o /dev/stdout cb.c
[...]
        movl    %eax, (%esp)
        call    cbt_display
        xorl    %eax, %eax
[...]

Okay, better.. but remove all use of the callback and call directly:

$ gcc -W -Wall -pedantic -O3 -S -o /dev/stdout cb.c
[...]
        movl    %edx, 8(%esp)
        movl    $.LC0, %edx
        movl    %edx, 4(%esp)
        movl    stdout, %eax
        movl    %eax, (%esp)
        call    fprintf
        xorl    %eax, %eax
[...]

Is it impossible for gcc to inline this? It should seem doable considering
that the callback function is directly accessible to the compiler and even
within the same module. Is the issue related to the fact that the function
pointer is not read-only? If so, I would expect it to always result in:

call *4(%eax)

But since I do see it calls the function directly, I'm wondering if there is
a way to inline these simple callbacks. I don't exactly know how to get the
function pointer to be const and assign to it within cbt_new(), other then
using a statically defined default and memcpy(c, &cbt_default, sizeof *c).
But this seems hardly portable, and it also doesn't result in anything
useful as far as the goal.

-cl



More information about the Gcc-help mailing list