RE: [PATCH 3/5] MIPS: LLVMLinux: Fix an 'inline asm input/output type mismatch' error.

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

 



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





[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux