From 9d48a0d94bd7f8a1b05d4b4698b0c4f2bb4833a6 Mon Sep 17 00:00:00 2001 From: Momchil Velikov Date: Tue, 13 Aug 2019 16:13:00 +0000 Subject: [PATCH] [ARM] Fix detection of duplicates when parsing reg list operands Differential Revision: https://reviews.llvm.org/D65957 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368712 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 62 ++++++++++++++------- test/MC/ARM/register-list-dup.s | 66 +++++++++++++++++++++++ 2 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 test/MC/ARM/register-list-dup.s diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 29353d5f349..6b571add7f7 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/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(Kind); - for (SmallVectorImpl>::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 pair in an ordered vector. Return true on +// success, or false, if duplicate encoding found. +static bool +insertNoDuplicates(SmallVectorImpl> &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(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(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(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(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(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(EReg, Reg)); + Registers.emplace_back(EReg, Reg); } } diff --git a/test/MC/ARM/register-list-dup.s b/test/MC/ARM/register-list-dup.s new file mode 100644 index 00000000000..2e98fa0712c --- /dev/null +++ b/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: {{^ \^}} -- 2.40.0