]> granicus.if.org Git - llvm/commitdiff
[ARM] Diagnose PC-writing instructions in IT blocks
authorOliver Stannard <oliver.stannard@arm.com>
Tue, 28 Feb 2017 10:04:36 +0000 (10:04 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Tue, 28 Feb 2017 10:04:36 +0000 (10:04 +0000)
In Thumb2, instructions which write to the PC are UNPREDICTABLE if they are in
an IT block but not the last instruction in the block.

Previously, we only diagnosed this for LDM instructions, this patch extends the
diagnostic to cover all of the relevant instructions.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296459 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/arm-thumb-trustzone.s
test/MC/ARM/basic-thumb2-instructions.s
test/MC/ARM/unpred-control-flow-in-it-block.s [new file with mode: 0644]

index 03e1d447b6672ba326a2e663ff2e2d3e428dce9b..dae8618fa070d1e5afb28c4d183024d3dd308b8f 100644 (file)
@@ -6305,10 +6305,6 @@ bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst,
   else if (ListContainsPC && ListContainsLR)
     return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
                  "PC and LR may not be in the register list simultaneously");
-  else if (inITBlock() && !lastInITBlock() && ListContainsPC)
-    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
-                 "instruction must be outside of IT block or the last "
-                 "instruction in an IT block");
   return false;
 }
 
@@ -6370,6 +6366,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
     return Warning(Loc, "predicated instructions should be in IT block");
   }
 
+  // PC-setting instructions in an IT block, but not the last instruction of
+  // the block, are UNPREDICTABLE.
+  if (inExplicitITBlock() && !lastInITBlock() && isITBlockTerminator(Inst)) {
+    return Error(Loc, "instruction must be outside of IT block or the last instruction in an IT block");
+  }
+
   const unsigned Opcode = Inst.getOpcode();
   switch (Opcode) {
   case ARM::LDRD:
@@ -9013,6 +9015,7 @@ bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const {
   // operands. We only care about Thumb instructions here, as ARM instructions
   // obviously can't be in an IT block.
   switch (Inst.getOpcode()) {
+  case ARM::tLDMIA:
   case ARM::t2LDMIA:
   case ARM::t2LDMIA_UPD:
   case ARM::t2LDMDB:
index 4fec4b7e982c633364bc3f4e9d01dc7afcbec410..de38c7f15e0924795e039b088567e646a1320c64 100644 (file)
@@ -16,11 +16,11 @@ _func:
 @ SMC
 @------------------------------------------------------------------------------
         smc #0xf
-        ite eq
+        it eq
         smceq #0
 
 @ NOTZ-NOT: smc        #15
 @ NOTZ-NOT: smceq      #0
 @ TZ: smc      #15                     @ encoding: [0xff,0xf7,0x00,0x80]
-@ TZ: ite      eq                      @ encoding: [0x0c,0xbf]
+@ TZ: it       eq                      @ encoding: [0x08,0xbf]
 @ TZ: smceq    #0                      @ encoding: [0xf0,0xf7,0x00,0x80]
index 1ef0d8eb11b9f1aa9c43d78a668f323dab705b05..af1b6289755eff58073474e2bd87539657629993 100644 (file)
@@ -3093,13 +3093,15 @@ _func:
 @ SVC
 @------------------------------------------------------------------------------
         svc #0
-        ite eq
+        it eq
         svceq #255
+        it ne
         swine #33
 
 @ CHECK: svc   #0                      @ encoding: [0x00,0xdf]
-@ CHECK: ite   eq                      @ encoding: [0x0c,0xbf]
+@ CHECK: it    eq                      @ encoding: [0x08,0xbf]
 @ CHECK: svceq #255                    @ encoding: [0xff,0xdf]
+@ CHECK: it    ne                      @ encoding: [0x18,0xbf]
 @ CHECK: svcne #33                     @ encoding: [0x21,0xdf]
 
 
diff --git a/test/MC/ARM/unpred-control-flow-in-it-block.s b/test/MC/ARM/unpred-control-flow-in-it-block.s
new file mode 100644 (file)
index 0000000..885d158
--- /dev/null
@@ -0,0 +1,57 @@
+@ RUN: not llvm-mc -triple=thumbv7m--none-eabi < %s 2>&1 | FileCheck %s
+
+@ These instructions all write to the PC, so are UNPREDICTABLE if they are in
+@ an IT block, but not the last instruction in the block.
+
+  itttt eq
+  addeq pc, r0
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  addeq pc, sp, pc
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  beq.n #.+0x20
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itttt eq
+  beq.w #.+0x20
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  bleq sym
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  blxeq r0
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itttt eq
+  bxeq r0
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  ldmeq r0, {r8, pc}
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  ldmdbeq r0, {r8, pc}
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itttt eq
+  ldreq pc, [r0, #4]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  ldreq pc, [r0, #-4]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  ldreq pc, [pc, #4]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itttt eq
+  ldreq pc, [r0, r1, LSL #1]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  moveq pc, r0
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  popeq {r0, pc}
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itttt eq
+  popeq {r8, pc}
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  popeq {pc}
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  tbbeq [r0, r1]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq
+  itt eq
+  tbheq [r0, r1, LSL #1]
+@ CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: instruction must be outside of IT block or the last instruction in an IT block
+  nopeq