avr-libc-dev
[Top][All Lists]
Advanced

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

Compilation with clang


From: Marian Buschsieweke
Subject: Compilation with clang
Date: Wed, 13 Oct 2021 18:05:23 +0200

Hi together,

parts of the avrlibc headers are not compatible with clang. (The use case is
not to compile avrlibc itself with clang, but rather an application using
a vanilla GCC compiled avrlibc.) However, the issues are not always trivial to
fix.

E.g. in avr/wdt.h there are several instances of code like this:

> static __inline__
> __attribute__ ((__always_inline__))
> void wdt_enable (const uint8_t value)
> {
>       if (_SFR_IO_REG_P (_WD_CONTROL_REG))
>       {
>               __asm__ __volatile__ (
>                               [...]
>                               : /* no outputs */
>                               : "I" (_SFR_IO_ADDR(_WD_CONTROL_REG)),
>                               [...]
>                               : "r0"
>               );
>       }
>       else {
>               /* variant not using _WD_CONTROL_REG as immediate */
>               [...]       
>       
> }

For targets where _SFR_IO_REG_P (_WD_CONTROL_REG) evaluates to false, the
inline assembly in the then-clause is syntactically not correct, as the
constraints "I" are not fulfilled. But GCC will never check the constraints,
because GCC eliminates the dead branches prior to verifying correctness of
inline assembly. With clang these syntax checks are done prior to the
optimization of dead branches. I'm aware that inline assembly isn't part of the
C language, still performing syntax checks prior to the optimizations seems
more consistent to me. (If there were C syntax errors in the dead branch, the
compiler would also refuse to compile despite the lines in question being
unreachable.)

So, the obvious solution would be to use preprocessor #if instead of C level
ifs to select the right assembly implementation. But that is not trivially
possible, as (without ASM compatibility) the register definitions use
> _SFR_MEM8(<addr>)
that boils down to
> (*(volatile uint8_t *)(<addr>)

This is something the preprocessor doesn't like at all.

It's a pity that the addresses in the io headers are not provided both as raw
numeric address compatible with the preprocessor, e.g. with an _ADDR postfix
added, and as _SFR_MEM8() for convenient use from C.

What would be the best way to fix this? 

Maybe a regex could extend the header files to indeed also provide the _ADDR
flavor without too much manual labor, but that would be a rather large patch.

I think that one alternatively could just always choose the least efficient
inline assembly that doesn't depend on the registers address being below 64 for
all AVRs, but maybe there are timing requirements that cannot tolerate the
additional CPU cycle for access via memory? In any case, this would add a few
bytes of program memory to existing software.

Kind regards,
Marian

Attachment: pgpzfdSJhhqUf.pgp
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]