All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Zoltán Kővágó" <dirty.ice.hu@gmail.com>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [RFC PATCH] osdep: Make MIN/MAX evaluate arguments only once
Date: Sat, 5 Jan 2019 01:23:38 +0100	[thread overview]
Message-ID: <4e30c442-6ddc-2988-160e-168dec552966@gmail.com> (raw)
In-Reply-To: <20190104153951.32306-1-eblake@redhat.com>

Hi,

I have a similar patch in my queue[1]

On 2019-01-04 16:39, Eric Blake wrote:
> Use the __auto_type keyword to make sure our min/max macros only
> evaluate their arguments once.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> 
> RFC because __auto_type didn't exist until gcc 4.9, and I don't know
> which clang version introduced it (other than that it went in
> during 2015: https://reviews.llvm.org/D12686).  Our minimum gcc
> version is 4.8, which has typeof; I'm not sure if our minimum clang
> version supports typeof.
> 
> I'm considering adding a snippet to compiler.h that looks like:
> 
>  #if .... // new enough gcc/clang
>  #define QEMU_TYPEOF(a) __auto_type
>  #else
>  #define QEMU_TYPEOF(a) typeof(a)
>  #endif
> 
> at which point we could blindly use QEMU_TYPEOF(a)=(a) anywhere we
> need automatic typing, for the benefit of smaller macro expansion
> [and proper handling of VLA types, although I don't think we use
> those to care about that aspect of __auto_type] in newer compilers,
> while still getting automatic type deduction in older compilers for
> macros that want single evaluation, and where we've localized the
> version checks to one spot instead of everywhere.  But for that to
> work, again, I need to know whether typeof is supported in our
> minimum clang version, and how to properly spell the version check
> for clang on when to prefer __auto_type over typeof (at least I
> know how to spell it for gcc).
> 
> While at it, the comments to MIN_NON_ZERO() state that callers should
> only compare unsigned types; I suspect we don't actually obey that
> rule, but I also think the comment is over-strict - the macro works
> as long as both arguments are non-negative, and when called with a
> mix of signed and unsigned types, as long as the type promotion
> preserves the fact that the value is still non-negative.  But it
> might be interesting to add compile-time checking (or maybe runtime
> asserts) that the macro is indeed only used on non-negative values.
> 
>  include/qemu/osdep.h | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> index 3bf48bcdec0..b941572b808 100644
> --- a/include/qemu/osdep.h
> +++ b/include/qemu/osdep.h
> @@ -233,17 +233,31 @@ extern int daemon(int, int);
>  #endif
> 
>  #ifndef MIN
> -#define MIN(a, b) (((a) < (b)) ? (a) : (b))
> +#define MIN(a, b)              \
> +    ({                         \
> +        __auto_type _a = (a);  \
> +        __auto_type _b = (b);  \
> +        _a < _b ? _a : _b;     \
> +    })
>  #endif
>  #ifndef MAX
> -#define MAX(a, b) (((a) > (b)) ? (a) : (b))
> +#define MAX(a, b)              \
> +    ({                         \
> +        __auto_type _a = (a);  \
> +        __auto_type _b = (b);  \
> +        _a > _b ? _a : _b;     \
> +    })
>  #endif
I tried this[2], but apparently random linux headers define their own
MIN/MAX and in case this version won't be used. And the version above
with __auto_type and statement expression doesn't work on bitfields and
when not in functions (for example struct XHCIState has
    USBPort  uports[MAX(MAXPORTS_2, MAXPORTS_3)];
as one of its member). It only works because currently glib/gmacros.h or
sys/param.h defines it's own MIN/MAX which is identical to the old version.

Now that I think about it, instead of undefining the old macro or only
conditionally defining it, maybe the best course of action would be to
rename MIN/MAX to something more unique so it won't clash with random
system headers.

> 
>  /* Minimum function that returns zero only iff both values are zero.
>   * Intended for use with unsigned values only. */
>  #ifndef MIN_NON_ZERO
> -#define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \
> -                                ((b) == 0 ? (a) : (MIN(a, b))))
> +#define MIN_NON_ZERO(a, b)                              \
> +    ({                                                  \
> +        __auto_type _a = (a);                           \
> +        __auto_type _b = (b);                           \
> +        _a == 0 ? _b : (_b == 0 || _b > _a) ? _a : _b;  \
> +    })
>  #endif
> 
>  /* Round number down to multiple */
> 

[1]: https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg05718.html
[2]: https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg06006.html

Regards,
Zoltan

  parent reply	other threads:[~2019-01-05  0:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-04 15:39 [Qemu-devel] [RFC PATCH] osdep: Make MIN/MAX evaluate arguments only once Eric Blake
2019-01-04 21:47 ` no-reply
2019-01-05  0:23 ` Zoltán Kővágó [this message]
2019-01-05 13:48   ` Eric Blake
2019-01-05 14:34     ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4e30c442-6ddc-2988-160e-168dec552966@gmail.com \
    --to=dirty.ice.hu@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.