[llvm] 0e1accd - [AArch64] Support expression results as immediate values in mov

Jian Cai via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 17:57:33 PDT 2020


Author: Jian Cai
Date: 2020-06-08T17:57:20-07:00
New Revision: 0e1accd0f726eef2c47be9f37dd0a06cb50d207e

URL: https://github.com/llvm/llvm-project/commit/0e1accd0f726eef2c47be9f37dd0a06cb50d207e
DIFF: https://github.com/llvm/llvm-project/commit/0e1accd0f726eef2c47be9f37dd0a06cb50d207e.diff

LOG: [AArch64] Support expression results as immediate values in mov

Summary:
This patch adds support of using the result of an expression as an
immediate value. For example,

0:
.skip 4
 1:
mov x0, 1b - 0b

is assembled to

mov x0, #4

Currently it does not support expressions requiring relocation unless
explicitly specified. This fixes PR#45781.

Reviewers: peter.smith, ostannard, efriedma

Reviewed By: efriedma

Subscribers: nickdesaulniers, llozano, manojgupta, efriedma, ostannard, kristof.beyls, hiraditya, danielkiss, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D80028

Added: 
    llvm/test/MC/AArch64/mov-expr-as-immediate.s
    llvm/test/MC/AArch64/mov-expression-as-immediate.s
    llvm/test/MC/AArch64/mov-unsupported-expr-as-immediate.s

Modified: 
    llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
    llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
    llvm/test/MC/AArch64/basic-a64-diagnostics.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 2b436d418132..848361e0fb9b 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -970,11 +970,15 @@ class AArch64Operand : public MCParsedAsmOperand {
   bool isMOVZMovAlias() const {
     if (!isImm()) return false;
 
-    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
-    if (!CE) return false;
-    uint64_t Value = CE->getValue();
+    const MCExpr *E = getImm();
+    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(E)) {
+      uint64_t Value = CE->getValue();
 
-    return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
+      return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
+    }
+    // Only supports the case of Shift being 0 if an expression is used as an
+    // operand
+    return !Shift && E;
   }
 
   template<int RegWidth, int Shift>
@@ -1774,9 +1778,13 @@ class AArch64Operand : public MCParsedAsmOperand {
   void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
 
-    const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
-    uint64_t Value = CE->getValue();
-    Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (CE) {
+      uint64_t Value = CE->getValue();
+      Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
+    } else {
+      addExpr(Inst, getImm());
+    }
   }
 
   template<int Shift>

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index a5e78f19aeba..9f7dfdf62482 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -243,11 +243,22 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
         static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
     if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS &&
         AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
-      // VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
-      // ever be resolved in the assembler.
-      Ctx.reportError(Fixup.getLoc(),
-                      "relocation for a thread-local variable points to an "
-                      "absolute symbol");
+      if (!RefKind) {
+        // The fixup is an expression
+        if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
+          Ctx.reportError(Fixup.getLoc(),
+                          "fixup value out of range [-0xFFFF, 0xFFFF]");
+
+        // Invert the negative immediate because it will feed into a MOVN.
+        if (SignedValue < 0)
+          SignedValue = ~SignedValue;
+        Value = static_cast<uint64_t>(SignedValue);
+      } else
+        // VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
+        // ever be resolved in the assembler.
+        Ctx.reportError(Fixup.getLoc(),
+                        "relocation for a thread-local variable points to an "
+                        "absolute symbol");
       return Value;
     }
 
@@ -440,8 +451,9 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
   // FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
   // handle this more cleanly. This may affect the output of -show-mc-encoding.
   AArch64MCExpr::VariantKind RefKind =
-    static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
-  if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS) {
+      static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
+  if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS ||
+      (!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
     // If the immediate is negative, generate MOVN else MOVZ.
     // (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
     if (SignedValue < 0)

diff  --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
index 8f4d9cb94d60..da8f511c650f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
@@ -569,23 +569,24 @@ unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
   if (UImm16MO.isImm())
     return EncodedValue;
 
-  const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
-  switch (A64E->getKind()) {
-  case AArch64MCExpr::VK_DTPREL_G2:
-  case AArch64MCExpr::VK_DTPREL_G1:
-  case AArch64MCExpr::VK_DTPREL_G0:
-  case AArch64MCExpr::VK_GOTTPREL_G1:
-  case AArch64MCExpr::VK_TPREL_G2:
-  case AArch64MCExpr::VK_TPREL_G1:
-  case AArch64MCExpr::VK_TPREL_G0:
-    return EncodedValue & ~(1u << 30);
-  default:
-    // Nothing to do for an unsigned fixup.
-    return EncodedValue;
+  const MCExpr *E = UImm16MO.getExpr();
+  if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(E)) {
+    switch (A64E->getKind()) {
+    case AArch64MCExpr::VK_DTPREL_G2:
+    case AArch64MCExpr::VK_DTPREL_G1:
+    case AArch64MCExpr::VK_DTPREL_G0:
+    case AArch64MCExpr::VK_GOTTPREL_G1:
+    case AArch64MCExpr::VK_TPREL_G2:
+    case AArch64MCExpr::VK_TPREL_G1:
+    case AArch64MCExpr::VK_TPREL_G0:
+      return EncodedValue & ~(1u << 30);
+    default:
+      // Nothing to do for an unsigned fixup.
+      return EncodedValue;
+    }
   }
 
-
-  return EncodedValue & ~(1u << 30);
+  return EncodedValue;
 }
 
 void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,

diff  --git a/llvm/test/MC/AArch64/basic-a64-diagnostics.s b/llvm/test/MC/AArch64/basic-a64-diagnostics.s
index 067acbfc012a..9114d30bc3d8 100644
--- 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-expr-as-immediate.s b/llvm/test/MC/AArch64/mov-expr-as-immediate.s
new file mode 100644
index 000000000000..bc3adc292312
--- /dev/null
+++ b/llvm/test/MC/AArch64/mov-expr-as-immediate.s
@@ -0,0 +1,16 @@
+// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump --triple aarch64-none-linux-gnu -Dr %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
+mov x0, 1b - 2 - 0b + 6
+// CHECK: mov x0, #8
+mov x0, #:abs_g0_s:1b
+// CHECK: mov x0, #0
+// CHECK-NEXT: R_AARCH64_MOVW_SABS_G0	.text+0x4

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
index 000000000000..9426293fccde
--- /dev/null
+++ b/llvm/test/MC/AArch64/mov-expression-as-immediate.s
@@ -0,0 +1,9 @@
+// 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

diff  --git a/llvm/test/MC/AArch64/mov-unsupported-expr-as-immediate.s b/llvm/test/MC/AArch64/mov-unsupported-expr-as-immediate.s
new file mode 100644
index 000000000000..5327ab744b76
--- /dev/null
+++ b/llvm/test/MC/AArch64/mov-unsupported-expr-as-immediate.s
@@ -0,0 +1,17 @@
+// 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: ^
+mov x0, 0b - 1b
+// CHECK: error: fixup value out of range
+// CHECK: mov x0, 0b - 1b
+// CHECK: ^
+mov x0, 1b
+// CHECK: error: invalid fixup for movz/movk instruction
+// CHECK: mov x0, 1b
+// CHECK: ^


        


More information about the llvm-commits mailing list