Re: [geert-m68k:master 2/2] lib/muldi3.c:53:28: sparse: sparse: asm output is not an lvalue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Linus,

On Sun, Jan 5, 2025 at 10:51 PM Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
> On Fri, 3 Jan 2025 at 01:22, Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote:
> > Perhaps this is an issue with sparse?
>
> No, this is just m68k doing disgusting things that happen to work with
> gcc, because gcc considers casts to be lvalues (which in turn is comes
> from some horrid C++ thing, since in C++ casting is a whole magical
> extra complexity).
>
> IOW, this m68k pattern is horrendous, and sparse quite reasonably
> complains about it:
>
>   #define umul_ppmm(w1, w0, u, v) \
>     __asm__ ("mulu%.l %3,%1:%0"                                           \
>              : "=d" ((USItype)(w0)),                                      \
>                "=d" ((USItype)(w1))                                       \
>              : "%0" ((USItype)(u)),                                       \
>                "dmi" ((USItype)(v)))
>
> notice how it has two register outputs (the "=d"), and the destination
> of said output is not a proper lvalue, but a cast expression.
>
> I think you could just remove the cast. Afaik the w0/w1 arguments come from
>
> #define __umulsidi3(u, v) \
>   ({DIunion __w;                                                        \
>     umul_ppmm (__w.s.high, __w.s.low, u, v);                            \
>     __w.ll; })
>
> and __w.s.high and __w.s.low are from struct DIstruct, which uses
> "SItype". So all the cast does is to change the signedness of the
> variable, but that has no *meaning* when you assign to it and the
> sizes match.
>
> Alternatively, you could just use the right types explicitly and write
> the umul_ppmm() macro something like
>
> #define umul_ppmm(w1, w0, u, v) do {            \
>         USItype __w0, __w1;                     \
>         __asm__ ("mulu%.l %3,%1:%0"             \
>                 : "=d" (__w0)                   \
>                   "=d" (__w1)                   \
>                 : "%0" ((USItype)(u)),          \
>                   "dmi" ((USItype)(v)));        \
>         w0 = __w0; w1 = __w1; } while (0)
>
> NOTE! UNTESTED! Treat the above as a "something like this, perhaps".

Thank you, using intermediate variables instead of casts for the output
operands gets rid of the lvalue-related sparse warnings.
That leaves us with the "not addressable" sparse error.  Apparently
that goes away by dropping the cast on the last input operand,
so I will introduce intermediate variables for all input operands, too.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds





[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux