Hi All,
Does anyone remember why clang rejects inline assembly where an input and output are tied together but are differently sized types? The code that rejects it (Sema::ActOnGCCAsmStmt()) is looking like it’s intentional but it’s not clear why it does so.
My current theory is that it’s to avoid dealing with cases where a register has to be tied to its own subregister or something along those lines.
Here’s a trimmed version of the original failing case from the Linux Kernel:
static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__u32 len, unsigned short proto,
__wsum sum)
{
asm(
/* snip */
" addu %0, %5 # proto (long in network byte order)\n"
" sltu $1, %0, %5 \n"
/* snip */
" lw %1, 0(%2) # four words source address\n"
/* snip */
: “=r” (sum), “=r” (proto)
: “r” (saddr), “r” (daddr),
“0” (htonl(len)), “1” (htonl(proto)), “r” (sum));
return csum_fold(sum);
}
Clang objects to the ‘htonl(proto)’ on the grounds that the type doesn’t match ‘proto’:
arch/mips/include/asm/checksum.h:285:27: error: unsupported inline asm: input with type ‘__be32’ (aka ‘unsigned int’) matching output with type ‘unsigned short’
“0” (htonl(len)), “1” (htonl(proto)), “r” (sum));
^~~~~~~~~~~~
Daniel Sanders
Leading Software Design Engineer, MIPS Processor IP
Imagination Technologies Limited