diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -970,11 +970,15 @@ bool isMOVZMovAlias() const { if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - uint64_t Value = CE->getValue(); + const MCExpr *E = getImm(); + if (const MCConstantExpr *CE = dyn_cast(E)) { + uint64_t Value = CE->getValue(); - return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth); + return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth); + } + // For expressions, only support the case of Shift being 0 as the result is + // unknown at this point. + return !Shift && E; } template @@ -1774,9 +1778,14 @@ void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *CE = cast(getImm()); - uint64_t Value = CE->getValue(); - Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff)); + const MCExpr *E = getImm(); + if (const MCConstantExpr *CE = dyn_cast(getImm())) { + uint64_t Value = CE->getValue(); + Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff)); + } else { + assert(!Shift && "Do not support shifted expressions as an operand!"); + addExpr(Inst, AArch64MCExpr::create(E, AArch64MCExpr::VK_ABS_G0_S, Ctx)); + } } template diff --git a/llvm/test/MC/AArch64/basic-a64-diagnostics.s b/llvm/test/MC/AArch64/basic-a64-diagnostics.s --- a/llvm/test/MC/AArch64/basic-a64-diagnostics.s +++ b/llvm/test/MC/AArch64/basic-a64-diagnostics.s @@ -167,9 +167,9 @@ // MOV alias should not accept any fiddling mov x2, xsp, #123 mov wsp, w27, #0xfff, lsl #12 -// CHECK-ERROR: error: expected compatible register or logical immediate +// CHECK-ERROR: error: invalid operand for instruction // CHECK-ERROR-NEXT: mov x2, xsp, #123 -// CHECK-ERROR-NEXT: ^ +// CHECK-ERROR-NEXT: ^ // CHECK-ERROR-NEXT: error: invalid operand for instruction // CHECK-ERROR-NEXT: mov wsp, w27, #0xfff, lsl #12 // CHECK-ERROR-NEXT: ^ diff --git a/llvm/test/MC/AArch64/mov-expression-as-immediate.s b/llvm/test/MC/AArch64/mov-expression-as-immediate.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/mov-expression-as-immediate.s @@ -0,0 +1,11 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump -d %t | FileCheck %s + +0: +.skip 4 +1: +mov x0, 1b - 0b +// CHECK: mov x0, #4 +mov x0, 0b - 1b +// CHECK: mov x0, #-4 +mov x0, 0b - 0b +// CHECK: mov x0, #0 diff --git a/llvm/test/MC/AArch64/mov-invalid-expression-as-immediate.s b/llvm/test/MC/AArch64/mov-invalid-expression-as-immediate.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/mov-invalid-expression-as-immediate.s @@ -0,0 +1,9 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o /dev/null 2>&1 | FileCheck %s + +0: +.skip 0x10000 +1: +mov x0, 1b - 0b +// CHECK: error: fixup value out of range +// CHECK: mov x0, 1b - 0b +// CHECK: ^