inlining callbacks question

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux