summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMomchil Velikov <momchil.velikov@arm.com>2019-08-13 16:13:00 +0000
committerMomchil Velikov <momchil.velikov@arm.com>2019-08-13 16:13:00 +0000
commit114c37e72a5f01f49761b42b3ff45334ed863a81 (patch)
treed8f8203a2a9a53974e5a6212e710a5e2210644bf
parentf990e4a4c7bcc3c3dec6ee8ffac39cc0a27e521a (diff)
downloadbcm5719-llvm-114c37e72a5f01f49761b42b3ff45334ed863a81.tar.gz
bcm5719-llvm-114c37e72a5f01f49761b42b3ff45334ed863a81.zip
[ARM] Fix detection of duplicates when parsing reg list operands
Differential Revision: https://reviews.llvm.org/D65957 llvm-svn: 368712
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp62
-rw-r--r--llvm/test/MC/ARM/register-list-dup.s66
2 files changed, 109 insertions, 19 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 29353d5f349..6b571add7f7 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -3559,16 +3559,15 @@ public:
Kind = k_SPRRegisterList;
}
- // Sort based on the register encoding values.
- array_pod_sort(Regs.begin(), Regs.end());
-
if (Kind == k_RegisterList && Regs.back().second == ARM::APSR)
Kind = k_RegisterListWithAPSR;
+ assert(std::is_sorted(Regs.begin(), Regs.end()) &&
+ "Register list must be sorted by encoding");
+
auto Op = make_unique<ARMOperand>(Kind);
- for (SmallVectorImpl<std::pair<unsigned, unsigned>>::const_iterator
- I = Regs.begin(), E = Regs.end(); I != E; ++I)
- Op->Registers.push_back(I->second);
+ for (const auto &P : Regs)
+ Op->Registers.push_back(P.second);
Op->StartLoc = StartLoc;
Op->EndLoc = EndLoc;
@@ -4269,6 +4268,24 @@ static unsigned getNextRegister(unsigned Reg) {
}
}
+// Insert an <Encoding, Register> pair in an ordered vector. Return true on
+// success, or false, if duplicate encoding found.
+static bool
+insertNoDuplicates(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
+ unsigned Enc, unsigned Reg) {
+ Regs.emplace_back(Enc, Reg);
+ for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) {
+ if (J->first == Enc) {
+ Regs.erase(J.base());
+ return false;
+ }
+ if (J->first < Enc)
+ break;
+ std::swap(*I, *J);
+ }
+ return true;
+}
+
/// Parse a register list.
bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
bool EnforceOrder) {
@@ -4294,7 +4311,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Reg = getDRegFromQReg(Reg);
EReg = MRI->getEncodingValue(Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ Registers.emplace_back(EReg, Reg);
++Reg;
}
const MCRegisterClass *RC;
@@ -4311,7 +4328,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
// Store the register.
EReg = MRI->getEncodingValue(Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ Registers.emplace_back(EReg, Reg);
// This starts immediately after the first register token in the list,
// so we can see either a comma or a minus (range separator) as a legal
@@ -4342,7 +4359,11 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
while (Reg != EndReg) {
Reg = getNextRegister(Reg);
EReg = MRI->getEncodingValue(Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ if (!insertNoDuplicates(Registers, EReg, Reg)) {
+ Warning(AfterMinusLoc, StringRef("duplicated register (") +
+ ARMInstPrinter::getRegisterName(Reg) +
+ ") in register list");
+ }
}
continue;
}
@@ -4366,11 +4387,16 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
// subset of GPRRegClassId except it contains APSR as well.
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID];
}
- if (Reg == ARM::VPR && (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
- RC == &ARMMCRegisterClasses[ARM::DPRRegClassID])) {
+ if (Reg == ARM::VPR &&
+ (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
+ RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] ||
+ RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) {
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID];
EReg = MRI->getEncodingValue(Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ if (!insertNoDuplicates(Registers, EReg, Reg)) {
+ Warning(RegLoc, "duplicated register (" + RegTok.getString() +
+ ") in register list");
+ }
continue;
}
// The register must be in the same register class as the first.
@@ -4387,21 +4413,19 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
return Error(RegLoc, "register list not in ascending order");
}
- if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
- Warning(RegLoc, "duplicated register (" + RegTok.getString() +
- ") in register list");
- continue;
- }
// VFP register lists must also be contiguous.
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] &&
Reg != OldReg + 1)
return Error(RegLoc, "non-contiguous register range");
EReg = MRI->getEncodingValue(Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ if (!insertNoDuplicates(Registers, EReg, Reg)) {
+ Warning(RegLoc, "duplicated register (" + RegTok.getString() +
+ ") in register list");
+ }
if (isQReg) {
EReg = MRI->getEncodingValue(++Reg);
- Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+ Registers.emplace_back(EReg, Reg);
}
}
diff --git a/llvm/test/MC/ARM/register-list-dup.s b/llvm/test/MC/ARM/register-list-dup.s
new file mode 100644
index 00000000000..2e98fa0712c
--- /dev/null
+++ b/llvm/test/MC/ARM/register-list-dup.s
@@ -0,0 +1,66 @@
+// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -show-encoding < %s 2>&1 | FileCheck -strict-whitespace %s
+
+clrm {r0, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r0}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r0, r0, r1}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r0, r1}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r0, r1, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r1, r0}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r0, r1, r1}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r0, r1, r1}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r1, r0, r1}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r1, r0, r1}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r1, r1, r0}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r1, r1, r0}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r0-r3, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0-r3, r0}}}
+// CHECK-NEXT: {{^ \^}}
+
+clrm {r2, r0-r3}
+// CHECK: warning: duplicated register (r2) in register list
+// CHECK-NEXT: {{^clrm {r2, r0-r3}}}
+// CHECK-NEXT: {{^ \^}}
+
+vscclrm {s0, s0, s1, vpr}
+// CHECK: error: non-contiguous register range
+// CHECK: {{^vscclrm {s0, s0, s1, vpr}}}
+// CHECK: {{^ \^}}
+
+vscclrm {s0-s3, vpr, s4}
+// CHECK: error: register list not in ascending order
+// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, s4}}}
+// CHECK-NEXT: {{^ \^}}
+
+vscclrm {s0-s3, vpr, vpr}
+// CHECK: warning: duplicated register (vpr) in register list
+// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, vpr}}}
+// CHECK-NEXT: {{^ \^}}
+
+vscclrm {q2, d4, vpr}
+// CHECK: error: register list not in ascending order
+// CHECK-NEXT: {{^vscclrm {q2, d4, vpr}}}
+// CHECK-NEXT: {{^ \^}}
+
+vscclrm {q2, d5, vpr}
+// CHECK: error: non-contiguous register range
+// CHECK-NEXT: {{^vscclrm {q2, d5, vpr}}}
+// CHECK-NEXT: {{^ \^}}
OpenPOWER on IntegriCloud