On Thu, 5 Feb 2015, Daniel Sanders wrote: > Apologies for the slow response. I've had an excessive amount of > meetings in the last couple days. No worries, if anyone, it's not me in a hurry here. ;) > > This definitely looks like a bug in clang to me. What this construct > > means is both input #5 and output #1 live in the same register, and that > > an `__u32' value is taken on input (from the result of the `htonl(proto)' > > calculation) and an `unsigned short' value produced in the same register > > on output, that'll be the value of the `proto' variable from there on. A > > perfectly valid arrangement. This would be the right arrangement to use > > with the MIPS16 SEH instruction for example. Has this bug been reported > > to clang maintainers? > > I'm not convinced it's a bug, but I do at least agree that the use case sounds > sensible. It makes sense to me that the focus should be on register allocations > rather than on types. However, the relevant clang source is being very specific > about the cases it is/isn't allowing which suggests it's deliberate. I've started a > thread on the clang mailing list to try to find out more about why we currently > reject it. I think it boils down to the register model implemented by a given architecture. MIPS processors do not have subregisters for integer data quantities narrower than the size of the machine word. The same GPR will hold a `char', a `short' or an `int', and therefore it is perfectly valid to arrange that it holds say an `int' on input and say a `short' on output. So given an artificial example like this: short foo(int i) { short v; asm("frob %0" : "=r" (v) : "0" (i)); return v; } the compiler knows it does not have to truncate the result of the calculation made in the asm before returning it to the caller, which it would unnecessarily have with this code: short foo(int i) { asm("frob %0" : "+r" (i)); return i; } This is unlike some other architectures. On x86 for example you do have subregisters, so for example an `int' will be stored in %eax, a short will be stored in %ax, and a `char' will be stored in %al, or worse yet, %ah. Consequently you may not be able to alias an input operand and an output operand of a different width each to each other. Also I think it is important to note that in the (first) example above, `i' and `v' are separate data entities as far as C code is concerned. And that the operands of the asm merely tell the C compiler that the value of `i' must appear in a register (that need not be the variable's original storage location) on entry to the asm and the value to set `v' to will appear in a register (that again need not be the place where the actual variable lives) on exit from the asm, and that the two registers must be physically the same (presumably because of a machine limitation, such as one observed with the MIPS16 SEH instruction mentioned), but that does not mean the input and the output otherwise have anything in common. And last but not least, the extended asm feature is a GCC extension, so if clang developers chose to implement it for GCC compatibility, then I am afraid they need to follow the rules set by GCC. So if GCC accepts it, they need too. > Yes, that works for me on both GCC and Clang. I'll change the patch to this. > Would you like a 'Suggested-By' in the patch description? Sure. Maciej