diff mbox

[RFC,10/19] target-alpha: Refactor debug output macros

Message ID 1359293537-8251-11-git-send-email-afaerber@suse.de
State New
Headers show

Commit Message

Andreas Färber Jan. 27, 2013, 1:32 p.m. UTC
Make LOG_DISAS() arguments compile-testable even if disabled.

Signed-off-by: Andreas Färber <afaerber@suse.de>
---
 target-alpha/translate.c |   12 ++++++------
 1 Datei geändert, 6 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)

Comments

Richard Henderson Jan. 28, 2013, 6:22 p.m. UTC | #1
On 01/27/2013 05:32 AM, Andreas Färber wrote:
> Make LOG_DISAS() arguments compile-testable even if disabled.
>
> Signed-off-by: Andreas Färber <afaerber@suse.de>
> ---
>   target-alpha/translate.c |   12 ++++++------
>   1 Datei geändert, 6 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)

Acked-by: Richard Henderson <rth@twiddle.net>

> +#define LOG_DISAS(...) G_STMT_START \
> +    if (ALPHA_DEBUG_DISAS) { \
> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
> +    } \
> +    G_STMT_END

I see zero advantage to using G_STMT_START/END over the
shorter and significantly more obvious direct use of do/while.

We just zapped useless gtype typedefs.  Do we have to add
yet another useless glib thing?


r~
Peter Maydell Jan. 28, 2013, 6:29 p.m. UTC | #2
On 28 January 2013 18:22, Richard Henderson <rth@twiddle.net> wrote:
> On 01/27/2013 05:32 AM, Andreas Färber wrote:
>> +#define LOG_DISAS(...) G_STMT_START \
>> +    if (ALPHA_DEBUG_DISAS) { \
>> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
>> +    } \
>> +    G_STMT_END
>
>
> I see zero advantage to using G_STMT_START/END over the
> shorter and significantly more obvious direct use of do/while.

Strong agreement -- G_STMT_START/END is just pointless
obfuscation without even the rationale of matching a
glib interface.

-- PMM
Andreas Färber Jan. 28, 2013, 6:54 p.m. UTC | #3
Am 28.01.2013 19:22, schrieb Richard Henderson:
> On 01/27/2013 05:32 AM, Andreas Färber wrote:
>> Make LOG_DISAS() arguments compile-testable even if disabled.
>>
>> Signed-off-by: Andreas Färber <afaerber@suse.de>
>> ---
>>   target-alpha/translate.c |   12 ++++++------
>>   1 Datei geändert, 6 Zeilen hinzugefügt(+), 6 Zeilen entfernt(-)
> 
> Acked-by: Richard Henderson <rth@twiddle.net>
> 
>> +#define LOG_DISAS(...) G_STMT_START \
>> +    if (ALPHA_DEBUG_DISAS) { \
>> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
>> +    } \
>> +    G_STMT_END
> 
> I see zero advantage to using G_STMT_START/END over the
> shorter and significantly more obvious direct use of do/while.

Well, I see close to zero advantage in using a loop at all. We could
just as well review all callers and just code the pure logic. An inline
function by comparison would relieve us from all that \ ugliness, too.

> We just zapped useless gtype typedefs.  Do we have to add
> yet another useless glib thing?

We didn't. It was proposed and rejected in that form.

Andreas
Peter Maydell Jan. 28, 2013, 6:59 p.m. UTC | #4
On 28 January 2013 18:54, Andreas Färber <afaerber@suse.de> wrote:
> Am 28.01.2013 19:22, schrieb Richard Henderson:
>> On 01/27/2013 05:32 AM, Andreas Färber wrote:
>>> +#define LOG_DISAS(...) G_STMT_START \
>>> +    if (ALPHA_DEBUG_DISAS) { \
>>> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
>>> +    } \
>>> +    G_STMT_END
>>
>> I see zero advantage to using G_STMT_START/END over the
>> shorter and significantly more obvious direct use of do/while.
>
> Well, I see close to zero advantage in using a loop at all.

Er, what? "do ... while (0)" is completely standard practice
for writing robust macros in C. Patches which don't do that
should fail code review.

> An inline function by comparison would relieve us from
> all that \ ugliness, too.

This is a completely separate argument.
 C macro with do..while(0): OK
 inline function: also OK
 C macro missing do..while(0) protection: not OK
 C macro using glib obfuscated macros: also not OK

-- PMM
Andreas Färber Jan. 28, 2013, 7:02 p.m. UTC | #5
Am 28.01.2013 19:29, schrieb Peter Maydell:
> On 28 January 2013 18:22, Richard Henderson <rth@twiddle.net> wrote:
>> On 01/27/2013 05:32 AM, Andreas Färber wrote:
>>> +#define LOG_DISAS(...) G_STMT_START \
>>> +    if (ALPHA_DEBUG_DISAS) { \
>>> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
>>> +    } \
>>> +    G_STMT_END
>>
>>
>> I see zero advantage to using G_STMT_START/END over the
>> shorter and significantly more obvious direct use of do/while.
> 
> Strong agreement -- G_STMT_START/END is just pointless
> obfuscation without even the rationale of matching a
> glib interface.

I happened to know them from another project and think their semantic is
much more clear if you read them out loud: statement start .. end vs. do
... while zero. We don't semantically want a loop, we use it as error
detection tool, it could just as well be (__extension__({...})) or
whatever funkiness of the day there is. :) A macro can be redefined,
replacing do { ... } while (0) is manual work.

I wouldn't mind a Q... or QEMU_... macro if you oppose the G, but best
if we can avoid it in the first place!

Andreas
Andreas Färber Jan. 28, 2013, 7:14 p.m. UTC | #6
Am 28.01.2013 19:59, schrieb Peter Maydell:
> On 28 January 2013 18:54, Andreas Färber <afaerber@suse.de> wrote:
>> Am 28.01.2013 19:22, schrieb Richard Henderson:
>>> On 01/27/2013 05:32 AM, Andreas Färber wrote:
>>>> +#define LOG_DISAS(...) G_STMT_START \
>>>> +    if (ALPHA_DEBUG_DISAS) { \
>>>> +        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
>>>> +    } \
>>>> +    G_STMT_END
>>>
>>> I see zero advantage to using G_STMT_START/END over the
>>> shorter and significantly more obvious direct use of do/while.
>>
>> Well, I see close to zero advantage in using a loop at all.
> 
> Er, what? "do ... while (0)" is completely standard practice
> for writing robust macros in C. Patches which don't do that
> should fail code review.

Oh really? None of our QOM cast macros use it, they passed your review,
and there is zero reason to bring that plague upon us for any reasonably
small macro. Anything larger in most use cases outside core TCG code is
an overuse of macros.

Misusing the memread() macros for instance gives you weird compiler
messages simply because it is in fact seeing qtest_memread() instead
with 1-shifted arguments. Those should be static inline functions
accessing a global variable IMO.

I simply didn't think of va_list here when hacking this RFC together.

Andreas

>> An inline function by comparison would relieve us from
>> all that \ ugliness, too.
> 
> This is a completely separate argument.
>  C macro with do..while(0): OK
>  inline function: also OK
>  C macro missing do..while(0) protection: not OK
>  C macro using glib obfuscated macros: also not OK
> 
> -- PMM
Peter Maydell Jan. 28, 2013, 9:10 p.m. UTC | #7
On 28 January 2013 19:14, Andreas Färber <afaerber@suse.de> wrote:
> Am 28.01.2013 19:59, schrieb Peter Maydell:
>> Er, what? "do ... while (0)" is completely standard practice
>> for writing robust macros in C. Patches which don't do that
>> should fail code review.
>
> Oh really? None of our QOM cast macros use it, they passed your review,
> and there is zero reason to bring that plague upon us for any reasonably
> small macro.

Sorry, I didn't expand that fully because I thought it was
obvious that I didn't mean "apply this to every macro in QEMU".
To be clear:

This is a standard practice for writing a robust macro, but
by "standard practice" I mean "putting in the do..while
in the places where the practice states that it is required",
not "wrapping every single #define in it even when that makes
no sense".

Specifically, the loop is required where the macro:
 1. expands to several C statements, or a complex statement
    like an "if"
 2. is used in a way that the user expects it to act like a
    C function, ie as if it were a single C statement

and the rationale is that it is easy for users to use such
a macro in contexts like
 if (foo)
     MY_MACRO();
 else
     something;

and get confusing errors or unintended behaviour.
(Yes, I know qemu's coding style would mandate braces; not all
our code has braces and in any case it is good defensive
programming practice to make the macro robust to minor
style issues in its users.)

Therefore, when in QEMU we have macros which meet the
above conditions, we should follow this standard practice.

The QOM cast macros do not meet condition 1 above
(they expand to a single simple expression). Nor does
memread(). These examples are therefore irrelevant to this
discussion. Other weird cases like macros which expand
to entire function definitions don't meet condition 2 because
they don't "look like" simple C functions, so they are also
not relevant here.

> Anything larger in most use cases outside core TCG code is
> an overuse of macros.

This is (again) a completely different discussion. If you want
to suggest that we should in general make more use of inline
functions rather than macros then yes, I agree with you.
All I am saying is that
 1. if and when we do use complex macros we need to get them right!
 2. we should do this in the standard way that would be recognised
    by any C programmer who's dealt with the issue before, not
    with bizarre glib specific macros which obscure what's actually
    going on

-- PMM
Markus Armbruster Jan. 29, 2013, 8:11 a.m. UTC | #8
Peter Maydell <peter.maydell@linaro.org> writes:

> On 28 January 2013 19:14, Andreas Färber <afaerber@suse.de> wrote:
>> Am 28.01.2013 19:59, schrieb Peter Maydell:
>>> Er, what? "do ... while (0)" is completely standard practice
>>> for writing robust macros in C. Patches which don't do that
>>> should fail code review.
>>
>> Oh really? None of our QOM cast macros use it, they passed your review,
>> and there is zero reason to bring that plague upon us for any reasonably
>> small macro.
>
> Sorry, I didn't expand that fully because I thought it was
> obvious that I didn't mean "apply this to every macro in QEMU".
> To be clear:
>
> This is a standard practice for writing a robust macro, but
> by "standard practice" I mean "putting in the do..while
> in the places where the practice states that it is required",
> not "wrapping every single #define in it even when that makes
> no sense".
>
> Specifically, the loop is required where the macro:
>  1. expands to several C statements, or a complex statement
>     like an "if"
>  2. is used in a way that the user expects it to act like a
>     C function, ie as if it were a single C statement
>
> and the rationale is that it is easy for users to use such
> a macro in contexts like
>  if (foo)
>      MY_MACRO();
>  else
>      something;
>
> and get confusing errors or unintended behaviour.
> (Yes, I know qemu's coding style would mandate braces; not all
> our code has braces and in any case it is good defensive
> programming practice to make the macro robust to minor
> style issues in its users.)
>
> Therefore, when in QEMU we have macros which meet the
> above conditions, we should follow this standard practice.
>
> The QOM cast macros do not meet condition 1 above
> (they expand to a single simple expression). Nor does
> memread(). These examples are therefore irrelevant to this
> discussion. Other weird cases like macros which expand
> to entire function definitions don't meet condition 2 because
> they don't "look like" simple C functions, so they are also
> not relevant here.
>
>> Anything larger in most use cases outside core TCG code is
>> an overuse of macros.
>
> This is (again) a completely different discussion. If you want
> to suggest that we should in general make more use of inline
> functions rather than macros then yes, I agree with you.
> All I am saying is that
>  1. if and when we do use complex macros we need to get them right!
>  2. we should do this in the standard way that would be recognised
>     by any C programmer who's dealt with the issue before, not
>     with bizarre glib specific macros which obscure what's actually
>     going on

Agreed on all counts.
Andreas Färber Jan. 29, 2013, 8:42 a.m. UTC | #9
Am 28.01.2013 22:10, schrieb Peter Maydell:
[lengthy discussion of what may go wrong without do { ... } while (0)]

We seem to to agree to disagree here.

The use of an if (foo) { ... } inside Fred's macro (or my pseudocode?)
was what prompted this whole mess, so there is no need to explain that
to me.

We seem to agree that by badly formulating a macro, bad effects can happen.

Where we disagree is that you suggest that do { ... while (0) is any
better than G_STMT_START ... G_STMT_END. I disagree and find *both*
obscuring the code. I clearly stated why.

Therefore I am interested in a non-obscured solution!

Analysing the reasons for the obscured suggestion:

a) "if (foo) MACRO1(); else MACRO2();" is forbidden by Coding Style.
Thus, if careful review indicates there are no such Coding Style
violations, it is entirely possible not to add any
fault-that-may-not-happen-obscuring macro statements.

b) Working around an issue resulting from hiding C statements inside a
preprocessor macro is totally backwards compared to properly using the C
language in the first place. Its mechanism for reuse are functions, and
for performance considerations static inline functions.

Therefore I disagree with you that b) is not an entirely different
disussion as you repeatedly suggest and that according to a) it is not
*generally* necessary to put do { ... } while (0) into any random macro
that one writes. It depends on the contents and on the context.

FWIW it is pretty similar to the reverse-comparison initiative: It is
addressing an issue that I never run into and that Coding Style
forbidding if ((foo = bar)) { ... } can address just as well, while
keeping things more readable. And that is from my perspective the core
of this discussion: which solution is best *readable*, not what
workaround *may* prevent some kind of error.
Adding parenthesis to avoid operator precedence issues is much less
invasive from my POV than adding two more lines with \ and indentation
inside a macro.

BTW if this discussion were about how to write a single macro inside
alpha code, there would be not much need for this discussion. KVM is
using do { .. } while (0) already. This is about avoiding to
unnecessarily *prescribe* cluttering every single source file in the
tree as you seemed to suggest.

Andreas
Peter Maydell Jan. 29, 2013, 9:56 a.m. UTC | #10
On 29 January 2013 08:42, Andreas Färber <afaerber@suse.de> wrote:
> Am 28.01.2013 22:10, schrieb Peter Maydell:
> Where we disagree is that you suggest that do { ... while (0) is any
> better than G_STMT_START ... G_STMT_END. I disagree and find *both*
> obscuring the code. I clearly stated why.P
>
> Therefore I am interested in a non-obscured solution!

There is none if you want to use a multistatement macro
(which presumably you do because that's what your patch does).
The best you can do is "standard thing that has been done for
decades and that is easily recognisable".

> Analysing the reasons for the obscured suggestion:
>
> a) "if (foo) MACRO1(); else MACRO2();" is forbidden by Coding Style.
> Thus, if careful review indicates there are no such Coding Style
> violations, it is entirely possible not to add any
> fault-that-may-not-happen-obscuring macro statements.

This requires analysis of all the callsites (including any that
may be incoming in not-yet-applied patchsets) -- that's a lot
harder and more error prone than just getting the macro right
in the first place.

> b) Working around an issue resulting from hiding C statements inside a
> preprocessor macro is totally backwards compared to properly using the C
> language in the first place. Its mechanism for reuse are functions, and
> for performance considerations static inline functions.
>
> Therefore I disagree with you that b) is not an entirely different
> disussion as you repeatedly suggest

It clearly is, because *you didn't submit a patch using an inline
function*. The whole reason we're having this argument is that you
submitted a patch that uses a multistatement macro. Feel free
to resubmit something using an inline function if you like. Once
again:

 C macro with do..while(0): OK
 inline function: also OK
 C macro missing do..while(0) protection: not OK
 C macro using glib obfuscated macros: also not OK

This really doesn't seem particularly complicated to me.

-- PMM
Markus Armbruster Jan. 29, 2013, 10:03 a.m. UTC | #11
Andreas Färber <afaerber@suse.de> writes:

> Am 28.01.2013 22:10, schrieb Peter Maydell:
> [lengthy discussion of what may go wrong without do { ... } while (0)]
>
> We seem to to agree to disagree here.
>
> The use of an if (foo) { ... } inside Fred's macro (or my pseudocode?)
> was what prompted this whole mess, so there is no need to explain that
> to me.
>
> We seem to agree that by badly formulating a macro, bad effects can happen.
>
> Where we disagree is that you suggest that do { ... while (0) is any
> better than G_STMT_START ... G_STMT_END. I disagree and find *both*
> obscuring the code. I clearly stated why.

There's a significant difference: "do ... while (0)" is a C idiom, as
Peter pointed out.

> Therefore I am interested in a non-obscured solution!
>
> Analysing the reasons for the obscured suggestion:
>
> a) "if (foo) MACRO1(); else MACRO2();" is forbidden by Coding Style.
> Thus, if careful review indicates there are no such Coding Style
> violations, it is entirely possible not to add any
> fault-that-may-not-happen-obscuring macro statements.

Brittle.

> b) Working around an issue resulting from hiding C statements inside a
> preprocessor macro is totally backwards compared to properly using the C
> language in the first place. Its mechanism for reuse are functions, and
> for performance considerations static inline functions.

Nobody denies inline functions are to be preferred in many cases.

Valid exceptions include cases where we want genericity, which a macro
can easily provide, but an inline function can't.

> Therefore I disagree with you that b) is not an entirely different
> disussion as you repeatedly suggest and that according to a) it is not
> *generally* necessary to put do { ... } while (0) into any random macro
> that one writes. It depends on the contents and on the context.

I don't think Peter suggested to put do ... while (0) into random
macros!  He asked to put it exactly into *statement-like* macros, as per
standard C practice.  Most macros are expression-like.

> FWIW it is pretty similar to the reverse-comparison initiative: It is
> addressing an issue that I never run into and that Coding Style
> forbidding if ((foo = bar)) { ... } can address just as well, while
> keeping things more readable.

No, the true reason we frown on Yoda-comparisons is that they make the
code less readable without buying us anything!  The compiler is more
reliable at flagging comparison vs. assignment accidents than a style
convention could ever be at avoiding them.

>                               And that is from my perspective the core
> of this discussion: which solution is best *readable*, not what
> workaround *may* prevent some kind of error.
> Adding parenthesis to avoid operator precedence issues is much less
> invasive from my POV than adding two more lines with \ and indentation
> inside a macro.

I don't think the do ... while (0) safety guard makes these macros any
uglier than they already (and necessarily) are.  If you want pretty, use
an inline function.  If you must have a macro, and cannot bear "do
... while (0)", consider the GNU C extension for turning statements into
expressions: ({ ... }).

> BTW if this discussion were about how to write a single macro inside
> alpha code, there would be not much need for this discussion. KVM is
> using do { .. } while (0) already. This is about avoiding to
> unnecessarily *prescribe* cluttering every single source file in the
> tree as you seemed to suggest.

I think you're overstating your case.  Statement-like macros should be
rare.
Andreas Färber Jan. 29, 2013, 10:21 a.m. UTC | #12
Am 29.01.2013 11:03, schrieb Markus Armbruster:
> Andreas Färber <afaerber@suse.de> writes:
> 
>> b) Working around an issue resulting from hiding C statements inside a
>> preprocessor macro is totally backwards compared to properly using the C
>> language in the first place. Its mechanism for reuse are functions, and
>> for performance considerations static inline functions.
> 
> Nobody denies inline functions are to be preferred in many cases.
> 
> Valid exceptions include cases where we want genericity, which a macro
> can easily provide, but an inline function can't.
> 
>> Therefore I disagree with you that b) is not an entirely different
>> disussion as you repeatedly suggest and that according to a) it is not
>> *generally* necessary to put do { ... } while (0) into any random macro
>> that one writes. It depends on the contents and on the context.
> 
> I don't think Peter suggested to put do ... while (0) into random
> macros!  He asked to put it exactly into *statement-like* macros, as per
> standard C practice.  Most macros are expression-like.

Quoting PMM from last night:
<<<
"do ... while (0)" is completely standard practice
for writing robust macros in C. Patches which don't do that
should fail code review.
>>>

This is what sparked the most heated part of this debate! I completely
object to this generalized statement without restriction to
statement-like macros.

> I think you're overstating your case.  Statement-like macros should be
> rare.

This RFC was just a beginning. An average 50%+ of per target-*/ files
contained macros that were touched here. Even more files are in hw/. Per
file it was up to ~5 such macro definitions. And my main issue is
deriving a convention for new files from this discussion.

Andreas
Andreas Färber Jan. 29, 2013, 10:34 a.m. UTC | #13
Am 29.01.2013 10:56, schrieb Peter Maydell:
> On 29 January 2013 08:42, Andreas Färber <afaerber@suse.de> wrote:
>> Analysing the reasons for the obscured suggestion:
>>
>> a) "if (foo) MACRO1(); else MACRO2();" is forbidden by Coding Style.
>> Thus, if careful review indicates there are no such Coding Style
>> violations, it is entirely possible not to add any
>> fault-that-may-not-happen-obscuring macro statements.
> 
> This requires analysis of all the callsites (including any that
> may be incoming in not-yet-applied patchsets) -- that's a lot
> harder and more error prone than just getting the macro right
> in the first place.

What I said. Converting these macros required me to review any use of
the defines anyway for possible #ifdef -> #if conversion (which we have
decided against already).

>> b) Working around an issue resulting from hiding C statements inside a
>> preprocessor macro is totally backwards compared to properly using the C
>> language in the first place. Its mechanism for reuse are functions, and
>> for performance considerations static inline functions.
>>
>> Therefore I disagree with you that b) is not an entirely different
>> disussion as you repeatedly suggest
> 
> It clearly is, because *you didn't submit a patch using an inline
> function*.

Then spare your virtual breath and see my reply to Anthony. I clearly
indicated that I intend to adopt his and Alex' proposal in a v2, so this
discussion you're leading here about my v1 patch (for which this was
suggested to me!) is pointless, we are debating general statements and
opinions only.

My opinion is that do { ... } while (0) is stupid in light of other
options, and it is unlikely that anything you reply here will change my
feelings.

> The whole reason we're having this argument is that you
> submitted a patch that uses a multistatement macro. Feel free
> to resubmit something using an inline function if you like. Once
> again:
> 
>  C macro with do..while(0): OK
>  inline function: also OK
>  C macro missing do..while(0) protection: not OK

Disagree, it depends. For random code "not OK".

>  C macro using glib obfuscated macros: also not OK

That's your opinion, possibly that of the majority of QEMU developers,
but not a natural fact if you put it.
Like I said, I don't see much difference to do { ... } while (0).

> This really doesn't seem particularly complicated to me.

No it isn't and it's going nowhere. I would rather spend my time fixing
issues for 1.4 and you haven't reviewed the ARM CPU type rename yet either.

Andreas
Markus Armbruster Jan. 29, 2013, 12:22 p.m. UTC | #14
Andreas Färber <afaerber@suse.de> writes:

> Am 29.01.2013 11:03, schrieb Markus Armbruster:
>> Andreas Färber <afaerber@suse.de> writes:
>> 
>>> b) Working around an issue resulting from hiding C statements inside a
>>> preprocessor macro is totally backwards compared to properly using the C
>>> language in the first place. Its mechanism for reuse are functions, and
>>> for performance considerations static inline functions.
>> 
>> Nobody denies inline functions are to be preferred in many cases.
>> 
>> Valid exceptions include cases where we want genericity, which a macro
>> can easily provide, but an inline function can't.
>> 
>>> Therefore I disagree with you that b) is not an entirely different
>>> disussion as you repeatedly suggest and that according to a) it is not
>>> *generally* necessary to put do { ... } while (0) into any random macro
>>> that one writes. It depends on the contents and on the context.
>> 
>> I don't think Peter suggested to put do ... while (0) into random
>> macros!  He asked to put it exactly into *statement-like* macros, as per
>> standard C practice.  Most macros are expression-like.
>
> Quoting PMM from last night:
> <<<
> "do ... while (0)" is completely standard practice
> for writing robust macros in C. Patches which don't do that
> should fail code review.
>>>>
>
> This is what sparked the most heated part of this debate! I completely
> object to this generalized statement without restriction to
> statement-like macros.

Well, you quite obviously can't use "do ... while (0)" in any but
statement-like macros!

If you use it in an expression-like macro, it's no longer an expression.
Pointlessly breaks uses in non-statement expression context.

If you use it in a declaration-like macro, it's no longer a declaration,
and the declaration part goes into its own scope, which tends to be
counter-productive.

If you use it in a file-level macro, you get syntax errors.

>> I think you're overstating your case.  Statement-like macros should be
>> rare.
>
> This RFC was just a beginning. An average 50%+ of per target-*/ files
> contained macros that were touched here. Even more files are in hw/. Per
> file it was up to ~5 such macro definitions. And my main issue is
> deriving a convention for new files from this discussion.

Stick to established C practice:

1. Avoid statement-like macros when there are superior alternatives,
like inline functions, or expression-like macros.

2. If you have to use a statement-like macro, ensure it expands into a
complete statement regardless of context.  The idiomatic technique for
that is "do ... while (0)".
Blue Swirl Jan. 29, 2013, 8:08 p.m. UTC | #15
On Tue, Jan 29, 2013 at 9:56 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 29 January 2013 08:42, Andreas Färber <afaerber@suse.de> wrote:
>> Am 28.01.2013 22:10, schrieb Peter Maydell:
>> Where we disagree is that you suggest that do { ... while (0) is any
>> better than G_STMT_START ... G_STMT_END. I disagree and find *both*
>> obscuring the code. I clearly stated why.P
>>
>> Therefore I am interested in a non-obscured solution!
>
> There is none if you want to use a multistatement macro
> (which presumably you do because that's what your patch does).
> The best you can do is "standard thing that has been done for
> decades and that is easily recognisable".
>
>> Analysing the reasons for the obscured suggestion:
>>
>> a) "if (foo) MACRO1(); else MACRO2();" is forbidden by Coding Style.
>> Thus, if careful review indicates there are no such Coding Style
>> violations, it is entirely possible not to add any
>> fault-that-may-not-happen-obscuring macro statements.
>
> This requires analysis of all the callsites (including any that
> may be incoming in not-yet-applied patchsets) -- that's a lot
> harder and more error prone than just getting the macro right
> in the first place.
>
>> b) Working around an issue resulting from hiding C statements inside a
>> preprocessor macro is totally backwards compared to properly using the C
>> language in the first place. Its mechanism for reuse are functions, and
>> for performance considerations static inline functions.
>>
>> Therefore I disagree with you that b) is not an entirely different
>> disussion as you repeatedly suggest
>
> It clearly is, because *you didn't submit a patch using an inline
> function*. The whole reason we're having this argument is that you
> submitted a patch that uses a multistatement macro. Feel free
> to resubmit something using an inline function if you like. Once
> again:
>
>  C macro with do..while(0): OK
>  inline function: also OK
>  C macro missing do..while(0) protection: not OK
>  C macro using glib obfuscated macros: also not OK

+1

>
> This really doesn't seem particularly complicated to me.
>
> -- PMM
>
diff mbox

Patch

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f687b95..c1da5bf 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -26,14 +26,14 @@ 
 #define GEN_HELPER 1
 #include "helper.h"
 
-#undef ALPHA_DEBUG_DISAS
+#define ALPHA_DEBUG_DISAS 0
 #define CONFIG_SOFTFLOAT_INLINE
 
-#ifdef ALPHA_DEBUG_DISAS
-#  define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
-#else
-#  define LOG_DISAS(...) do { } while (0)
-#endif
+#define LOG_DISAS(...) G_STMT_START \
+    if (ALPHA_DEBUG_DISAS) { \
+        qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
+    } \
+    G_STMT_END
 
 typedef struct DisasContext DisasContext;
 struct DisasContext {