Bug or incorrect use of inline asm?

Hi all,
I stumbled upon either a bug, or we are emitting wrong inline asm code.

The testcase is:


source_filename = "testcase.d"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx"

define void @_D7asanasm3fooFZv() {
%a = alloca [4 x i32], align 32
call void asm sideeffect "movl %ebx, 4+$0", "=*m,~{memory}"([4 x i32]* %a)
ret void
}

When I try to compile this to assembly code with llc, llc errors.

llc testcase.ll -o testcase.s -O0

:1:16: error: unknown token in expression
movl %ebx, 4+(%rsp)

^

The explicit -O0 is required for the error to arise.

The error is gone after removing (or reducing) the alignment of %a. This makes me believe that our inline asm syntax is correct to add an offset to a pointer: " 4+$0 ".

Is this a bug in the asm parser?

Thanks,
Johan

The AT&T syntax for a displaced address doesn't have the '+'; it's
just "4(%rsp)" so you should change the IR to "4$0".

LLVM appears to be optimizing the addressing mode, and the optimizer
is being more lenient on this detail so you're getting lucky when the
+4 can be combined with an existing %rsp offset.

Cheers.

Tim.

I thought I had tested exactly that and observed wrong behaviour. But now I
see it works well... confused.
Thanks!
  Johan

Things break down when part of the offset is a linktime constant:

source_filename = "asanasm.d"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"

@globVar = global [2 x i32] [i32 66051, i32 66051]

define void @_D7asanasm8offconstFZv() {
  call void asm sideeffect "movdqa 4$0, %xmm7", "*m,~{xmm7}"([2 x i32]*
@globVar)
  ret void
}

results in:
<inline asm>:1:10: error: unexpected token in argument list
        movdqa 4globVar(%rip), %xmm7

So in that case, I do have to add the '+' to make it work ("4+$0").

So depending on the pointer argument, I need to write a + or without +,
complicating automatic codegen.

Thanks for the help,
  Johan

FWIW we do support:

4+4(%rsp)

as 8(%rsp)

we just don’t support

4+(%rsp)

but do support

4+0(%rsp)

as 4(%rsp)

oddly enough gas does support the 4+(%rsp) but I’ve never had time to go try to fix it in the assembler.

-eric

2017-08-03 8:58 GMT-07:00 Johan Engelen via llvm-dev <
llvm-dev@lists.llvm.org>:
> The error is gone after removing (or reducing) the alignment of `%a`.
This
> makes me believe that our inline asm syntax is correct to add an offset
to a
> pointer: " 4+$0 ".

The AT&T syntax for a displaced address doesn't have the '+'; it's
just "4(%rsp)" so you should change the IR to "4$0".

LLVM appears to be optimizing the addressing mode, and the optimizer
is being more lenient on this detail so you're getting lucky when the
+4 can be combined with an existing %rsp offset.

Things break down when part of the offset is a linktime constant:

...

So depending on the pointer argument, I need to write a + or without +,
complicating automatic codegen.

The problem is worse. The following code is accepted depending on PIC or
non-PIC compilation:

source_filename = "asanasm.d"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-linux-gnu"

@_D7asanasm9constantsG2k = global [2 x i32] [i32 66051, i32 66051]

define void @_D7asanasm8offconstFZv() {
  call void asm sideeffect "movdqa 4$0, %xmm7", "*m,~{xmm7}"([2 x i32]*
@_D7asanasm9constantsG2k)
  ret void
}

I get no errors with PIC:

llc test.ll -o test.s -O0 -relocation-model=pic

The asm output:
  movq _D7asanasm9constantsG2k@GOTPCREL(%rip), %rax
  #InlineASM
  movdqa 4(%rax), %xmm7

But without PIC:

llc test.ll -o test.s -O0 -relocation-model=static

<inline asm>:1:10: error: unexpected token in argument list
        movdqa 4_D7asanasm9constantsG2k(%rip), %xmm7
                ^

So it appears that applying an offset to a pointer variable will break
using either "4+$0" or "4$0", and you have to be lucky to guess correctly
what's going to happen with the pointer argument passed into the inline asm
call. (my problem would be solved when "4+$0" would always be accepted)

I now feel this is a bug in LLVM, do you agree?
Unfortunately, I do not know how to work around the current problem.

Thanks,
  Johan

Oh I haven’t disagreed with you at all. Sorry I wasn’t clear :slight_smile:

Mostly the x86 asm parser needs work to support this. I -think- it’s just a matter of typing, but I haven’t really tried to fix it.
You might be able to use a register constraint to put the address into a register and go from there. It’s not ideal, but might work.

-eric