Skip to content

Commit 114c37e

Browse files
committedAug 13, 2019
[ARM] Fix detection of duplicates when parsing reg list operands
Differential Revision: https://reviews.llvm.org/D65957 llvm-svn: 368712
1 parent f990e4a commit 114c37e

File tree

2 files changed

+109
-19
lines changed

2 files changed

+109
-19
lines changed
 

Diff for: ‎llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

+43-19
Original file line numberDiff line numberDiff line change
@@ -3559,16 +3559,15 @@ class ARMOperand : public MCParsedAsmOperand {
35593559
Kind = k_SPRRegisterList;
35603560
}
35613561

3562-
// Sort based on the register encoding values.
3563-
array_pod_sort(Regs.begin(), Regs.end());
3564-
35653562
if (Kind == k_RegisterList && Regs.back().second == ARM::APSR)
35663563
Kind = k_RegisterListWithAPSR;
35673564

3565+
assert(std::is_sorted(Regs.begin(), Regs.end()) &&
3566+
"Register list must be sorted by encoding");
3567+
35683568
auto Op = make_unique<ARMOperand>(Kind);
3569-
for (SmallVectorImpl<std::pair<unsigned, unsigned>>::const_iterator
3570-
I = Regs.begin(), E = Regs.end(); I != E; ++I)
3571-
Op->Registers.push_back(I->second);
3569+
for (const auto &P : Regs)
3570+
Op->Registers.push_back(P.second);
35723571

35733572
Op->StartLoc = StartLoc;
35743573
Op->EndLoc = EndLoc;
@@ -4269,6 +4268,24 @@ static unsigned getNextRegister(unsigned Reg) {
42694268
}
42704269
}
42714270

4271+
// Insert an <Encoding, Register> pair in an ordered vector. Return true on
4272+
// success, or false, if duplicate encoding found.
4273+
static bool
4274+
insertNoDuplicates(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
4275+
unsigned Enc, unsigned Reg) {
4276+
Regs.emplace_back(Enc, Reg);
4277+
for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) {
4278+
if (J->first == Enc) {
4279+
Regs.erase(J.base());
4280+
return false;
4281+
}
4282+
if (J->first < Enc)
4283+
break;
4284+
std::swap(*I, *J);
4285+
}
4286+
return true;
4287+
}
4288+
42724289
/// Parse a register list.
42734290
bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
42744291
bool EnforceOrder) {
@@ -4294,7 +4311,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
42944311
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
42954312
Reg = getDRegFromQReg(Reg);
42964313
EReg = MRI->getEncodingValue(Reg);
4297-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4314+
Registers.emplace_back(EReg, Reg);
42984315
++Reg;
42994316
}
43004317
const MCRegisterClass *RC;
@@ -4311,7 +4328,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
43114328

43124329
// Store the register.
43134330
EReg = MRI->getEncodingValue(Reg);
4314-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4331+
Registers.emplace_back(EReg, Reg);
43154332

43164333
// This starts immediately after the first register token in the list,
43174334
// so we can see either a comma or a minus (range separator) as a legal
@@ -4342,7 +4359,11 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
43424359
while (Reg != EndReg) {
43434360
Reg = getNextRegister(Reg);
43444361
EReg = MRI->getEncodingValue(Reg);
4345-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4362+
if (!insertNoDuplicates(Registers, EReg, Reg)) {
4363+
Warning(AfterMinusLoc, StringRef("duplicated register (") +
4364+
ARMInstPrinter::getRegisterName(Reg) +
4365+
") in register list");
4366+
}
43464367
}
43474368
continue;
43484369
}
@@ -4366,11 +4387,16 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
43664387
// subset of GPRRegClassId except it contains APSR as well.
43674388
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID];
43684389
}
4369-
if (Reg == ARM::VPR && (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
4370-
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID])) {
4390+
if (Reg == ARM::VPR &&
4391+
(RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
4392+
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] ||
4393+
RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) {
43714394
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID];
43724395
EReg = MRI->getEncodingValue(Reg);
4373-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4396+
if (!insertNoDuplicates(Registers, EReg, Reg)) {
4397+
Warning(RegLoc, "duplicated register (" + RegTok.getString() +
4398+
") in register list");
4399+
}
43744400
continue;
43754401
}
43764402
// The register must be in the same register class as the first.
@@ -4387,21 +4413,19 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
43874413
else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
43884414
return Error(RegLoc, "register list not in ascending order");
43894415
}
4390-
if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
4391-
Warning(RegLoc, "duplicated register (" + RegTok.getString() +
4392-
") in register list");
4393-
continue;
4394-
}
43954416
// VFP register lists must also be contiguous.
43964417
if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
43974418
RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] &&
43984419
Reg != OldReg + 1)
43994420
return Error(RegLoc, "non-contiguous register range");
44004421
EReg = MRI->getEncodingValue(Reg);
4401-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4422+
if (!insertNoDuplicates(Registers, EReg, Reg)) {
4423+
Warning(RegLoc, "duplicated register (" + RegTok.getString() +
4424+
") in register list");
4425+
}
44024426
if (isQReg) {
44034427
EReg = MRI->getEncodingValue(++Reg);
4404-
Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
4428+
Registers.emplace_back(EReg, Reg);
44054429
}
44064430
}
44074431

Diff for: ‎llvm/test/MC/ARM/register-list-dup.s

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -show-encoding < %s 2>&1 | FileCheck -strict-whitespace %s
2+
3+
clrm {r0, r0}
4+
// CHECK: warning: duplicated register (r0) in register list
5+
// CHECK-NEXT: {{^clrm {r0, r0}}}
6+
// CHECK-NEXT: {{^ \^}}
7+
8+
clrm {r0, r0, r1}
9+
// CHECK: warning: duplicated register (r0) in register list
10+
// CHECK-NEXT: {{^clrm {r0, r0, r1}}}
11+
// CHECK-NEXT: {{^ \^}}
12+
13+
clrm {r0, r1, r0}
14+
// CHECK: warning: duplicated register (r0) in register list
15+
// CHECK-NEXT: {{^clrm {r0, r1, r0}}}
16+
// CHECK-NEXT: {{^ \^}}
17+
18+
clrm {r0, r1, r1}
19+
// CHECK: warning: duplicated register (r1) in register list
20+
// CHECK-NEXT: {{^clrm {r0, r1, r1}}}
21+
// CHECK-NEXT: {{^ \^}}
22+
23+
clrm {r1, r0, r1}
24+
// CHECK: warning: duplicated register (r1) in register list
25+
// CHECK-NEXT: {{^clrm {r1, r0, r1}}}
26+
// CHECK-NEXT: {{^ \^}}
27+
28+
clrm {r1, r1, r0}
29+
// CHECK: warning: duplicated register (r1) in register list
30+
// CHECK-NEXT: {{^clrm {r1, r1, r0}}}
31+
// CHECK-NEXT: {{^ \^}}
32+
33+
clrm {r0-r3, r0}
34+
// CHECK: warning: duplicated register (r0) in register list
35+
// CHECK-NEXT: {{^clrm {r0-r3, r0}}}
36+
// CHECK-NEXT: {{^ \^}}
37+
38+
clrm {r2, r0-r3}
39+
// CHECK: warning: duplicated register (r2) in register list
40+
// CHECK-NEXT: {{^clrm {r2, r0-r3}}}
41+
// CHECK-NEXT: {{^ \^}}
42+
43+
vscclrm {s0, s0, s1, vpr}
44+
// CHECK: error: non-contiguous register range
45+
// CHECK: {{^vscclrm {s0, s0, s1, vpr}}}
46+
// CHECK: {{^ \^}}
47+
48+
vscclrm {s0-s3, vpr, s4}
49+
// CHECK: error: register list not in ascending order
50+
// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, s4}}}
51+
// CHECK-NEXT: {{^ \^}}
52+
53+
vscclrm {s0-s3, vpr, vpr}
54+
// CHECK: warning: duplicated register (vpr) in register list
55+
// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, vpr}}}
56+
// CHECK-NEXT: {{^ \^}}
57+
58+
vscclrm {q2, d4, vpr}
59+
// CHECK: error: register list not in ascending order
60+
// CHECK-NEXT: {{^vscclrm {q2, d4, vpr}}}
61+
// CHECK-NEXT: {{^ \^}}
62+
63+
vscclrm {q2, d5, vpr}
64+
// CHECK: error: non-contiguous register range
65+
// CHECK-NEXT: {{^vscclrm {q2, d5, vpr}}}
66+
// CHECK-NEXT: {{^ \^}}

0 commit comments

Comments
 (0)
Please sign in to comment.