[llvm] r304702 - [ARM] Support fixup for Thumb2 modified immediate

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 5 02:37:13 PDT 2017


Author: psmith
Date: Mon Jun  5 04:37:12 2017
New Revision: 304702

URL: http://llvm.org/viewvc/llvm-project?rev=304702&view=rev
Log:
[ARM] Support fixup for Thumb2 modified immediate
    
This change adds a new fixup fixup_t2_so_imm for the t2_so_imm_asmoperand
"T2SOImm". The fixup permits code such as:
.L1:
 sub r3, r3, #.L2 - .L1
.L2:
to assemble in Thumb2 as well as in ARM state.
    
The operand predicate isT2SOImm() explicitly doesn't match expressions
containing :upper16: and :lower16: as expressions with these operators
must match the movt and movw instructions.
    
The test mov r0, foo2 in thumb2-diagnostics is moved to a new file as the
fixup delays the error message till after the assembler has quit due to
the other errors.
    
As the mov instruction shares the t2_so_imm_asmoperand mov instructions
with a non constant expression now match t2MOVi rather than t2MOVi16 so the
error message is slightly different.
    
Fixes PR28647

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


Added:
    llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error1.s
    llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error2.s
    llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup.s
Modified:
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
    llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s
    llvm/trunk/test/MC/ARM/thumb2-diagnostics.s

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Mon Jun  5 04:37:12 2017
@@ -1026,6 +1026,15 @@ public:
             ARM_AM::getSOImmVal(-Value) != -1);
   }
   bool isT2SOImm() const {
+    // If we have an immediate that's not a constant, treat it as an expression
+    // needing a fixup.
+    if (isImm() && !isa<MCConstantExpr>(getImm())) {
+      // We want to avoid matching :upper16: and :lower16: as we want these
+      // expressions to match in isImm0_65535Expr()
+      const ARMMCExpr *ARM16Expr = dyn_cast<ARMMCExpr>(getImm());
+      return (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 &&
+                             ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16));
+    }
     if (!isImm()) return false;
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
     if (!CE) return false;
@@ -8404,7 +8413,8 @@ bool ARMAsmParser::processInstruction(MC
     // wide encoding wasn't explicit.
     if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
         !isARMLowRegister(Inst.getOperand(0).getReg()) ||
-        (unsigned)Inst.getOperand(2).getImm() > 255 ||
+        (Inst.getOperand(2).isImm() &&
+         (unsigned)Inst.getOperand(2).getImm() > 255) ||
         ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
          (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
         (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
@@ -8556,7 +8566,8 @@ bool ARMAsmParser::processInstruction(MC
     // If we can use the 16-bit encoding and the user didn't explicitly
     // request the 32-bit variant, transform it here.
     if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
-        (unsigned)Inst.getOperand(1).getImm() <= 255 &&
+        (Inst.getOperand(1).isImm() &&
+         (unsigned)Inst.getOperand(1).getImm() <= 255) &&
         ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
           Inst.getOperand(4).getReg() == ARM::CPSR) ||
          (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp Mon Jun  5 04:37:12 2017
@@ -98,6 +98,7 @@ const MCFixupKindInfo &ARMAsmBackend::ge
       {"fixup_t2_movt_hi16", 0, 20, 0},
       {"fixup_t2_movw_lo16", 0, 20, 0},
       {"fixup_arm_mod_imm", 0, 12, 0},
+      {"fixup_t2_so_imm", 0, 26, 0},
   };
   const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {
       // This table *must* be in the order that the fixup_* kinds are defined in
@@ -148,6 +149,7 @@ const MCFixupKindInfo &ARMAsmBackend::ge
       {"fixup_t2_movt_hi16", 12, 20, 0},
       {"fixup_t2_movw_lo16", 12, 20, 0},
       {"fixup_arm_mod_imm", 20, 12, 0},
+      {"fixup_t2_so_imm", 26, 6, 0},
   };
 
   if (Kind < FirstTargetFixupKind)
@@ -693,6 +695,22 @@ unsigned ARMAsmBackend::adjustFixupValue
       return 0;
     }
     return Value;
+  case ARM::fixup_t2_so_imm:
+    Value = ARM_AM::getT2SOImmVal(Value);
+    if ((int64_t)Value < 0) {
+      Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value");
+      return 0;
+    }
+    // Value will contain a 12-bit value broken up into a 4-bit shift in bits
+    // 11:8 and the 8-bit immediate in 0:7. The instruction has the immediate
+    // in 0:7. The 4-bit shift is split up into i:imm3 where i is placed at bit
+    // 10 of the upper half-word and imm3 is placed at 14:12 of the lower
+    // half-word.
+    uint64_t EncValue = 0;
+    EncValue |= (Value & 0x800) << 15;
+    EncValue |= (Value & 0x700) << 4;
+    EncValue |= (Value & 0xff);
+    return swapHalfWords(EncValue, IsLittleEndian);
   }
 }
 
@@ -792,6 +810,7 @@ static unsigned getFixupKindNumBytes(uns
   case ARM::fixup_arm_movw_lo16:
   case ARM::fixup_t2_movt_hi16:
   case ARM::fixup_t2_movw_lo16:
+  case ARM::fixup_t2_so_imm:
     return 4;
 
   case FK_SecRel_2:
@@ -844,6 +863,7 @@ static unsigned getFixupKindContainerSiz
   case ARM::fixup_t2_movt_hi16:
   case ARM::fixup_t2_movw_lo16:
   case ARM::fixup_arm_mod_imm:
+  case ARM::fixup_t2_so_imm:
     // Instruction size is 4 bytes.
     return 4;
   }

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h Mon Jun  5 04:37:12 2017
@@ -110,6 +110,9 @@ enum Fixups {
   // fixup_arm_mod_imm - Fixup for mod_imm
   fixup_arm_mod_imm,
 
+  // fixup_t2_so_imm - Fixup for Thumb2 8-bit rotated operand
+  fixup_t2_so_imm,
+
   // Marker
   LastTargetFixupKind,
   NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp Mon Jun  5 04:37:12 2017
@@ -339,7 +339,17 @@ public:
   unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
                            SmallVectorImpl<MCFixup> &Fixups,
                            const MCSubtargetInfo &STI) const {
-    unsigned SoImm = MI.getOperand(Op).getImm();
+    const MCOperand &MO = MI.getOperand(Op);
+
+    // Support for fixups (MCFixup)
+    if (MO.isExpr()) {
+      const MCExpr *Expr = MO.getExpr();
+      // Fixups resolve to plain values that need to be encoded.
+      MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_so_imm);
+      Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
+      return 0;
+    }
+    unsigned SoImm = MO.getImm();
     unsigned Encoded =  ARM_AM::getT2SOImmVal(SoImm);
     assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
     return Encoded;

Modified: llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s (original)
+++ llvm/trunk/test/MC/ARM/big-endian-thumb2-fixup.s Mon Jun  5 04:37:12 2017
@@ -47,3 +47,9 @@ ldst_precel_12_label:
 	nop
 adr_pcrel_12_label:
 
+ at ARM::fixup_t2_so_imm
+.section s_t2_so_imm,"ax",%progbits
+// CHECK-LABEL: Contents of section s_t2_so_imm
+// CHECK: 0000 f1033337
+	add r3, r3,val
+.equ val,0x37373737

Added: llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error1.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error1.s?rev=304702&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error1.s (added)
+++ llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error1.s Mon Jun  5 04:37:12 2017
@@ -0,0 +1,13 @@
+@ PR28647
+@ RUN: not llvm-mc -triple=thumbv7a-linux-gnueabi -filetype=obj < %s 2>&1 | FileCheck %s
+    .text
+    .syntax unified
+    .balign 2
+
+@ Error with unencodeable immediate
+    add r1, r2, sym0
+@ CHECK: error: out of range immediate fixup value
+    .equ sym0, 0x01abcdef
+.L2:
+    mov r0, .L2
+@ CHECK: error: unsupported relocation on symbol

Added: llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error2.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error2.s?rev=304702&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error2.s (added)
+++ llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup-error2.s Mon Jun  5 04:37:12 2017
@@ -0,0 +1,12 @@
+@ PR28647
+@ RUN: not llvm-mc -triple=thumbv7a-linux-gnueabi -filetype=obj < %s 2>&1 | FileCheck %s
+    .text
+    .syntax unified
+    .balign 2
+
+@ mov with :upper16: or :lower16: should not match mov with modified immediate
+    mov r0, :upper16: sym0
+@ CHECK: error: instruction requires: arm-mode
+    mov r0, :lower16: sym0
+@ CHECK: error: instruction requires: arm-mode
+    .equ sym0, 0x01abcdef

Added: llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup.s?rev=304702&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup.s (added)
+++ llvm/trunk/test/MC/ARM/t2-modified-immediate-fixup.s Mon Jun  5 04:37:12 2017
@@ -0,0 +1,45 @@
+@ PR28647
+@ RUN: llvm-mc < %s -triple=thumbv7a-linux-gnueabi -filetype=obj -o - \
+@ RUN: | llvm-objdump --disassemble -triple=thumbv7a-linux-gnueabi - | FileCheck %s
+    .text
+    .syntax unified
+    .balign 2
+@ Thumb2 modified immediate instructions
+    add r1,r1, sym0
+    sub r1,r2, sym1
+    cmp r2,    sym2
+    and r4,r4, sym3
+    orr r8,r9, sym4
+    teq r1,    sym5
+    tst r1,    sym6
+    sbc r1,r1, sym7
+    adc r1,r0, sym8
+ at CHECK: add.w   r1, r1, #255
+ at CHECK: sub.w   r1, r2, #16711935
+ at CHECK: cmp.w   r2, #4278255360
+ at CHECK: and     r4, r4, #303174162
+ at CHECK: orr     r8, r9, #2852126720
+ at CHECK: teq.w   r1, #1426063360
+ at CHECK: tst.w   r1, #713031680
+ at CHECK: sbc     r1, r1, #2785280
+ at CHECK: adc     r1, r0, #340
+
+.L1:
+    sub r3, r3, #.L2 - .L1
+.L2:
+ at CHECK: sub.w   r3, r3, #4
+
+@ mov without :upper16: or :lower16: should match mov with modified immediate
+     mov r1, sym3
+ at CHECK: mov.w   r1, #303174162
+
+@ Modified immediate constants
+    .equ sym0, 0x000000ff
+    .equ sym1, 0x00ff00ff
+    .equ sym2, 0xff00ff00
+    .equ sym3, 0x12121212
+    .equ sym4, 0xaa000000
+    .equ sym5, 0x55000000
+    .equ sym6, 0x2a800000
+    .equ sym7, 0x002a8000
+    .equ sym8, 0x00000154

Modified: llvm/trunk/test/MC/ARM/thumb2-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/thumb2-diagnostics.s?rev=304702&r1=304701&r2=304702&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/thumb2-diagnostics.s (original)
+++ llvm/trunk/test/MC/ARM/thumb2-diagnostics.s Mon Jun  5 04:37:12 2017
@@ -76,10 +76,8 @@
 @ CHECK-ERRORS: error: branch target out of range
 
 foo2:
-        mov r0, foo2
         movw r0, foo2
         movt r0, foo2
-@ CHECK-ERRORS: error: instruction requires: arm-mode
 @ CHECK-ERRORS: error: immediate expression for mov requires :lower16: or :upper16
 @ CHECK-ERRORS:                  ^
 @ CHECK-ERRORS: error: immediate expression for mov requires :lower16: or :upper16




More information about the llvm-commits mailing list