On Tue, Jun 19, 2012 at 4:41 AM, Daniel Santos <danielfsan...@att.net> wrote:
> 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.

The question this boils down to is - what is a constant?  The current
implementation is pretty clear (see builtins.c:fold_builtin_constant_p)
and excludes any addresses of entities (being functions or variables).
Which probably asks for a new builtin to verify this, not over-loading
__builtin_constant_p.

> 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
>     */

I think that would be essentially the same as declaring myfunc
with attribute always-inline.  You'd get an error if the function pointer
turns into a direct call and is not inlined.

Richard.

>    fnptr(0);
> }
>
> int main(int argc, char *argv[]) {
>    jack(myfunc);
> }
>
> Thanks
> Daniel

Reply via email to