Yes, my topic sounds crazy huh?  But you guys made it possible when you
started optimizing out constant function pointers. (Thank you!!) This
didn't mature to "full power" until 4.6.? (works in 4.6.2, not sure
about earlier 4.6).  Now that you can populate a struct with const
pointers to inline functions and pass a pointer to that struct to a
generic inline function, full C type-injection is now possible. (Well,
you probably didn't need to be able to do it via a struct, but it sure
cleans up the interface).

Example here: http://lwn.net/Articles/500757/ (patches last sent to LKML
on June 7th, don't have them posted elsewhere atm, sorry)

However, the process of verifying that your calls by
constant-function-pointer (much less, one that is a struct member) is
one of examining the generated code, since __builtin_constant_p will
always return zero when passed a function pointer (or any pointer I've
given it thus far).  This simple program demonstrates the problem:

#include <stdio.h>
static inline int myfunc(int a) {
    return a + 42;
}

static int (*const myptr)(int) = myfunc;

int main(int argc, char *argv[]) {
    printf("is const = %d\n", __builtin_constant_p(myptr));
    /* same result if I dereference it: __builtin_constant_p(*myptr) */
}

So before filing any feature request bugs, I figured I should bring my
discussion here first, as I believe some enhancements to gcc can better
enable this type of programming.

First off, we need a mechanism to verify constness of a function pointer
at build time and generate an error when the value is non-const, similar
to the construct:

#define BUILD_BUG_ON_NON_CONST(arg)                   \
do {                                                  \
    extern void __value_non_constant(void)            \
        __attribute__((error("value not constant"))); \
    if (!__builtin_constant_p(arg))                   \
        __not_constant_error();                       \
} while (0)

Second, it will be helpful to have a mechanism to generate a -Winline
warning when a function call by pointer cannot be inlined.  Obviously,
this is impossible if you can't first determine that it's a const
function pointer and resolve that to the actual function.  I'm sorry to
say that I don't have a suggestion for doing this other than some
__builtin_isinlineable() type of function (that accepts a function
pointer).  Perhaps solving the above problem and assuring that, after
this test for function pointer constness succeeds and the const function
pointer can be resolved to an inline function, the compiler can just
emit a warning as it would when a normal function call to an inline
cannot be inlined.  Here's an example:

#include <stdio.h>
static inline int myfunc(int a) {
    return a + 42;
}

static inline void jack(int (*const fnptr)(int)) {
    /* macro from above, except working for function pointers */
    BUILD_BUG_ON_NON_CONST(fnptr);

    /* if the above test passes, any inability to inline myfunc should
     * produce a -Winline warning
     */
    fnptr(0);
}

int main(int argc, char *argv[]) {
    jack(myfunc);
}

Thanks
Daniel

Reply via email to