[FFmpeg-devel] Moving if(constant expression) to preprocessor?

Axel Holzinger aholzinger
Sun Sep 19 18:14:49 CEST 2010


M?ns Rullg?rd wrote:
> "Axel Holzinger" <aholzinger at gmx.de> writes:
> 
> > M?ns Rullg?rd wrote:
> >> "Axel Holzinger" <aholzinger at gmx.de> writes:
> >> 
> >> > Hi M?ns and all,
> >> >
> >> > M?ns Rullg?rd wrote:
> >> >> "Axel Holzinger" <aholzinger at gmx.de> writes:
> >> >> 
> >> >> > Hi all,
> >> >> >
> >> >> > if compiling FFmpeg code with zero optimisations 
> (even without 
> >> >> > dead code elimination) there are linker errors (undefined 
> >> >> > references to functions or structs) that come from
constructs 
> >> >> > like i.e.  the following in libavcodec/allcodecs.c:
> >> >> >
> >> >> > if(CONFIG_##X##_HWACCEL) av_register_hwaccel(&x##_hwaccel);
}
> >> >> >
> >> >> > The runtime (lower case) "if" leads to an undefined 
> reference, 
> >> >> > because it is evaluated at runtime and not at compile time.
> >> >> >
> >> >> > If dead code eliminitation optimisation is on, this isn't an

> >> >> > issue, but with optimisations completely off it is.
> >> >> 
> >> >> > Then I would try and find a solution based on 
> preprocessor magic.
> >> >> 
> >> >> That is not easily possible.
> >> >
> >> > Says who ;-)
> >> 
> >> Says I.
> >
> > And that has to suffice?
> 
> Yes.
> 
> >> > It is possible to write a macro that does the trick and 
> in the end 
> >> > the above line would for example look like this:
> >> >
> >> > AV_COND_IF(CONFIG_##X##_HWACCEL, 
> >> > (av_register_hwaccel(&x##_hwaccel)),)
> >> 
> >> How would AV_COND_IF be defined?
> >
> > Do you know boost?
> 
> I have encountered the monstrosity.

It's a library. Use what you like, let the rest stay away. Perhaps
just try it out and make your own experiences. But that's OT here.
 
> > They have a really nice preprocessor library.
> 
> Boost and nice are mutually exclusive.

M?ns Rullg?rd and nice are mutually exclusive. Does this help?

> > I got inspired by their BOOST_PP_IF macro.
> >
> > It's more generic as it would be needed here. So reduced to what's

> > needed it could look like this (compiler specific #fdefs removed
for
> > clarity):
> 
> What compiler-specifics would be involved here?  FFmpeg uses 
> only standard C99 features in non-optional code.
> 
> > # define ICL_PP_IF(cond, t, f) ICL_PP_IF_I(cond, t, f) # define 
> > ICL_PP_IF_I(cond, t, f) ICL_PP_IIF(ICL_PP_BOOL(cond), t, f)
> >
> > #else
> >
> > #define AV_COND_IF(bit, t, f) AV_COND_IF_OO((bit, t, f)) #define 
> > AV_COND_IF_OO(par) AV_COND_IF_I ## par
> 
> This is not valid C.  See C99 spec section 6.10.3.3 The ## operator:
> 
>   If the result is not a valid preprocessing token, the behavior is
>   undefined.
> 
> You are attempting to concatenate the token AV_COND_IF_I with 
> a left parenthesis, which combination is not a valid single token.
> 
> > #define AV_COND_IF_I(bit, t, f) AV_COND_IF_I(AV_COND_IIF_ ##
bit(t, 
> > f)) #define AV_COND_IF_I(id) id
> 
> Quoting the spec again:
> 
>   [...] an identifier currently defined as a function-like macro
shall
>   not be redefined by another #define preprocessing directive unless
>   the second definition is a function-like macro definition that has
>   the same number and spelling of parameters, and the two
replacement
>   lists are identical.
> 
> > #define AV_COND_IF_0(t, f) f
> > #define AV_COND_IF_1(t, f) t

Here is the code that works and that's tested with gcc:

#define AV_COND_IIF(bit, t, f) AV_COND_IIF_I(bit, t, f)
#define AV_COND_IIF_I(bit, t, f) AV_COND_IIF_II(AV_COND_IIF_ ## bit(t,
f))
#define AV_COND_IIF_II(id) id
#define AV_COND_IIF_0(t, f) f
#define AV_COND_IIF_1(t, f) t
#define AV_COND_BOOL(x) AV_COND_BOOL_I(x)
#define AV_COND_BOOL_I(x) AV_COND_BOOL_ ## x
#define AV_COND_BOOL_0 0
#define AV_COND_BOOL_1 1
#define AV_COND_IF(cond, t, f) AV_COND_IIF(AV_COND_BOOL(cond), t, f)

Nothing is redefined.

> I see what you are trying to do, but the way you are doing it 
> does not work.  With a few more layers of macros it would 
> actually work, at least in trivial cases.

see above

Usage:
Before:
#define REGISTER_HWACCEL(X,x) { \
          extern AVHWAccel x##_hwaccel; \
          if(CONFIG_##X##_HWACCEL) av_register_hwaccel(&x##_hwaccel);
}

With the macro:
#define REGISTER_HWACCEL(X,x) { \
          extern AVHWAccel x##_hwaccel; \
          AV_COND_IF(CONFIG_##X##_HWACCEL,
(av_register_hwaccel(&x##_hwaccel)),) ; }

> However, it is far more convoluted than the current code

What?

> for no gain,

It makes it possible to completely disable optimisations. To date the
configure script offers to disable optimisations, but doesn't do so.
One could call this a bug, at least it relies on compiler specifics
that are not mandated by C99.

> and Reimar's comments are valid too.

I think Reimar's comments are beside the point. The only thing the
compiler does, if a runtime if is used instead of a macro, is that it
checks the syntax of the call, nothing else.

> > Isn't that sexy?
> 
> No.

I think we might also disagree on real sexy girls.

Axel




More information about the ffmpeg-devel mailing list