[ARM] Diagnose PC-writing instructions in IT blocks

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

llvm-svn: 296459
This commit is contained in:
Oliver Stannard 2017-02-28 10:04:36 +00:00
parent 3a7e13140a
commit 85d4d5b493
4 changed files with 70 additions and 8 deletions

View 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:

View 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]

View 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]

View File

@ -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