Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 446 Lines • ▼ Show 20 Lines | class ARMAsmParser : public MCTargetAsmParser { | ||||
bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, | bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, | ||||
unsigned ListNo, bool IsARPop = false); | unsigned ListNo, bool IsARPop = false); | ||||
bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, | bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, | ||||
unsigned ListNo); | unsigned ListNo); | ||||
int tryParseRegister(); | int tryParseRegister(); | ||||
bool tryParseRegisterWithWriteBack(OperandVector &); | bool tryParseRegisterWithWriteBack(OperandVector &); | ||||
int tryParseShiftRegister(OperandVector &); | int tryParseShiftRegister(OperandVector &); | ||||
bool parseRegisterList(OperandVector &, bool EnforceOrder = true); | bool parseRegisterList(OperandVector &, bool EnforceOrder = true, | ||||
bool AllowRAAC = false); | |||||
bool parseMemory(OperandVector &); | bool parseMemory(OperandVector &); | ||||
bool parseOperand(OperandVector &, StringRef Mnemonic); | bool parseOperand(OperandVector &, StringRef Mnemonic); | ||||
bool parsePrefix(ARMMCExpr::VariantKind &RefKind); | bool parsePrefix(ARMMCExpr::VariantKind &RefKind); | ||||
bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, | bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType, | ||||
unsigned &ShiftAmount); | unsigned &ShiftAmount); | ||||
bool parseLiteralValues(unsigned Size, SMLoc L); | bool parseLiteralValues(unsigned Size, SMLoc L); | ||||
bool parseDirectiveThumb(SMLoc L); | bool parseDirectiveThumb(SMLoc L); | ||||
bool parseDirectiveARM(SMLoc L); | bool parseDirectiveARM(SMLoc L); | ||||
▲ Show 20 Lines • Show All 3,995 Lines • ▼ Show 20 Lines | for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) { | ||||
if (J->first < Enc) | if (J->first < Enc) | ||||
break; | break; | ||||
std::swap(*I, *J); | std::swap(*I, *J); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/// Parse a register list. | /// Parse a register list. | ||||
bool ARMAsmParser::parseRegisterList(OperandVector &Operands, | bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, | ||||
bool EnforceOrder) { | bool AllowRAAC) { | ||||
MCAsmParser &Parser = getParser(); | MCAsmParser &Parser = getParser(); | ||||
if (Parser.getTok().isNot(AsmToken::LCurly)) | if (Parser.getTok().isNot(AsmToken::LCurly)) | ||||
return TokError("Token is not a Left Curly Brace"); | return TokError("Token is not a Left Curly Brace"); | ||||
SMLoc S = Parser.getTok().getLoc(); | SMLoc S = Parser.getTok().getLoc(); | ||||
Parser.Lex(); // Eat '{' token. | Parser.Lex(); // Eat '{' token. | ||||
SMLoc RegLoc = Parser.getTok().getLoc(); | SMLoc RegLoc = Parser.getTok().getLoc(); | ||||
// Check the first register in the list to see what register class | // Check the first register in the list to see what register class | ||||
// this is a list of. | // this is a list of. | ||||
int Reg = tryParseRegister(); | int Reg = tryParseRegister(); | ||||
if (Reg == -1) | if (Reg == -1) | ||||
return Error(RegLoc, "register expected"); | return Error(RegLoc, "register expected"); | ||||
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) | |||||
return Error(RegLoc, "pseudo-register not allowed"); | |||||
// The reglist instructions have at most 16 registers, so reserve | // The reglist instructions have at most 16 registers, so reserve | ||||
// space for that many. | // space for that many. | ||||
int EReg = 0; | int EReg = 0; | ||||
SmallVector<std::pair<unsigned, unsigned>, 16> Registers; | SmallVector<std::pair<unsigned, unsigned>, 16> Registers; | ||||
// Allow Q regs and just interpret them as the two D sub-registers. | // Allow Q regs and just interpret them as the two D sub-registers. | ||||
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { | if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { | ||||
Reg = getDRegFromQReg(Reg); | Reg = getDRegFromQReg(Reg); | ||||
EReg = MRI->getEncodingValue(Reg); | EReg = MRI->getEncodingValue(Reg); | ||||
Registers.emplace_back(EReg, Reg); | Registers.emplace_back(EReg, Reg); | ||||
++Reg; | ++Reg; | ||||
} | } | ||||
const MCRegisterClass *RC; | const MCRegisterClass *RC; | ||||
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) | if (Reg == ARM::RA_AUTH_CODE || | ||||
ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) | |||||
RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; | RC = &ARMMCRegisterClasses[ARM::GPRRegClassID]; | ||||
else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) | else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) | ||||
RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; | RC = &ARMMCRegisterClasses[ARM::DPRRegClassID]; | ||||
else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) | else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg)) | ||||
RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; | RC = &ARMMCRegisterClasses[ARM::SPRRegClassID]; | ||||
else if (ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) | else if (ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) | ||||
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; | RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; | ||||
else | else | ||||
return Error(RegLoc, "invalid register in register list"); | return Error(RegLoc, "invalid register in register list"); | ||||
// Store the register. | // Store the register. | ||||
EReg = MRI->getEncodingValue(Reg); | EReg = MRI->getEncodingValue(Reg); | ||||
Registers.emplace_back(EReg, Reg); | Registers.emplace_back(EReg, Reg); | ||||
// This starts immediately after the first register token in the list, | // 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 | // so we can see either a comma or a minus (range separator) as a legal | ||||
// next token. | // next token. | ||||
while (Parser.getTok().is(AsmToken::Comma) || | while (Parser.getTok().is(AsmToken::Comma) || | ||||
Parser.getTok().is(AsmToken::Minus)) { | Parser.getTok().is(AsmToken::Minus)) { | ||||
if (Parser.getTok().is(AsmToken::Minus)) { | if (Parser.getTok().is(AsmToken::Minus)) { | ||||
if (Reg == ARM::RA_AUTH_CODE) | |||||
return Error(RegLoc, "pseudo-register not allowed"); | |||||
Parser.Lex(); // Eat the minus. | Parser.Lex(); // Eat the minus. | ||||
SMLoc AfterMinusLoc = Parser.getTok().getLoc(); | SMLoc AfterMinusLoc = Parser.getTok().getLoc(); | ||||
int EndReg = tryParseRegister(); | int EndReg = tryParseRegister(); | ||||
if (EndReg == -1) | if (EndReg == -1) | ||||
return Error(AfterMinusLoc, "register expected"); | return Error(AfterMinusLoc, "register expected"); | ||||
if (EndReg == ARM::RA_AUTH_CODE) | |||||
return Error(AfterMinusLoc, "pseudo-register not allowed"); | |||||
// Allow Q regs and just interpret them as the two D sub-registers. | // Allow Q regs and just interpret them as the two D sub-registers. | ||||
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) | if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg)) | ||||
EndReg = getDRegFromQReg(EndReg) + 1; | EndReg = getDRegFromQReg(EndReg) + 1; | ||||
// If the register is the same as the start reg, there's nothing | // If the register is the same as the start reg, there's nothing | ||||
// more to do. | // more to do. | ||||
if (Reg == EndReg) | if (Reg == EndReg) | ||||
continue; | continue; | ||||
// The register must be in the same register class as the first. | // The register must be in the same register class as the first. | ||||
if (!RC->contains(EndReg)) | if ((Reg == ARM::RA_AUTH_CODE && | ||||
RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) || | |||||
(Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg))) | |||||
return Error(AfterMinusLoc, "invalid register in register list"); | return Error(AfterMinusLoc, "invalid register in register list"); | ||||
RKSimon: @stuij Static analysis is warning about dead code here - we've already handled the Reg == ARM… | |||||
stuijAuthorUnsubmitted Thanks! Made https://reviews.llvm.org/D122577 for this. stuij: Thanks! Made https://reviews.llvm.org/D122577 for this. | |||||
// Ranges must go from low to high. | // Ranges must go from low to high. | ||||
if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) | if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg)) | ||||
return Error(AfterMinusLoc, "bad range in register list"); | return Error(AfterMinusLoc, "bad range in register list"); | ||||
// Add all the registers in the range to the register list. | // Add all the registers in the range to the register list. | ||||
while (Reg != EndReg) { | while (Reg != EndReg) { | ||||
Reg = getNextRegister(Reg); | Reg = getNextRegister(Reg); | ||||
EReg = MRI->getEncodingValue(Reg); | EReg = MRI->getEncodingValue(Reg); | ||||
if (!insertNoDuplicates(Registers, EReg, Reg)) { | if (!insertNoDuplicates(Registers, EReg, Reg)) { | ||||
Warning(AfterMinusLoc, StringRef("duplicated register (") + | Warning(AfterMinusLoc, StringRef("duplicated register (") + | ||||
ARMInstPrinter::getRegisterName(Reg) + | ARMInstPrinter::getRegisterName(Reg) + | ||||
") in register list"); | ") in register list"); | ||||
} | } | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
Parser.Lex(); // Eat the comma. | Parser.Lex(); // Eat the comma. | ||||
RegLoc = Parser.getTok().getLoc(); | RegLoc = Parser.getTok().getLoc(); | ||||
int OldReg = Reg; | int OldReg = Reg; | ||||
const AsmToken RegTok = Parser.getTok(); | const AsmToken RegTok = Parser.getTok(); | ||||
Reg = tryParseRegister(); | Reg = tryParseRegister(); | ||||
if (Reg == -1) | if (Reg == -1) | ||||
return Error(RegLoc, "register expected"); | return Error(RegLoc, "register expected"); | ||||
if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) | |||||
return Error(RegLoc, "pseudo-register not allowed"); | |||||
// Allow Q regs and just interpret them as the two D sub-registers. | // Allow Q regs and just interpret them as the two D sub-registers. | ||||
bool isQReg = false; | bool isQReg = false; | ||||
if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { | if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { | ||||
Reg = getDRegFromQReg(Reg); | Reg = getDRegFromQReg(Reg); | ||||
isQReg = true; | isQReg = true; | ||||
} | } | ||||
if (!RC->contains(Reg) && | if (Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg) && | ||||
RC->getID() == ARMMCRegisterClasses[ARM::GPRRegClassID].getID() && | RC->getID() == ARMMCRegisterClasses[ARM::GPRRegClassID].getID() && | ||||
ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) { | ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg)) { | ||||
// switch the register classes, as GPRwithAPSRnospRegClassID is a partial | // switch the register classes, as GPRwithAPSRnospRegClassID is a partial | ||||
// subset of GPRRegClassId except it contains APSR as well. | // subset of GPRRegClassId except it contains APSR as well. | ||||
RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; | RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID]; | ||||
} | } | ||||
if (Reg == ARM::VPR && | if (Reg == ARM::VPR && | ||||
(RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] || | (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] || | ||||
RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] || | RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] || | ||||
RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) { | RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) { | ||||
RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID]; | RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID]; | ||||
EReg = MRI->getEncodingValue(Reg); | EReg = MRI->getEncodingValue(Reg); | ||||
if (!insertNoDuplicates(Registers, EReg, Reg)) { | if (!insertNoDuplicates(Registers, EReg, Reg)) { | ||||
Warning(RegLoc, "duplicated register (" + RegTok.getString() + | Warning(RegLoc, "duplicated register (" + RegTok.getString() + | ||||
") in register list"); | ") in register list"); | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
// The register must be in the same register class as the first. | // The register must be in the same register class as the first. | ||||
if (!RC->contains(Reg)) | if ((Reg == ARM::RA_AUTH_CODE && | ||||
RC != &ARMMCRegisterClasses[ARM::GPRRegClassID]) || | |||||
(Reg != ARM::RA_AUTH_CODE && !RC->contains(Reg))) | |||||
return Error(RegLoc, "invalid register in register list"); | return Error(RegLoc, "invalid register in register list"); | ||||
// In most cases, the list must be monotonically increasing. An | // In most cases, the list must be monotonically increasing. An | ||||
// exception is CLRM, which is order-independent anyway, so | // exception is CLRM, which is order-independent anyway, so | ||||
// there's no potential for confusion if you write clrm {r2,r1} | // there's no potential for confusion if you write clrm {r2,r1} | ||||
// instead of clrm {r1,r2}. | // instead of clrm {r1,r2}. | ||||
if (EnforceOrder && | if (EnforceOrder && | ||||
MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { | MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) { | ||||
if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) | if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) | ||||
▲ Show 20 Lines • Show All 7,091 Lines • ▼ Show 20 Lines | if (!UC.hasFnStart()) | ||||
return Error(L, ".fnstart must precede .save or .vsave directives"); | return Error(L, ".fnstart must precede .save or .vsave directives"); | ||||
if (UC.hasHandlerData()) | if (UC.hasHandlerData()) | ||||
return Error(L, ".save or .vsave must precede .handlerdata directive"); | return Error(L, ".save or .vsave must precede .handlerdata directive"); | ||||
// RAII object to make sure parsed operands are deleted. | // RAII object to make sure parsed operands are deleted. | ||||
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands; | ||||
// Parse the register list | // Parse the register list | ||||
if (parseRegisterList(Operands) || | if (parseRegisterList(Operands, true, true) || | ||||
parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) | parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) | ||||
return true; | return true; | ||||
ARMOperand &Op = (ARMOperand &)*Operands[0]; | ARMOperand &Op = (ARMOperand &)*Operands[0]; | ||||
if (!IsVector && !Op.isRegList()) | if (!IsVector && !Op.isRegList()) | ||||
return Error(L, ".save expects GPR registers"); | return Error(L, ".save expects GPR registers"); | ||||
if (IsVector && !Op.isDPRRegList()) | if (IsVector && !Op.isDPRRegList()) | ||||
return Error(L, ".vsave expects DPR registers"); | return Error(L, ".vsave expects DPR registers"); | ||||
▲ Show 20 Lines • Show All 777 Lines • Show Last 20 Lines |
@stuij Static analysis is warning about dead code here - we've already handled the Reg == ARM::RA_AUTH_CODE case at line 4519, should this just be: