[llvm] r315305 - [ARM, Asm] Harden GNU LDRD/STRD aliases against invalid inputs
Oliver Stannard via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 10 05:38:22 PDT 2017
Author: olista01
Date: Tue Oct 10 05:38:22 2017
New Revision: 315305
URL: http://llvm.org/viewvc/llvm-project?rev=315305&view=rev
Log:
[ARM, Asm] Harden GNU LDRD/STRD aliases against invalid inputs
Previously, the code that implemented the GNU assembler aliases for the
LDRD and STRD instructions (where the second register is omitted)
assumed that the input was a valid instruction. This caused assertion
failures for every example in ldrd-strd-gnu-bad-inst.s.
This improves this code so that it bails out if the instruction is not
in the expected format, the check bails out, and the asm parser is run
on the unmodified instruction.
It also relaxes the alias on thumb targets, so that unaligned pairs of
registers can be used. The restriction that Rt must be even-numbered
only applies to the ARM versions of these instructions.
Differential revision: https://reviews.llvm.org/D36732
Added:
llvm/trunk/test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s
llvm/trunk/test/MC/ARM/ldrd-strd-gnu-bad-inst.s
Modified:
llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/trunk/test/MC/ARM/ldrd-strd-gnu-sp.s
llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s
llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb.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=315305&r1=315304&r2=315305&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Tue Oct 10 05:38:22 2017
@@ -564,6 +564,7 @@ class ARMAsmParser : public MCTargetAsmP
bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
bool isITBlockTerminator(MCInst &Inst) const;
+ void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands);
public:
enum ARMMatchResultTy {
@@ -5865,6 +5866,52 @@ static bool RequiresVFPRegListValidation
return false;
}
+// The GNU assembler has aliases of ldrd and strd with the second register
+// omitted. We don't have a way to do that in tablegen, so fix it up here.
+//
+// We have to be careful to not emit an invalid Rt2 here, because the rest of
+// the assmebly parser could then generate confusing diagnostics refering to
+// it. If we do find anything that prevents us from doing the transformation we
+// bail out, and let the assembly parser report an error on the instruction as
+// it is written.
+void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic,
+ OperandVector &Operands) {
+ if (Mnemonic != "ldrd" && Mnemonic != "strd")
+ return;
+ if (Operands.size() < 4)
+ return;
+
+ ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
+ ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
+
+ if (!Op2.isReg())
+ return;
+ if (!Op3.isMem())
+ return;
+
+ const MCRegisterClass &GPR = MRI->getRegClass(ARM::GPRRegClassID);
+ if (!GPR.contains(Op2.getReg()))
+ return;
+
+ unsigned RtEncoding = MRI->getEncodingValue(Op2.getReg());
+ if (!isThumb() && (RtEncoding & 1)) {
+ // In ARM mode, the registers must be from an aligned pair, this
+ // restriction does not apply in Thumb mode.
+ return;
+ }
+ if (Op2.getReg() == ARM::PC)
+ return;
+ unsigned PairedReg = GPR.getRegister(RtEncoding + 1);
+ if (!PairedReg || PairedReg == ARM::PC ||
+ (PairedReg == ARM::SP && !hasV8Ops()))
+ return;
+
+ Operands.insert(
+ Operands.begin() + 3,
+ ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc()));
+ return;
+}
+
/// Parse an arm instruction mnemonic followed by its operands.
bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
@@ -6107,25 +6154,8 @@ bool ARMAsmParser::ParseInstruction(Pars
}
}
- // GNU Assembler extension (compatibility)
- if ((Mnemonic == "ldrd" || Mnemonic == "strd")) {
- ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
- ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
- if (Op3.isMem()) {
- assert(Op2.isReg() && "expected register argument");
-
- unsigned SuperReg = MRI->getMatchingSuperReg(
- Op2.getReg(), ARM::gsub_0, &MRI->getRegClass(ARM::GPRPairRegClassID));
-
- assert(SuperReg && "expected register pair");
-
- unsigned PairedReg = MRI->getSubReg(SuperReg, ARM::gsub_1);
-
- Operands.insert(
- Operands.begin() + 3,
- ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc()));
- }
- }
+ // GNU Assembler extension (compatibility).
+ fixupGNULDRDAlias(Mnemonic, Operands);
// FIXME: As said above, this is all a pretty gross hack. This instruction
// does not fit with other "subs" and tblgen.
Added: llvm/trunk/test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s?rev=315305&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s (added)
+++ llvm/trunk/test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s Tue Oct 10 05:38:22 2017
@@ -0,0 +1,19 @@
+@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
+
+.text
+.arm
+@ CHECK: error: invalid instruction
+@ CHECK: ldrd r12, [r0, #512]
+ ldrd r12, [r0, #512]
+
+@ CHECK: error: invalid instruction
+@ CHECK: strd r12, [r0, #512]
+ strd r12, [r0, #512]
+
+@ CHECK: error: invalid instruction
+@ CHECK: ldrd r1, [r0, #512]
+ ldrd r1, [r0, #512]
+
+@ CHECK: error: invalid instruction
+@ CHECK: strd r1, [r0, #512]
+ strd r1, [r0, #512]
Added: llvm/trunk/test/MC/ARM/ldrd-strd-gnu-bad-inst.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/ldrd-strd-gnu-bad-inst.s?rev=315305&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/ldrd-strd-gnu-bad-inst.s (added)
+++ llvm/trunk/test/MC/ARM/ldrd-strd-gnu-bad-inst.s Tue Oct 10 05:38:22 2017
@@ -0,0 +1,29 @@
+@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
+
+ .text
+ .thumb
+@ CHECK: error: invalid instruction
+ strd
+@ CHECK: error: invalid instruction
+ ldrd
+@ CHECK: error: invalid instruction
+ strd r0
+@ CHECK: error: invalid instruction
+ ldrd r0
+@ CHECK: error: invalid instruction
+ strd s0, [r0]
+@ CHECK: error: invalid instruction
+ ldrd s0, [r0]
+ .arm
+@ CHECK: error: invalid instruction
+ strd
+@ CHECK: error: invalid instruction
+ ldrd
+@ CHECK: error: invalid instruction
+ strd r0
+@ CHECK: error: invalid instruction
+ ldrd r0
+@ CHECK: error: invalid instruction
+ strd s0, [r0]
+@ CHECK: error: invalid instruction
+ ldrd s0, [r0]
Modified: llvm/trunk/test/MC/ARM/ldrd-strd-gnu-sp.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/ldrd-strd-gnu-sp.s?rev=315305&r1=315304&r2=315305&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/ldrd-strd-gnu-sp.s (original)
+++ llvm/trunk/test/MC/ARM/ldrd-strd-gnu-sp.s Tue Oct 10 05:38:22 2017
@@ -1,9 +1,27 @@
// PR19320
-// RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s
-.text
+// RUN: not llvm-mc -triple=armv7a-linux-gnueabi -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=V7
+// RUN: llvm-mc -triple=armv8a-linux-gnueabi -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=V8
+ .text
-// CHECK: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xc2,0xc0,0xe1]
+// This tries to use the GNU ldrd/strd alias to create an ldrd/strd instruction
+// using the sp register. This is valid for V8, but not earlier architectures.
+
+ .arm
+
+// V7: error: invalid instruction
+// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xc2,0xc0,0xe1]
+ ldrd r12, [r0, #32]
+
+// V7: error: invalid instruction
+// V8: strd r12, sp, [r0, #32] @ encoding: [0xf0,0xc2,0xc0,0xe1]
+ strd r12, [r0, #32]
+
+ .thumb
+
+// V7: error: invalid instruction
+// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xe9,0x08,0xcd]
ldrd r12, [r0, #32]
-// CHECK: strd r12, sp, [r0, #32] @ encoding: [0xf0,0xc2,0xc0,0xe1]
+// V7: error: invalid instruction
+// V8: strd r12, sp, [r0, #32] @ encoding: [0xc0,0xe9,0x08,0xcd]
strd r12, [r0, #32]
Modified: llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s?rev=315305&r1=315304&r2=315305&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s (original)
+++ llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s Tue Oct 10 05:38:22 2017
@@ -1,14 +1,11 @@
@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
-@ FIXME: These errors are inaccurate because the error is being reported on the
-@ implicit r13 operand added after r12.
-
.text
.thumb
-@ CHECK: error: operand must be a register in range [r0, r12] or r14
+@ CHECK: error: invalid instruction
@ CHECK: ldrd r12, [r0, #512]
ldrd r12, [r0, #512]
-@ CHECK: error: operand must be a register in range [r0, r12] or r14
+@ CHECK: error: invalid instruction
@ CHECK: strd r12, [r0, #512]
strd r12, [r0, #512]
Modified: llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb.s?rev=315305&r1=315304&r2=315305&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb.s (original)
+++ llvm/trunk/test/MC/ARM/ldrd-strd-gnu-thumb.s Tue Oct 10 05:38:22 2017
@@ -18,3 +18,18 @@
strd r0, [r10, #512]!
strd r0, [r10], #512
strd r0, [r10, #512]
+
+@ Rt is allowed to be odd for Thumb (but not ARM)
+@ CHECK: ldrd r1, r2, [r10, #512]! @ encoding: [0xfa,0xe9,0x80,0x12]
+@ CHECK: ldrd r1, r2, [r10], #512 @ encoding: [0xfa,0xe8,0x80,0x12]
+@ CHECK: ldrd r1, r2, [r10, #512] @ encoding: [0xda,0xe9,0x80,0x12]
+ ldrd r1, [r10, #512]!
+ ldrd r1, [r10], #512
+ ldrd r1, [r10, #512]
+
+@ CHECK: strd r1, r2, [r10, #512]! @ encoding: [0xea,0xe9,0x80,0x12]
+@ CHECK: strd r1, r2, [r10], #512 @ encoding: [0xea,0xe8,0x80,0x12]
+@ CHECK: strd r1, r2, [r10, #512] @ encoding: [0xca,0xe9,0x80,0x12]
+ strd r1, [r10, #512]!
+ strd r1, [r10], #512
+ strd r1, [r10, #512]
More information about the llvm-commits
mailing list