On 2021-10-12, Jakub Jelinek wrote:
On Tue, Oct 12, 2021 at 09:21:21AM -0700, Fāng-ruì Sòng wrote:
> > An output constraint takes a lvalue. While GCC happily strips the
> > incorrect lvalue to rvalue conversion, Clang rejects the code by default:
> >
> >     error: invalid use of a cast in a inline asm context requiring an 
lvalue: remove the cast or build with -fheinous-gnu-extensions
> >
> > The file appears to share the same origin with gmplib longlong.h but
> > they differ much now (gmplib version is much longer).
> >
> > I don't have write access to the git repo.
> > ---
> >  include/longlong.h | 186 ++++++++++++++++++++++-----------------------
> >  1 file changed, 93 insertions(+), 93 deletions(-)
> >
> > diff --git a/include/longlong.h b/include/longlong.h
> > index c3e92e54ecc..0a21a441d2d 100644
> > --- a/include/longlong.h
> > +++ b/include/longlong.h
> > @@ -194,8 +194,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, 
UDItype, UDItype);
> >  #if defined (__arc__) && W_TYPE_SIZE == 32
> >  #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> >    __asm__ ("add.f    %1, %4, %5\n\tadc       %0, %2, %3"             \
> > -        : "=r" ((USItype) (sh)),                                     \
> > -          "=&r" ((USItype) (sl))                                     \
> > +        : "=r" (sh),                                                 \
> > +          "=&r" (sl)                                                 \
> >          : "%r" ((USItype) (ah)),                                     \
> >            "rICal" ((USItype) (bh)),                                  \
> >            "%r" ((USItype) (al)),                                     \
>
> This seems to alter the meanining of existing programs if sh and sl do
> not have the expected type.
>
> I think you need to add a compound expression and temporaries of type
> USItype if you want to avoid the cast.

Add folks who may comment on the output constraint behavior when a
lvalue to rvalue conversion like (`(USItype)`) is added.

Allowing the casts in there is intentional, the comment about this
e.g. in GCC's C FE says:
Really, this should not be here.  Users should be using a
proper lvalue, dammit.  But there's a long history of using casts
in the output operands.  In cases like longlong.h, this becomes a
primitive form of typechecking -- if the cast can be removed, then
the output operand had a type of the proper width; otherwise we'll
get an error.

If you try e.g.:

void
foo (void)
{
 int i;
 long l;
 __asm ("" : "=r" ((unsigned) i));
 __asm ("" : "=r" ((long) l));
 __asm ("" : "=r" ((long long) l));
 __asm ("" : "=r" ((int) l));
 __asm ("" : "=r" ((long) i));
}

then on e.g. x86-64 the first 3 asms are accepted by GCC, the last two
rejected, because the modes are different there.

So the above change throws away important typechecking.  As it is
used in a macro, something different should verify that if the casts are
removed.

        Jakub


Thanks for the detailed explanation. I see the type checking effect now.
In many cases the assembler can provide some checks, e.g.

  long foo(long a) {
    long r;
    __asm__ ("movq %1, %0" : "=r"(r) : "r"(a));
    return r;
  }

I came here from trying to build glibc with Clang where I came across errors 
like

In file included from strtof_l.c:44:
./strtod_l.c:1500:26: error: invalid use of a cast in a inline asm context 
requiring an lvalue: remove the cast or build with -fheinous-gnu-extensions
              udiv_qrnnd (quot, n, n, 0, d);
              ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
./longlong.h:518:24: note: expanded from macro 'udiv_qrnnd'
             "=d" ((UDItype) (r))                                       \
                   ~~~~~~~~~~~^~
In file included from strtof_l.c:44:
./strtod_l.c:1606:21: error: invalid use of a cast in a inline asm context 
requiring an lvalue: remove the cast or build with -fheinous-gnu-extensions
                      add_ssaaaa (n1, n0, r - d0, 0, 0, d0);
                      ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~

(Seems that building GCC with Clang doesn't run into the issues?)

If the desire to keep the checking is still strong, perhaps I will just stick 
with using the -f option for glibc.

Reply via email to