Page MenuHomePhabricator

[Sparc] Fix addressing mode when using 64-bit values in inline assembly
ClosedPublic

Authored by dcederman on Apr 18 2018, 4:15 AM.

Details

Summary

If a 64-bit register is used as an operand in inline assembly together with a memory reference, the memory addressing will be wrong. The addressing will be a single reg, instead of reg+reg or reg+imm. This will generate a bad offset value or an exception in printMemOperand().

For example:

long long int val = 5;
long long int mem;
__asm__ volatile ("std %1, %0":"=m"(mem):"r"(val));

becomes:

std %i0, [%i2+589833]

The problem is that SelectInlineAsmMemoryOperand() is never called for the memory references if one of the operands is a 64-bit register. By calling SelectInlineAsmMemoryOperands() in tryInlineAsm() the Sparc version of SelectInlineAsmMemoryOperand() gets called for each memory reference.

A comment above SelectInlineAsmMemoryOperands() says that it should only be called by tblgen. So alternatively one could call SelectCode() on the new Node instead, or copy the content of SelectInlineAsmMemoryOperands() to tryInlineAsm().

Diff Detail

Repository
rL LLVM

Event Timeline

dcederman created this revision.Apr 18 2018, 4:15 AM

Looks reasonable to me -- SelectInlineAsmMemoryOperands is called in the equivalent generic INLINEASM select code so it makes sense to do so here too. I wonder if the same bug exists on ARM, which has effectively the same code.

jyknight accepted this revision.Apr 19 2018, 6:49 PM

(forgot to click accept)

This revision is now accepted and ready to land.Apr 19 2018, 6:49 PM

Thanks!

I wonder if the same bug exists on ARM, which has effectively the same code.

The ARM backend does not change addressing mode in its SelectInlineAsmMemoryOperand(), so I do not think it matters if it gets called or not. But I could create a similar patch for ARM.

This revision was automatically updated to reflect the committed changes.