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;
}
}
+// 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) {
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;
// 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
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;
}
// 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.
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);
}
}
--- /dev/null
+// 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: {{^ \^}}