X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FAArch64%2FAsmParser%2FAArch64AsmParser.cpp;h=e26420f6ed814acd9ee7c51b517690fdb9f21abc;hb=20bb042d74a95970b4942f38cb2606a84fc279f7;hp=69f51daa99be872ece58c9dd4543ac6e2918a4e2;hpb=60d87672119075cb51749de25b22eb394b5428bb;p=oota-llvm.git diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 69f51daa99b..e26420f6ed8 100644 --- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -9,27 +9,30 @@ #include "MCTargetDesc/AArch64AddressingModes.h" #include "MCTargetDesc/AArch64MCExpr.h" +#include "MCTargetDesc/AArch64TargetStreamer.h" #include "Utils/AArch64BaseInfo.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Twine.h" #include using namespace llvm; @@ -40,8 +43,6 @@ class AArch64Operand; class AArch64AsmParser : public MCTargetAsmParser { private: StringRef Mnemonic; ///< Instruction mnemonic. - MCSubtargetInfo &STI; - MCAsmParser &Parser; // Map of register aliases registers via the .req directive. StringMap > RegisterReqs; @@ -51,10 +52,7 @@ private: return static_cast(TS); } - MCAsmParser &getParser() const { return Parser; } - MCAsmLexer &getLexer() const { return Parser.getLexer(); } - - SMLoc getLoc() const { return Parser.getTok().getLoc(); } + SMLoc getLoc() const { return getParser().getTok().getLoc(); } bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands); AArch64CC::CondCode parseCondCodeString(StringRef Cond); @@ -68,11 +66,13 @@ private: bool parseOperand(OperandVector &Operands, bool isCondCode, bool invertCondCode); - void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } - bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } + void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); } + bool Error(SMLoc L, const Twine &Msg) { return getParser().Error(L, Msg); } bool showMatchError(SMLoc Loc, unsigned ErrCode); bool parseDirectiveWord(unsigned Size, SMLoc L); + bool parseDirectiveInst(SMLoc L); + bool parseDirectiveTLSDescCall(SMLoc L); bool parseDirectiveLOH(StringRef LOH, SMLoc L); @@ -84,7 +84,7 @@ private: bool validateInstruction(MCInst &Inst, SmallVectorImpl &Loc); bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) override; /// @name Auto-generated Match Functions /// { @@ -106,6 +106,7 @@ private: OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands); OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands); bool tryParseVectorRegister(OperandVector &Operands); + OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands); public: enum AArch64MatchResultTy { @@ -113,16 +114,16 @@ public: #define GET_OPERAND_DIAGNOSTIC_TYPES #include "AArch64GenAsmMatcher.inc" }; - AArch64AsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) - : MCTargetAsmParser(), STI(_STI), Parser(_Parser) { - MCAsmParserExtension::Initialize(_Parser); - if (Parser.getStreamer().getTargetStreamer() == nullptr) - new AArch64TargetStreamer(Parser.getStreamer()); + AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options, STI) { + MCAsmParserExtension::Initialize(Parser); + MCStreamer &S = getParser().getStreamer(); + if (S.getTargetStreamer() == nullptr) + new AArch64TargetStreamer(S); // Initialize the set of available features. - setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); } bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -204,14 +205,16 @@ private: struct BarrierOp { unsigned Val; // Not the enum since not all values have names. + const char *Data; + unsigned Length; }; struct SysRegOp { const char *Data; unsigned Length; - uint64_t FeatureBits; // We need to pass through information about which - // core we are compiling for so that the SysReg - // Mappers can appropriately conditionalize. + uint32_t MRSReg; + uint32_t MSRReg; + uint32_t PStateField; }; struct SysCRImmOp { @@ -220,6 +223,8 @@ private: struct PrefetchOp { unsigned Val; + const char *Data; + unsigned Length; }; struct ShiftExtendOp { @@ -253,8 +258,7 @@ private: MCContext &Ctx; public: - AArch64Operand(KindTy K, MCContext &_Ctx) - : MCParsedAsmOperand(), Kind(K), Ctx(_Ctx) {} + AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {} AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) { Kind = o.Kind; @@ -348,6 +352,11 @@ public: return Barrier.Val; } + StringRef getBarrierName() const { + assert(Kind == k_Barrier && "Invalid access!"); + return StringRef(Barrier.Data, Barrier.Length); + } + unsigned getReg() const override { assert(Kind == k_Register && "Invalid access!"); return Reg.RegNum; @@ -373,11 +382,6 @@ public: return StringRef(SysReg.Data, SysReg.Length); } - uint64_t getSysRegFeatureBits() const { - assert(Kind == k_SysReg && "Invalid access!"); - return SysReg.FeatureBits; - } - unsigned getSysCR() const { assert(Kind == k_SysCR && "Invalid access!"); return SysCRImm.Val; @@ -388,6 +392,11 @@ public: return Prefetch.Val; } + StringRef getPrefetchName() const { + assert(Kind == k_Prefetch && "Invalid access!"); + return StringRef(Prefetch.Data, Prefetch.Length); + } + AArch64_AM::ShiftExtendType getShiftExtendType() const { assert(Kind == k_ShiftExtend && "Invalid access!"); return ShiftExtend.Type; @@ -487,6 +496,15 @@ public: return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000; } + bool isImm0_1() const { + if (!isImm()) + return false; + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) + return false; + int64_t Val = MCE->getValue(); + return (Val >= 0 && Val < 2); + } bool isImm0_7() const { if (!isImm()) return false; @@ -633,6 +651,23 @@ public: return false; return AArch64_AM::isLogicalImmediate(MCE->getValue(), 64); } + bool isLogicalImm32Not() const { + if (!isImm()) + return false; + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) + return false; + int64_t Val = ~MCE->getValue() & 0xFFFFFFFF; + return AArch64_AM::isLogicalImmediate(Val, 32); + } + bool isLogicalImm64Not() const { + if (!isImm()) + return false; + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) + return false; + return AArch64_AM::isLogicalImmediate(~MCE->getValue(), 64); + } bool isShiftedImm() const { return Kind == k_ShiftedImm; } bool isAddSubImm() const { if (!isShiftedImm() && !isImm()) @@ -672,6 +707,25 @@ public: const MCConstantExpr *CE = cast(Expr); return CE->getValue() >= 0 && CE->getValue() <= 0xfff; } + bool isAddSubImmNeg() const { + if (!isShiftedImm() && !isImm()) + return false; + + const MCExpr *Expr; + + // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'. + if (isShiftedImm()) { + unsigned Shift = ShiftedImm.ShiftAmount; + Expr = ShiftedImm.Val; + if (Shift != 0 && Shift != 12) + return false; + } else + Expr = getImm(); + + // Otherwise it should be a real negative immediate in range: + const MCConstantExpr *CE = dyn_cast(Expr); + return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff; + } bool isCondCode() const { return Kind == k_CondCode; } bool isSIMDImmType10() const { if (!isImm()) @@ -739,58 +793,47 @@ public: } bool isMovZSymbolG3() const { - static AArch64MCExpr::VariantKind Variants[] = { AArch64MCExpr::VK_ABS_G3 }; - return isMovWSymbol(Variants); + return isMovWSymbol(AArch64MCExpr::VK_ABS_G3); } bool isMovZSymbolG2() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S, - AArch64MCExpr::VK_TPREL_G2, AArch64MCExpr::VK_DTPREL_G2}; - return isMovWSymbol(Variants); + return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S, + AArch64MCExpr::VK_TPREL_G2, + AArch64MCExpr::VK_DTPREL_G2}); } bool isMovZSymbolG1() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S, + return isMovWSymbol({ + AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S, AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1, AArch64MCExpr::VK_DTPREL_G1, - }; - return isMovWSymbol(Variants); + }); } bool isMovZSymbolG0() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S, - AArch64MCExpr::VK_TPREL_G0, AArch64MCExpr::VK_DTPREL_G0}; - return isMovWSymbol(Variants); + return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S, + AArch64MCExpr::VK_TPREL_G0, + AArch64MCExpr::VK_DTPREL_G0}); } bool isMovKSymbolG3() const { - static AArch64MCExpr::VariantKind Variants[] = { AArch64MCExpr::VK_ABS_G3 }; - return isMovWSymbol(Variants); + return isMovWSymbol(AArch64MCExpr::VK_ABS_G3); } bool isMovKSymbolG2() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G2_NC}; - return isMovWSymbol(Variants); + return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC); } bool isMovKSymbolG1() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G1_NC, AArch64MCExpr::VK_TPREL_G1_NC, - AArch64MCExpr::VK_DTPREL_G1_NC - }; - return isMovWSymbol(Variants); + return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC, + AArch64MCExpr::VK_TPREL_G1_NC, + AArch64MCExpr::VK_DTPREL_G1_NC}); } bool isMovKSymbolG0() const { - static AArch64MCExpr::VariantKind Variants[] = { - AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC, - AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC - }; - return isMovWSymbol(Variants); + return isMovWSymbol( + {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC, + AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC}); } template @@ -837,28 +880,19 @@ public: bool isMRSSystemRegister() const { if (!isSysReg()) return false; - bool IsKnownRegister; - auto Mapper = AArch64SysReg::MRSMapper(getSysRegFeatureBits()); - Mapper.fromString(getSysReg(), IsKnownRegister); - - return IsKnownRegister; + return SysReg.MRSReg != -1U; } bool isMSRSystemRegister() const { if (!isSysReg()) return false; - - bool IsKnownRegister; - auto Mapper = AArch64SysReg::MSRMapper(getSysRegFeatureBits()); - Mapper.fromString(getSysReg(), IsKnownRegister); - - return IsKnownRegister; + return SysReg.MSRReg != -1U; } - bool isSystemPStateField() const { + bool isSystemPStateFieldWithImm0_1() const { if (!isSysReg()) return false; - - bool IsKnownRegister; - AArch64PState::PStateMapper().fromString(getSysReg(), IsKnownRegister); - - return IsKnownRegister; + return SysReg.PStateField == AArch64PState::PAN; + } + bool isSystemPStateFieldWithImm0_15() const { + if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false; + return SysReg.PStateField != -1U; } bool isReg() const override { return Kind == k_Register && !Reg.isVector; } bool isVectorReg() const { return Kind == k_Register && Reg.isVector; } @@ -871,6 +905,16 @@ public: return Kind == k_Register && !Reg.isVector && AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum); } + bool isWSeqPair() const { + return Kind == k_Register && !Reg.isVector && + AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains( + Reg.RegNum); + } + bool isXSeqPair() const { + return Kind == k_Register && !Reg.isVector && + AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains( + Reg.RegNum); + } bool isGPR64sp0() const { return Kind == k_Register && !Reg.isVector && @@ -1095,16 +1139,16 @@ public: void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); else if (const MCConstantExpr *CE = dyn_cast(Expr)) - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); else - Inst.addOperand(MCOperand::CreateExpr(Expr)); + Inst.addOperand(MCOperand::createExpr(Expr)); } void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } void addGPR32as64Operands(MCInst &Inst, unsigned N) const { @@ -1116,73 +1160,77 @@ public: uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister( RI->getEncodingValue(getReg())); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); } void addVectorReg64Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); assert( AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg())); - Inst.addOperand(MCOperand::CreateReg(AArch64::D0 + getReg() - AArch64::Q0)); + Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0)); } void addVectorReg128Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); assert( AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg())); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } void addVectorRegLoOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } template void addVectorList64Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - static unsigned FirstRegs[] = { AArch64::D0, AArch64::D0_D1, - AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 }; + static const unsigned FirstRegs[] = { AArch64::D0, + AArch64::D0_D1, + AArch64::D0_D1_D2, + AArch64::D0_D1_D2_D3 }; unsigned FirstReg = FirstRegs[NumRegs - 1]; Inst.addOperand( - MCOperand::CreateReg(FirstReg + getVectorListStart() - AArch64::Q0)); + MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0)); } template void addVectorList128Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - static unsigned FirstRegs[] = { AArch64::Q0, AArch64::Q0_Q1, - AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 }; + static const unsigned FirstRegs[] = { AArch64::Q0, + AArch64::Q0_Q1, + AArch64::Q0_Q1_Q2, + AArch64::Q0_Q1_Q2_Q3 }; unsigned FirstReg = FirstRegs[NumRegs - 1]; Inst.addOperand( - MCOperand::CreateReg(FirstReg + getVectorListStart() - AArch64::Q0)); + MCOperand::createReg(FirstReg + getVectorListStart() - AArch64::Q0)); } void addVectorIndex1Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndexBOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndexHOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndexSOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addVectorIndexDOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); + Inst.addOperand(MCOperand::createImm(getVectorIndex())); } void addImmOperands(MCInst &Inst, unsigned N) const { @@ -1197,16 +1245,28 @@ public: assert(N == 2 && "Invalid number of operands!"); if (isShiftedImm()) { addExpr(Inst, getShiftedImmVal()); - Inst.addOperand(MCOperand::CreateImm(getShiftedImmShift())); + Inst.addOperand(MCOperand::createImm(getShiftedImmShift())); } else { addExpr(Inst, getImm()); - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); } } + void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + + const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm(); + const MCConstantExpr *CE = cast(MCE); + int64_t Val = -CE->getValue(); + unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0; + + Inst.addOperand(MCOperand::createImm(Val)); + Inst.addOperand(MCOperand::createImm(ShiftAmt)); + } + void addCondCodeOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCondCode())); + Inst.addOperand(MCOperand::createImm(getCondCode())); } void addAdrpLabelOperands(MCInst &Inst, unsigned N) const { @@ -1215,7 +1275,7 @@ public: if (!MCE) addExpr(Inst, getImm()); else - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 12)); + Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12)); } void addAdrLabelOperands(MCInst &Inst, unsigned N) const { @@ -1228,161 +1288,163 @@ public: const MCConstantExpr *MCE = dyn_cast(getImm()); if (!MCE) { - Inst.addOperand(MCOperand::CreateExpr(getImm())); + Inst.addOperand(MCOperand::createExpr(getImm())); return; } - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() / Scale)); + Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale)); } void addSImm9Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addSImm7s4Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() / 4)); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4)); } void addSImm7s8Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() / 8)); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8)); } void addSImm7s16Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() / 16)); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16)); + } + + void addImm0_1Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_7Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_8Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_15Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_16Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); + const MCConstantExpr *MCE = cast(getImm()); assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_31Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_31Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_32Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_63Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_63Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm1_64Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_127Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_255Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm0_65535Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addImm32_63Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue())); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue())); } void addLogicalImm32Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid logical immediate operand!"); + const MCConstantExpr *MCE = cast(getImm()); uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue() & 0xFFFFFFFF, 32); - Inst.addOperand(MCOperand::CreateImm(encoding)); + Inst.addOperand(MCOperand::createImm(encoding)); } void addLogicalImm64Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid logical immediate operand!"); + const MCConstantExpr *MCE = cast(getImm()); uint64_t encoding = AArch64_AM::encodeLogicalImmediate(MCE->getValue(), 64); - Inst.addOperand(MCOperand::CreateImm(encoding)); + Inst.addOperand(MCOperand::createImm(encoding)); + } + + void addLogicalImm32NotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = cast(getImm()); + int64_t Val = ~MCE->getValue() & 0xFFFFFFFF; + uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, 32); + Inst.addOperand(MCOperand::createImm(encoding)); + } + + void addLogicalImm64NotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = cast(getImm()); + uint64_t encoding = + AArch64_AM::encodeLogicalImmediate(~MCE->getValue(), 64); + Inst.addOperand(MCOperand::createImm(encoding)); } void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - const MCConstantExpr *MCE = dyn_cast(getImm()); - assert(MCE && "Invalid immediate operand!"); + const MCConstantExpr *MCE = cast(getImm()); uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue()); - Inst.addOperand(MCOperand::CreateImm(encoding)); + Inst.addOperand(MCOperand::createImm(encoding)); } void addBranchTarget26Operands(MCInst &Inst, unsigned N) const { @@ -1396,7 +1458,7 @@ public: return; } assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 2)); + Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2)); } void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const { @@ -1410,7 +1472,7 @@ public: return; } assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 2)); + Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2)); } void addBranchTarget14Operands(MCInst &Inst, unsigned N) const { @@ -1424,64 +1486,58 @@ public: return; } assert(MCE && "Invalid constant immediate operand!"); - Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 2)); + Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2)); } void addFPImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getFPImm())); + Inst.addOperand(MCOperand::createImm(getFPImm())); } void addBarrierOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getBarrier())); + Inst.addOperand(MCOperand::createImm(getBarrier())); } void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - bool Valid; - auto Mapper = AArch64SysReg::MRSMapper(getSysRegFeatureBits()); - uint32_t Bits = Mapper.fromString(getSysReg(), Valid); - - Inst.addOperand(MCOperand::CreateImm(Bits)); + Inst.addOperand(MCOperand::createImm(SysReg.MRSReg)); } void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - bool Valid; - auto Mapper = AArch64SysReg::MSRMapper(getSysRegFeatureBits()); - uint32_t Bits = Mapper.fromString(getSysReg(), Valid); - - Inst.addOperand(MCOperand::CreateImm(Bits)); + Inst.addOperand(MCOperand::createImm(SysReg.MSRReg)); } - void addSystemPStateFieldOperands(MCInst &Inst, unsigned N) const { + void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - bool Valid; - uint32_t Bits = - AArch64PState::PStateMapper().fromString(getSysReg(), Valid); + Inst.addOperand(MCOperand::createImm(SysReg.PStateField)); + } - Inst.addOperand(MCOperand::CreateImm(Bits)); + void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::createImm(SysReg.PStateField)); } void addSysCROperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getSysCR())); + Inst.addOperand(MCOperand::createImm(getSysCR())); } void addPrefetchOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getPrefetch())); + Inst.addOperand(MCOperand::createImm(getPrefetch())); } void addShifterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); unsigned Imm = AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount()); - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addExtendOperands(MCInst &Inst, unsigned N) const { @@ -1489,7 +1545,7 @@ public: AArch64_AM::ShiftExtendType ET = getShiftExtendType(); if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW; unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount()); - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addExtend64Operands(MCInst &Inst, unsigned N) const { @@ -1497,15 +1553,15 @@ public: AArch64_AM::ShiftExtendType ET = getShiftExtendType(); if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX; unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount()); - Inst.addOperand(MCOperand::CreateImm(Imm)); + Inst.addOperand(MCOperand::createImm(Imm)); } void addMemExtendOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); AArch64_AM::ShiftExtendType ET = getShiftExtendType(); bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX; - Inst.addOperand(MCOperand::CreateImm(IsSigned)); - Inst.addOperand(MCOperand::CreateImm(getShiftExtendAmount() != 0)); + Inst.addOperand(MCOperand::createImm(IsSigned)); + Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0)); } // For 8-bit load/store instructions with a register offset, both the @@ -1516,8 +1572,8 @@ public: assert(N == 2 && "Invalid number of operands!"); AArch64_AM::ShiftExtendType ET = getShiftExtendType(); bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX; - Inst.addOperand(MCOperand::CreateImm(IsSigned)); - Inst.addOperand(MCOperand::CreateImm(hasShiftExtendAmount())); + Inst.addOperand(MCOperand::createImm(IsSigned)); + Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount())); } template @@ -1526,7 +1582,7 @@ public: const MCConstantExpr *CE = cast(getImm()); uint64_t Value = CE->getValue(); - Inst.addOperand(MCOperand::CreateImm((Value >> Shift) & 0xffff)); + Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff)); } template @@ -1535,7 +1591,7 @@ public: const MCConstantExpr *CE = cast(getImm()); uint64_t Value = CE->getValue(); - Inst.addOperand(MCOperand::CreateImm((~Value >> Shift) & 0xffff)); + Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff)); } void print(raw_ostream &OS) const override; @@ -1622,21 +1678,30 @@ public: return Op; } - static std::unique_ptr CreateBarrier(unsigned Val, SMLoc S, + static std::unique_ptr CreateBarrier(unsigned Val, + StringRef Str, + SMLoc S, MCContext &Ctx) { auto Op = make_unique(k_Barrier, Ctx); Op->Barrier.Val = Val; + Op->Barrier.Data = Str.data(); + Op->Barrier.Length = Str.size(); Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr - CreateSysReg(StringRef Str, SMLoc S, uint64_t FeatureBits, MCContext &Ctx) { + static std::unique_ptr CreateSysReg(StringRef Str, SMLoc S, + uint32_t MRSReg, + uint32_t MSRReg, + uint32_t PStateField, + MCContext &Ctx) { auto Op = make_unique(k_SysReg, Ctx); Op->SysReg.Data = Str.data(); Op->SysReg.Length = Str.size(); - Op->SysReg.FeatureBits = FeatureBits; + Op->SysReg.MRSReg = MRSReg; + Op->SysReg.MSRReg = MSRReg; + Op->SysReg.PStateField = PStateField; Op->StartLoc = S; Op->EndLoc = S; return Op; @@ -1651,10 +1716,14 @@ public: return Op; } - static std::unique_ptr CreatePrefetch(unsigned Val, SMLoc S, + static std::unique_ptr CreatePrefetch(unsigned Val, + StringRef Str, + SMLoc S, MCContext &Ctx) { auto Op = make_unique(k_Prefetch, Ctx); Op->Prefetch.Val = Val; + Op->Barrier.Data = Str.data(); + Op->Barrier.Length = Str.size(); Op->StartLoc = S; Op->EndLoc = S; return Op; @@ -1682,21 +1751,20 @@ void AArch64Operand::print(raw_ostream &OS) const { << AArch64_AM::getFPImmFloat(getFPImm()) << ") >"; break; case k_Barrier: { - bool Valid; - StringRef Name = AArch64DB::DBarrierMapper().toString(getBarrier(), Valid); - if (Valid) + StringRef Name = getBarrierName(); + if (!Name.empty()) OS << ""; else OS << ""; break; } case k_Immediate: - getImm()->print(OS); + OS << *getImm(); break; case k_ShiftedImm: { unsigned Shift = getShiftedImmShift(); OS << "print(OS); + OS << *getShiftedImmVal(); OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">"; break; } @@ -1727,9 +1795,8 @@ void AArch64Operand::print(raw_ostream &OS) const { OS << "c" << getSysCR(); break; case k_Prefetch: { - bool Valid; - StringRef Name = AArch64PRFM::PRFMMapper().toString(getPrefetch(), Valid); - if (Valid) + StringRef Name = getPrefetchName(); + if (!Name.empty()) OS << ""; else OS << ""; @@ -1754,7 +1821,7 @@ static unsigned MatchRegisterName(StringRef Name); /// } static unsigned matchVectorRegName(StringRef Name) { - return StringSwitch(Name) + return StringSwitch(Name.lower()) .Case("v0", AArch64::Q0) .Case("v1", AArch64::Q1) .Case("v2", AArch64::Q2) @@ -1861,6 +1928,7 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name, /// Identifier when called, and if it is a register name the token is eaten and /// the register is added to the operand list. int AArch64AsmParser::tryParseRegister() { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); @@ -1885,6 +1953,7 @@ int AArch64AsmParser::tryParseRegister() { /// tryMatchVectorRegister - Try to parse a vector register name with optional /// kind specifier. If it is a register specifier, eat the token and return it. int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) { + MCAsmParser &Parser = getParser(); if (Parser.getTok().isNot(AsmToken::Identifier)) { TokError("vector register expected"); return -1; @@ -1917,6 +1986,7 @@ int AArch64AsmParser::tryMatchVectorRegister(StringRef &Kind, bool expected) { /// tryParseSysCROperand - Try to parse a system instruction CR operand name. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); if (Parser.getTok().isNot(AsmToken::Identifier)) { @@ -1946,6 +2016,7 @@ AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) { /// tryParsePrefetch - Try to parse a prefetch operand. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); const AsmToken &Tok = Parser.getTok(); // Either an identifier for named values or a 5-bit immediate. @@ -1968,7 +2039,12 @@ AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) { return MatchOperand_ParseFail; } - Operands.push_back(AArch64Operand::CreatePrefetch(prfop, S, getContext())); + bool Valid; + auto Mapper = AArch64PRFM::PRFMMapper(); + StringRef Name = + Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid); + Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Name, + S, getContext())); return MatchOperand_Success; } @@ -1978,14 +2054,17 @@ AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) { } bool Valid; - unsigned prfop = AArch64PRFM::PRFMMapper().fromString(Tok.getString(), Valid); + auto Mapper = AArch64PRFM::PRFMMapper(); + unsigned prfop = + Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid); if (!Valid) { TokError("pre-fetch hint expected"); return MatchOperand_ParseFail; } Parser.Lex(); // Eat identifier token. - Operands.push_back(AArch64Operand::CreatePrefetch(prfop, S, getContext())); + Operands.push_back(AArch64Operand::CreatePrefetch(prfop, Tok.getString(), + S, getContext())); return MatchOperand_Success; } @@ -1993,6 +2072,7 @@ AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) { /// instruction. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); const MCExpr *Expr; @@ -2012,7 +2092,7 @@ AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { // No modifier was specified at all; this is the syntax for an ELF basic // ADRP relocation (unfortunately). Expr = - AArch64MCExpr::Create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext()); + AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext()); } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) && Addend != 0) { @@ -2043,6 +2123,7 @@ AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { /// instruction. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); const MCExpr *Expr; @@ -2062,6 +2143,7 @@ AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) { /// tryParseFPImm - A floating point immediate expression operand. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseFPImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); bool Hash = false; @@ -2079,15 +2161,16 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) { const AsmToken &Tok = Parser.getTok(); if (Tok.is(AsmToken::Real)) { APFloat RealVal(APFloat::IEEEdouble, Tok.getString()); + if (isNegative) + RealVal.changeSign(); + uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); - // If we had a '-' in front, toggle the sign bit. - IntVal ^= (uint64_t)isNegative << 63; int Val = AArch64_AM::getFP64Imm(APInt(64, IntVal)); Parser.Lex(); // Eat the token. // Check for out of range values. As an exception, we let Zero through, // as we handle that special case in post-processing before matching in // order to use the zero register for it. - if (Val == -1 && !RealVal.isZero()) { + if (Val == -1 && !RealVal.isPosZero()) { TokError("expected compatible register or floating-point constant"); return MatchOperand_ParseFail; } @@ -2124,6 +2207,7 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) { /// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); if (Parser.getTok().is(AsmToken::Hash)) @@ -2141,7 +2225,7 @@ AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) { if (MCE) { int64_t Val = MCE->getValue(); if (Val > 0xfff && (Val & 0xfff) == 0) { - Imm = MCConstantExpr::Create(Val >> 12, getContext()); + Imm = MCConstantExpr::create(Val >> 12, getContext()); ShiftAmount = 12; } } @@ -2215,6 +2299,7 @@ AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) { /// parseCondCode - Parse a Condition Code operand. bool AArch64AsmParser::parseCondCode(OperandVector &Operands, bool invertCondCode) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); @@ -2240,6 +2325,7 @@ bool AArch64AsmParser::parseCondCode(OperandVector &Operands, /// them if present. AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); std::string LowerID = Tok.getString().lower(); AArch64_AM::ShiftExtendType ShOp = @@ -2285,10 +2371,11 @@ AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) { if (Hash) Parser.Lex(); // Eat the '#'. - // Make sure we do actually have a number - if (!Parser.getTok().is(AsmToken::Integer)) { - Error(Parser.getTok().getLoc(), - "expected integer shift amount"); + // Make sure we do actually have a number or a parenthesized expression. + SMLoc E = Parser.getTok().getLoc(); + if (!Parser.getTok().is(AsmToken::Integer) && + !Parser.getTok().is(AsmToken::LParen)) { + Error(E, "expected integer shift amount"); return MatchOperand_ParseFail; } @@ -2298,11 +2385,11 @@ AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) { const MCConstantExpr *MCE = dyn_cast(ImmVal); if (!MCE) { - TokError("expected #imm after shift specifier"); + Error(E, "expected constant '#imm' after shift specifier"); return MatchOperand_ParseFail; } - SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1); + E = SMLoc::getFromPointer(getLoc().getPointer() - 1); Operands.push_back(AArch64Operand::CreateShiftExtend( ShOp, MCE->getValue(), true, S, E, getContext())); return MatchOperand_Success; @@ -2319,6 +2406,7 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc, Operands.push_back( AArch64Operand::CreateToken("sys", false, NameLoc, getContext())); + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); StringRef Op = Tok.getString(); SMLoc S = Tok.getLoc(); @@ -2327,14 +2415,14 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc, #define SYS_ALIAS(op1, Cn, Cm, op2) \ do { \ - Expr = MCConstantExpr::Create(op1, getContext()); \ + Expr = MCConstantExpr::create(op1, getContext()); \ Operands.push_back( \ AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \ Operands.push_back( \ AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext())); \ Operands.push_back( \ AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext())); \ - Expr = MCConstantExpr::Create(op2, getContext()); \ + Expr = MCConstantExpr::create(op2, getContext()); \ Operands.push_back( \ AArch64Operand::CreateImm(Expr, S, getLoc(), getContext())); \ } while (0) @@ -2557,6 +2645,7 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc, AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); // Can be either a #imm style literal or an option name @@ -2578,8 +2667,12 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { Error(ExprLoc, "barrier operand out of range"); return MatchOperand_ParseFail; } - Operands.push_back( - AArch64Operand::CreateBarrier(MCE->getValue(), ExprLoc, getContext())); + bool Valid; + auto Mapper = AArch64DB::DBarrierMapper(); + StringRef Name = + Mapper.toString(MCE->getValue(), getSTI().getFeatureBits(), Valid); + Operands.push_back( AArch64Operand::CreateBarrier(MCE->getValue(), Name, + ExprLoc, getContext())); return MatchOperand_Success; } @@ -2589,7 +2682,9 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { } bool Valid; - unsigned Opt = AArch64DB::DBarrierMapper().fromString(Tok.getString(), Valid); + auto Mapper = AArch64DB::DBarrierMapper(); + unsigned Opt = + Mapper.fromString(Tok.getString(), getSTI().getFeatureBits(), Valid); if (!Valid) { TokError("invalid barrier option name"); return MatchOperand_ParseFail; @@ -2601,8 +2696,8 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { return MatchOperand_ParseFail; } - Operands.push_back( - AArch64Operand::CreateBarrier(Opt, getLoc(), getContext())); + Operands.push_back( AArch64Operand::CreateBarrier(Opt, Tok.getString(), + getLoc(), getContext())); Parser.Lex(); // Consume the option return MatchOperand_Success; @@ -2610,13 +2705,34 @@ AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) { AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseSysReg(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return MatchOperand_NoMatch; - Operands.push_back(AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), - STI.getFeatureBits(), getContext())); + bool IsKnown; + auto MRSMapper = AArch64SysReg::MRSMapper(); + uint32_t MRSReg = MRSMapper.fromString(Tok.getString(), + getSTI().getFeatureBits(), IsKnown); + assert(IsKnown == (MRSReg != -1U) && + "register should be -1 if and only if it's unknown"); + + auto MSRMapper = AArch64SysReg::MSRMapper(); + uint32_t MSRReg = MSRMapper.fromString(Tok.getString(), + getSTI().getFeatureBits(), IsKnown); + assert(IsKnown == (MSRReg != -1U) && + "register should be -1 if and only if it's unknown"); + + auto PStateMapper = AArch64PState::PStateMapper(); + uint32_t PStateField = + PStateMapper.fromString(Tok.getString(), + getSTI().getFeatureBits(), IsKnown); + assert(IsKnown == (PStateField != -1U) && + "register should be -1 if and only if it's unknown"); + + Operands.push_back(AArch64Operand::CreateSysReg( + Tok.getString(), getLoc(), MRSReg, MSRReg, PStateField, getContext())); Parser.Lex(); // Eat identifier return MatchOperand_Success; @@ -2624,6 +2740,7 @@ AArch64AsmParser::tryParseSysReg(OperandVector &Operands) { /// tryParseVectorRegister - Parse a vector register operand. bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); if (Parser.getTok().isNot(AsmToken::Identifier)) return true; @@ -2672,6 +2789,7 @@ bool AArch64AsmParser::tryParseVectorRegister(OperandVector &Operands) { /// parseRegister - Parse a non-vector register operand. bool AArch64AsmParser::parseRegister(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); SMLoc S = getLoc(); // Try for a vector register. if (!tryParseVectorRegister(Operands)) @@ -2714,6 +2832,7 @@ bool AArch64AsmParser::parseRegister(OperandVector &Operands) { } bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { + MCAsmParser &Parser = getParser(); bool HasELFModifier = false; AArch64MCExpr::VariantKind RefKind; @@ -2785,13 +2904,14 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { return true; if (HasELFModifier) - ImmVal = AArch64MCExpr::Create(ImmVal, RefKind, getContext()); + ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext()); return false; } /// parseVectorList - Parse a vector list operand for AdvSIMD instructions. bool AArch64AsmParser::parseVectorList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not a Left Bracket"); SMLoc S = getLoc(); Parser.Lex(); // Eat left bracket token. @@ -2890,6 +3010,7 @@ bool AArch64AsmParser::parseVectorList(OperandVector &Operands) { AArch64AsmParser::OperandMatchResultTy AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (!Tok.is(AsmToken::Identifier)) return MatchOperand_NoMatch; @@ -2935,6 +3056,7 @@ AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) { /// operand regardless of the mnemonic. bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, bool invertCondCode) { + MCAsmParser &Parser = getParser(); // Check if the current operand has a custom associated parser, if so, try to // custom parse the operand, or fallback to the general approach. OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); @@ -3054,13 +3176,18 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, if (getParser().parseExpression(SubExprVal)) return true; + if (Operands.size() < 2 || + !static_cast(*Operands[1]).isReg()) + return Error(Loc, "Only valid when first operand is register"); + + bool IsXReg = + AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains( + Operands[1]->getReg()); + MCContext& Ctx = getContext(); E = SMLoc::getFromPointer(Loc.getPointer() - 1); // If the op is an imm and can be fit into a mov, then replace ldr with mov. - if (isa(SubExprVal) && Operands.size() >= 2 && - static_cast(*Operands[1]).isReg()) { - bool IsXReg = AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains( - Operands[1]->getReg()); + if (isa(SubExprVal)) { uint64_t Imm = (cast(SubExprVal))->getValue(); uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16; while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) { @@ -3070,15 +3197,20 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) { Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx); Operands.push_back(AArch64Operand::CreateImm( - MCConstantExpr::Create(Imm, Ctx), S, E, Ctx)); + MCConstantExpr::create(Imm, Ctx), S, E, Ctx)); if (ShiftAmt) Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL, ShiftAmt, true, S, E, Ctx)); return false; } + APInt Simm = APInt(64, Imm << ShiftAmt); + // check if the immediate is an unsigned or signed 32-bit int for W regs + if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32))) + return Error(Loc, "Immediate too large for register"); } // If it is a label or an imm that cannot fit in a movz, put it into CP. - const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal); + const MCExpr *CPLoc = + getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc); Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx)); return false; } @@ -3090,6 +3222,7 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode, bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { + MCAsmParser &Parser = getParser(); Name = StringSwitch(Name.lower()) .Case("beq", "b.eq") .Case("bne", "b.ne") @@ -3495,6 +3628,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) { return Error(Loc, "index must be a multiple of 8 in range [0, 32760]."); case Match_InvalidMemoryIndexed16: return Error(Loc, "index must be a multiple of 16 in range [0, 65520]."); + case Match_InvalidImm0_1: + return Error(Loc, "immediate must be an integer in range [0, 1]."); case Match_InvalidImm0_7: return Error(Loc, "immediate must be an integer in range [0, 7]."); case Match_InvalidImm0_15: @@ -3538,12 +3673,12 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) { } } -static const char *getSubtargetFeatureName(unsigned Val); +static const char *getSubtargetFeatureName(uint64_t Val); bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) { assert(!Operands.empty() && "Unexpect empty operand list!"); AArch64Operand &Op = static_cast(*Operands[0]); @@ -3570,8 +3705,8 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, NewOp4Val = 63 - Op3Val; } - const MCExpr *NewOp3 = MCConstantExpr::Create(NewOp3Val, getContext()); - const MCExpr *NewOp4 = MCConstantExpr::Create(NewOp4Val, getContext()); + const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext()); + const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext()); Operands[0] = AArch64Operand::CreateToken( "ubfm", false, Op.getStartLoc(), getContext()); @@ -3581,6 +3716,60 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Op3.getEndLoc(), getContext()); } } + } else if (NumOperands == 4 && Tok == "bfc") { + // FIXME: Horrible hack to handle BFC->BFM alias. + AArch64Operand &Op1 = static_cast(*Operands[1]); + AArch64Operand LSBOp = static_cast(*Operands[2]); + AArch64Operand WidthOp = static_cast(*Operands[3]); + + if (Op1.isReg() && LSBOp.isImm() && WidthOp.isImm()) { + const MCConstantExpr *LSBCE = dyn_cast(LSBOp.getImm()); + const MCConstantExpr *WidthCE = dyn_cast(WidthOp.getImm()); + + if (LSBCE && WidthCE) { + uint64_t LSB = LSBCE->getValue(); + uint64_t Width = WidthCE->getValue(); + + uint64_t RegWidth = 0; + if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains( + Op1.getReg())) + RegWidth = 64; + else + RegWidth = 32; + + if (LSB >= RegWidth) + return Error(LSBOp.getStartLoc(), + "expected integer in range [0, 31]"); + if (Width < 1 || Width > RegWidth) + return Error(WidthOp.getStartLoc(), + "expected integer in range [1, 32]"); + + uint64_t ImmR = 0; + if (RegWidth == 32) + ImmR = (32 - LSB) & 0x1f; + else + ImmR = (64 - LSB) & 0x3f; + + uint64_t ImmS = Width - 1; + + if (ImmR != 0 && ImmS >= ImmR) + return Error(WidthOp.getStartLoc(), + "requested insert overflows register"); + + const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext()); + const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext()); + Operands[0] = AArch64Operand::CreateToken( + "bfm", false, Op.getStartLoc(), getContext()); + Operands[2] = AArch64Operand::CreateReg( + RegWidth == 32 ? AArch64::WZR : AArch64::XZR, false, SMLoc(), + SMLoc(), getContext()); + Operands[3] = AArch64Operand::CreateImm( + ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext()); + Operands.emplace_back( + AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(), + WidthOp.getEndLoc(), getContext())); + } + } } else if (NumOperands == 5) { // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and // UBFIZ -> UBFM aliases. @@ -3612,8 +3801,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, "expected integer in range [1, 32]"); uint64_t NewOp3Val = 0; - if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains( - Op1.getReg())) + if (RegWidth == 32) NewOp3Val = (32 - Op3Val) & 0x1f; else NewOp3Val = (64 - Op3Val) & 0x3f; @@ -3625,9 +3813,9 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, "requested insert overflows register"); const MCExpr *NewOp3 = - MCConstantExpr::Create(NewOp3Val, getContext()); + MCConstantExpr::create(NewOp3Val, getContext()); const MCExpr *NewOp4 = - MCConstantExpr::Create(NewOp4Val, getContext()); + MCConstantExpr::create(NewOp4Val, getContext()); Operands[3] = AArch64Operand::CreateImm( NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext()); Operands[4] = AArch64Operand::CreateImm( @@ -3683,7 +3871,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, "requested extract overflows register"); const MCExpr *NewOp4 = - MCConstantExpr::Create(NewOp4Val, getContext()); + MCConstantExpr::create(NewOp4Val, getContext()); Operands[4] = AArch64Operand::CreateImm( NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext()); if (Tok == "bfxil") @@ -3770,10 +3958,27 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // If that fails, try against the alternate table containing long-form NEON: // "fadd v0.2s, v1.2s, v2.2s" - if (MatchResult != Match_Success) + if (MatchResult != Match_Success) { + // But first, save the short-form match result: we can use it in case the + // long-form match also fails. + auto ShortFormNEONErrorInfo = ErrorInfo; + auto ShortFormNEONMatchResult = MatchResult; + MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0); + // Now, both matches failed, and the long-form match failed on the mnemonic + // suffix token operand. The short-form match failure is probably more + // relevant: use it instead. + if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 && + Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() && + ((AArch64Operand &)*Operands[1]).isTokenSuffix()) { + MatchResult = ShortFormNEONMatchResult; + ErrorInfo = ShortFormNEONErrorInfo; + } + } + + switch (MatchResult) { case Match_Success: { // Perform range checking and other semantic validations @@ -3785,7 +3990,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return true; Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst, STI); + Out.EmitInstruction(Inst, getSTI()); return false; } case Match_MissingFeature: { @@ -3793,7 +3998,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // Special case the error message for the very common case where only // a single subtarget feature is missing (neon, e.g.). std::string Msg = "instruction requires:"; - unsigned Mask = 1; + uint64_t Mask = 1; for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { if (ErrorInfo & Mask) { Msg += " "; @@ -3807,7 +4012,8 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return showMatchError(IDLoc, MatchResult); case Match_InvalidOperand: { SMLoc ErrorLoc = IDLoc; - if (ErrorInfo != ~0U) { + + if (ErrorInfo != ~0ULL) { if (ErrorInfo >= Operands.size()) return Error(IDLoc, "too few operands for instruction"); @@ -3852,6 +4058,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_InvalidMemoryIndexed8SImm7: case Match_InvalidMemoryIndexed16SImm7: case Match_InvalidMemoryIndexedSImm9: + case Match_InvalidImm0_1: case Match_InvalidImm0_7: case Match_InvalidImm0_15: case Match_InvalidImm0_31: @@ -3882,11 +4089,15 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, } llvm_unreachable("Implement any new match types added!"); - return true; } /// ParseDirective parses the arm specific directives bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) { + const MCObjectFileInfo::Environment Format = + getContext().getObjectFileInfo()->getObjectFileType(); + bool IsMachO = Format == MCObjectFileInfo::IsMachO; + bool IsCOFF = Format == MCObjectFileInfo::IsCOFF; + StringRef IDVal = DirectiveID.getIdentifier(); SMLoc Loc = DirectiveID.getLoc(); if (IDVal == ".hword") @@ -3900,7 +4111,12 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".ltorg" || IDVal == ".pool") return parseDirectiveLtorg(Loc); if (IDVal == ".unreq") - return parseDirectiveUnreq(DirectiveID.getLoc()); + return parseDirectiveUnreq(Loc); + + if (!IsMachO && !IsCOFF) { + if (IDVal == ".inst") + return parseDirectiveInst(Loc); + } return parseDirectiveLOH(IDVal, Loc); } @@ -3908,13 +4124,14 @@ bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) { /// parseDirectiveWord /// ::= .word [ expression (, expression)* ] bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { + MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { const MCExpr *Value; if (getParser().parseExpression(Value)) return true; - getParser().getStreamer().EmitValue(Value, Size); + getParser().getStreamer().EmitValue(Value, Size, L); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -3930,6 +4147,47 @@ bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { return false; } +/// parseDirectiveInst +/// ::= .inst opcode [, ...] +bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) { + MCAsmParser &Parser = getParser(); + if (getLexer().is(AsmToken::EndOfStatement)) { + Parser.eatToEndOfStatement(); + Error(Loc, "expected expression following directive"); + return false; + } + + for (;;) { + const MCExpr *Expr; + + if (getParser().parseExpression(Expr)) { + Error(Loc, "expected expression"); + return false; + } + + const MCConstantExpr *Value = dyn_cast_or_null(Expr); + if (!Value) { + Error(Loc, "expected constant expression"); + return false; + } + + getTargetStreamer().emitInst(Value->getValue()); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) { + Error(Loc, "unexpected token in directive"); + return false; + } + + Parser.Lex(); // Eat comma. + } + + Parser.Lex(); + return false; +} + // parseDirectiveTLSDescCall: // ::= .tlsdesccall symbol bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) { @@ -3937,15 +4195,15 @@ bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) { if (getParser().parseIdentifier(Name)) return Error(L, "expected symbol after directive"); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, getContext()); - Expr = AArch64MCExpr::Create(Expr, AArch64MCExpr::VK_TLSDESC, getContext()); + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext()); + Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext()); MCInst Inst; Inst.setOpcode(AArch64::TLSDESCCALL); - Inst.addOperand(MCOperand::CreateExpr(Expr)); + Inst.addOperand(MCOperand::createExpr(Expr)); - getParser().getStreamer().EmitInstruction(Inst, STI); + getParser().getStreamer().EmitInstruction(Inst, getSTI()); return false; } @@ -3961,10 +4219,9 @@ bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) { // We successfully get a numeric value for the identifier. // Check if it is valid. int64_t Id = getParser().getTok().getIntVal(); - Kind = (MCLOHType)Id; - // Check that Id does not overflow MCLOHType. - if (!isValidMCLOHType(Kind) || Id != Kind) + if (Id <= -1U && !isValidMCLOHType(Id)) return TokError("invalid numeric identifier in directive"); + Kind = (MCLOHType)Id; } else { StringRef Name = getTok().getIdentifier(); // We successfully parse an identifier. @@ -3987,7 +4244,7 @@ bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) { StringRef Name; if (getParser().parseIdentifier(Name)) return TokError("expected identifier in directive"); - Args.push_back(getContext().GetOrCreateSymbol(Name)); + Args.push_back(getContext().getOrCreateSymbol(Name)); if (Idx + 1 == NbArgs) break; @@ -4012,6 +4269,7 @@ bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) { /// parseDirectiveReq /// ::= name .req registername bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { + MCAsmParser &Parser = getParser(); Parser.Lex(); // Eat the '.req' token. SMLoc SRegLoc = getLoc(); unsigned RegNum = tryParseRegister(); @@ -4043,7 +4301,7 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { Parser.Lex(); // Consume the EndOfStatement auto pair = std::make_pair(IsVector, RegNum); - if (RegisterReqs.GetOrCreateValue(Name, pair).getValue() != pair) + if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair) Warning(L, "ignoring redefinition of register alias '" + Name + "'"); return true; @@ -4052,6 +4310,7 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { /// parseDirectiveUneq /// ::= .unreq registername bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) { + MCAsmParser &Parser = getParser(); if (Parser.getTok().isNot(AsmToken::Identifier)) { Error(Parser.getTok().getLoc(), "unexpected input in .unreq directive."); Parser.eatToEndOfStatement(); @@ -4116,9 +4375,7 @@ AArch64AsmParser::classifySymbolRef(const MCExpr *Expr, extern "C" void LLVMInitializeAArch64AsmParser() { RegisterMCAsmParser X(TheAArch64leTarget); RegisterMCAsmParser Y(TheAArch64beTarget); - - RegisterMCAsmParser Z(TheARM64leTarget); - RegisterMCAsmParser W(TheARM64beTarget); + RegisterMCAsmParser Z(TheARM64Target); } #define GET_REGISTER_MATCHER @@ -4187,3 +4444,77 @@ unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, return Match_Success; return Match_InvalidOperand; } + + +AArch64AsmParser::OperandMatchResultTy +AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) { + + SMLoc S = getLoc(); + + if (getParser().getTok().isNot(AsmToken::Identifier)) { + Error(S, "expected register"); + return MatchOperand_ParseFail; + } + + int FirstReg = tryParseRegister(); + if (FirstReg == -1) { + return MatchOperand_ParseFail; + } + const MCRegisterClass &WRegClass = + AArch64MCRegisterClasses[AArch64::GPR32RegClassID]; + const MCRegisterClass &XRegClass = + AArch64MCRegisterClasses[AArch64::GPR64RegClassID]; + + bool isXReg = XRegClass.contains(FirstReg), + isWReg = WRegClass.contains(FirstReg); + if (!isXReg && !isWReg) { + Error(S, "expected first even register of a " + "consecutive same-size even/odd register pair"); + return MatchOperand_ParseFail; + } + + const MCRegisterInfo *RI = getContext().getRegisterInfo(); + unsigned FirstEncoding = RI->getEncodingValue(FirstReg); + + if (FirstEncoding & 0x1) { + Error(S, "expected first even register of a " + "consecutive same-size even/odd register pair"); + return MatchOperand_ParseFail; + } + + SMLoc M = getLoc(); + if (getParser().getTok().isNot(AsmToken::Comma)) { + Error(M, "expected comma"); + return MatchOperand_ParseFail; + } + // Eat the comma + getParser().Lex(); + + SMLoc E = getLoc(); + int SecondReg = tryParseRegister(); + if (SecondReg ==-1) { + return MatchOperand_ParseFail; + } + + if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 || + (isXReg && !XRegClass.contains(SecondReg)) || + (isWReg && !WRegClass.contains(SecondReg))) { + Error(E,"expected second odd register of a " + "consecutive same-size even/odd register pair"); + return MatchOperand_ParseFail; + } + + unsigned Pair = 0; + if(isXReg) { + Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64, + &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]); + } else { + Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32, + &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]); + } + + Operands.push_back(AArch64Operand::CreateReg(Pair, false, S, getLoc(), + getContext())); + + return MatchOperand_Success; +}