diff options
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 638 |
1 files changed, 416 insertions, 222 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 52577d75ddf5..e410fe0aeff2 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -32,7 +32,6 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" @@ -500,6 +499,7 @@ class ARMAsmParser : public MCTargetAsmParser { StringRef FullInst, bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode, bool &CanAcceptVPTPredicationCode); + bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc); void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, OperandVector &Operands); @@ -847,7 +847,7 @@ class ARMOperand : public MCParsedAsmOperand { unsigned BaseRegNum; // Offset is in OffsetReg or OffsetImm. If both are zero, no offset // was specified. - const MCConstantExpr *OffsetImm; // Offset immediate value + const MCExpr *OffsetImm; // Offset immediate value unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg unsigned ShiftImm; // shift for OffsetReg. @@ -1107,7 +1107,10 @@ public: else if (isGPRMem()) { if(!Memory.OffsetImm || Memory.OffsetRegNum) return false; if(Memory.BaseRegNum != ARM::PC) return false; - Val = Memory.OffsetImm->getValue(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + Val = CE->getValue(); + else + return false; } else return false; return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020); @@ -1496,9 +1499,12 @@ public: return false; // Immediate offset in range [-4095, 4095]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val > -4096 && Val < 4096) || - (Val == std::numeric_limits<int32_t>::min()); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val > -4096 && Val < 4096) || + (Val == std::numeric_limits<int32_t>::min()); + } + return false; } bool isAlignedMemory() const { @@ -1581,8 +1587,11 @@ public: if (Memory.OffsetRegNum) return true; // Immediate offset in range [-4095, 4095]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val > -4096 && Val < 4096; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val > -4096 && Val < 4096; + } + return false; } bool isAM2OffsetImm() const { @@ -1608,11 +1617,14 @@ public: if (Memory.OffsetRegNum) return true; // Immediate offset in range [-255, 255]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - // The #-0 offset is encoded as std::numeric_limits<int32_t>::min(), and we - // have to check for this too. - return (Val > -256 && Val < 256) || - Val == std::numeric_limits<int32_t>::min(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + // The #-0 offset is encoded as std::numeric_limits<int32_t>::min(), and + // we have to check for this too. + return (Val > -256 && Val < 256) || + Val == std::numeric_limits<int32_t>::min(); + } + return false; } bool isAM3Offset() const { @@ -1640,9 +1652,12 @@ public: if (Memory.OffsetRegNum) return false; // Immediate offset in range [-1020, 1020] and a multiple of 4. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || - Val == std::numeric_limits<int32_t>::min(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) || + Val == std::numeric_limits<int32_t>::min(); + } + return false; } bool isAddrMode5FP16() const { @@ -1656,9 +1671,12 @@ public: if (Memory.OffsetRegNum) return false; // Immediate offset in range [-510, 510] and a multiple of 2. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) || - Val == std::numeric_limits<int32_t>::min(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val >= -510 && Val <= 510 && ((Val & 1) == 0)) || + Val == std::numeric_limits<int32_t>::min(); + } + return false; } bool isMemTBB() const { @@ -1710,8 +1728,11 @@ public: return false; // Immediate offset, multiple of 4 in range [0, 124]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val <= 124 && (Val % 4) == 0; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val <= 124 && (Val % 4) == 0; + } + return false; } bool isMemThumbRIs2() const { @@ -1720,8 +1741,11 @@ public: return false; // Immediate offset, multiple of 4 in range [0, 62]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val <= 62 && (Val % 2) == 0; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val <= 62 && (Val % 2) == 0; + } + return false; } bool isMemThumbRIs1() const { @@ -1730,8 +1754,11 @@ public: return false; // Immediate offset in range [0, 31]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val <= 31; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val <= 31; + } + return false; } bool isMemThumbSPI() const { @@ -1740,8 +1767,11 @@ public: return false; // Immediate offset, multiple of 4 in range [0, 1020]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val <= 1020 && (Val % 4) == 0; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val <= 1020 && (Val % 4) == 0; + } + return false; } bool isMemImm8s4Offset() const { @@ -1754,11 +1784,15 @@ public: return false; // Immediate offset a multiple of 4 in range [-1020, 1020]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - // Special case, #-0 is std::numeric_limits<int32_t>::min(). - return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || - Val == std::numeric_limits<int32_t>::min(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + // Special case, #-0 is std::numeric_limits<int32_t>::min(). + return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || + Val == std::numeric_limits<int32_t>::min(); + } + return false; } + bool isMemImm7s4Offset() const { // If we have an immediate that's not a constant, treat it as a label // reference needing a fixup. If it is a constant, it's something else @@ -1771,17 +1805,24 @@ public: return false; // Immediate offset a multiple of 4 in range [-508, 508]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - // Special case, #-0 is INT32_MIN. - return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + // Special case, #-0 is INT32_MIN. + return (Val >= -508 && Val <= 508 && (Val & 3) == 0) || Val == INT32_MIN; + } + return false; } + bool isMemImm0_1020s4Offset() const { if (!isGPRMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset a multiple of 4 in range [0, 1020]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val <= 1020 && (Val & 3) == 0; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val <= 1020 && (Val & 3) == 0; + } + return false; } bool isMemImm8Offset() const { @@ -1791,9 +1832,12 @@ public: if (Memory.BaseRegNum == ARM::PC) return false; // Immediate offset in range [-255, 255]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val == std::numeric_limits<int32_t>::min()) || - (Val > -256 && Val < 256); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val == std::numeric_limits<int32_t>::min()) || + (Val > -256 && Val < 256); + } + return false; } template<unsigned Bits, unsigned RegClassID> @@ -1806,22 +1850,25 @@ public: // [-127, 127], shifted left by Bits. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); - // INT32_MIN is a special-case value (indicating the encoding with - // zero offset and the subtract bit set) - if (Val == INT32_MIN) - return true; + // INT32_MIN is a special-case value (indicating the encoding with + // zero offset and the subtract bit set) + if (Val == INT32_MIN) + return true; - unsigned Divisor = 1U << Bits; + unsigned Divisor = 1U << Bits; - // Check that the low bits are zero - if (Val % Divisor != 0) - return false; + // Check that the low bits are zero + if (Val % Divisor != 0) + return false; - // Check that the remaining offset is within range. - Val /= Divisor; - return (Val >= -127 && Val <= 127); + // Check that the remaining offset is within range. + Val /= Divisor; + return (Val >= -127 && Val <= 127); + } + return false; } template <int shift> bool isMemRegRQOffset() const { @@ -1853,20 +1900,24 @@ public: Memory.BaseRegNum)) return false; - if(!Memory.OffsetImm) return true; + if (!Memory.OffsetImm) + return true; static_assert(shift < 56, "Such that we dont shift by a value higher than 62"); - int64_t Val = Memory.OffsetImm->getValue(); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); - // The value must be a multiple of (1 << shift) - if ((Val & ((1U << shift) - 1)) != 0) - return false; + // The value must be a multiple of (1 << shift) + if ((Val & ((1U << shift) - 1)) != 0) + return false; - // And be in the right range, depending on the amount that it is shifted - // by. Shift 0, is equal to 7 unsigned bits, the sign bit is set - // separately. - int64_t Range = (1U << (7+shift)) - 1; - return (Val == INT32_MIN) || (Val > -Range && Val < Range); + // And be in the right range, depending on the amount that it is shifted + // by. Shift 0, is equal to 7 unsigned bits, the sign bit is set + // separately. + int64_t Range = (1U << (7 + shift)) - 1; + return (Val == INT32_MIN) || (Val > -Range && Val < Range); + } + return false; } bool isMemPosImm8Offset() const { @@ -1874,8 +1925,11 @@ public: return false; // Immediate offset in range [0, 255]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return Val >= 0 && Val < 256; + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return Val >= 0 && Val < 256; + } + return false; } bool isMemNegImm8Offset() const { @@ -1885,9 +1939,12 @@ public: if (Memory.BaseRegNum == ARM::PC) return false; // Immediate offset in range [-255, -1]. if (!Memory.OffsetImm) return false; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val == std::numeric_limits<int32_t>::min()) || - (Val > -256 && Val < 0); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val == std::numeric_limits<int32_t>::min()) || + (Val > -256 && Val < 0); + } + return false; } bool isMemUImm12Offset() const { @@ -1895,8 +1952,11 @@ public: return false; // Immediate offset in range [0, 4095]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val >= 0 && Val < 4096); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val >= 0 && Val < 4096); + } + return false; } bool isMemImm12Offset() const { @@ -1911,9 +1971,14 @@ public: return false; // Immediate offset in range [-4095, 4095]. if (!Memory.OffsetImm) return true; - int64_t Val = Memory.OffsetImm->getValue(); - return (Val > -4096 && Val < 4096) || - (Val == std::numeric_limits<int32_t>::min()); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int64_t Val = CE->getValue(); + return (Val > -4096 && Val < 4096) || + (Val == std::numeric_limits<int32_t>::min()); + } + // If we have an immediate that's not a constant, treat it as a + // symbolic expression needing a fixup. + return true; } bool isConstPoolAsmImm() const { @@ -2760,7 +2825,10 @@ public: assert(isGPRMem() && "Unknown value type!"); assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!"); - Inst.addOperand(MCOperand::createImm(Memory.OffsetImm->getValue())); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + Inst.addOperand(MCOperand::createImm(CE->getValue())); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { @@ -2800,8 +2868,10 @@ public: void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - int32_t Imm = Memory.OffsetImm->getValue(); - Inst.addOperand(MCOperand::createImm(Imm)); + if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + Inst.addOperand(MCOperand::createImm(CE->getValue())); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addAdrLabelOperands(MCInst &Inst, unsigned N) const { @@ -2872,22 +2942,31 @@ public: void addAddrMode2Operands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); - int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); if (!Memory.OffsetRegNum) { - ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; - // Special case for #-0 - if (Val == std::numeric_limits<int32_t>::min()) Val = 0; - if (Val < 0) Val = -Val; - Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int32_t Val = CE->getValue(); + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == std::numeric_limits<int32_t>::min()) + Val = 0; + if (Val < 0) + Val = -Val; + Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); + Inst.addOperand(MCOperand::createImm(Val)); + } else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } else { // For register offset, we encode the shift type and negation flag // here. - Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, - Memory.ShiftImm, Memory.ShiftType); + int32_t Val = + ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, + Memory.ShiftImm, Memory.ShiftType); + Inst.addOperand(MCOperand::createImm(Val)); } - Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); } void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const { @@ -2916,21 +2995,30 @@ public: return; } - int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; + Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); if (!Memory.OffsetRegNum) { - ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; - // Special case for #-0 - if (Val == std::numeric_limits<int32_t>::min()) Val = 0; - if (Val < 0) Val = -Val; - Val = ARM_AM::getAM3Opc(AddSub, Val); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int32_t Val = CE->getValue(); + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == std::numeric_limits<int32_t>::min()) + Val = 0; + if (Val < 0) + Val = -Val; + Val = ARM_AM::getAM3Opc(AddSub, Val); + Inst.addOperand(MCOperand::createImm(Val)); + } else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } else { // For register offset, we encode the shift type and negation flag // here. - Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); + int32_t Val = + ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0); + Inst.addOperand(MCOperand::createImm(Val)); } - Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createReg(Memory.OffsetRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); } void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { @@ -2966,15 +3054,22 @@ public: return; } - // The lower two bits are always zero and as such are not encoded. - int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; - ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; - // Special case for #-0 - if (Val == std::numeric_limits<int32_t>::min()) Val = 0; - if (Val < 0) Val = -Val; - Val = ARM_AM::getAM5Opc(AddSub, Val); Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + // The lower two bits are always zero and as such are not encoded. + int32_t Val = CE->getValue() / 4; + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == std::numeric_limits<int32_t>::min()) + Val = 0; + if (Val < 0) + Val = -Val; + Val = ARM_AM::getAM5Opc(AddSub, Val); + Inst.addOperand(MCOperand::createImm(Val)); + } else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addAddrMode5FP16Operands(MCInst &Inst, unsigned N) const { @@ -2988,15 +3083,22 @@ public: return; } - // The lower bit is always zero and as such is not encoded. - int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 2 : 0; - ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; - // Special case for #-0 - if (Val == std::numeric_limits<int32_t>::min()) Val = 0; - if (Val < 0) Val = -Val; - Val = ARM_AM::getAM5FP16Opc(AddSub, Val); Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + // The lower bit is always zero and as such is not encoded. + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) { + int32_t Val = CE->getValue() / 2; + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == std::numeric_limits<int32_t>::min()) + Val = 0; + if (Val < 0) + Val = -Val; + Val = ARM_AM::getAM5FP16Opc(AddSub, Val); + Inst.addOperand(MCOperand::createImm(Val)); + } else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const { @@ -3010,9 +3112,8 @@ public: return; } - int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addMemImm7s4OffsetOperands(MCInst &Inst, unsigned N) const { @@ -3026,24 +3127,26 @@ public: return; } - int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - // The lower two bits are always zero and as such are not encoded. - int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + // The lower two bits are always zero and as such are not encoded. + Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addMemImmOffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addMemRegRQOffsetOperands(MCInst &Inst, unsigned N) const { @@ -3062,9 +3165,8 @@ public: } // Otherwise, it's a normal memory reg+offset. - int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { @@ -3077,9 +3179,8 @@ public: } // Otherwise, it's a normal memory reg+offset. - int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const { @@ -3126,30 +3227,43 @@ public: void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + // The lower two bits are always zero and as such are not encoded. + Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + Inst.addOperand(MCOperand::createImm(CE->getValue() / 2)); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + addExpr(Inst, Memory.OffsetImm); } void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0; Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); - Inst.addOperand(MCOperand::createImm(Val)); + if (!Memory.OffsetImm) + Inst.addOperand(MCOperand::createImm(0)); + else if (const auto *CE = dyn_cast<MCConstantExpr>(Memory.OffsetImm)) + // The lower two bits are always zero and as such are not encoded. + Inst.addOperand(MCOperand::createImm(CE->getValue() / 4)); + else + Inst.addOperand(MCOperand::createExpr(Memory.OffsetImm)); } void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const { @@ -3686,10 +3800,9 @@ public: } static std::unique_ptr<ARMOperand> - CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm, - unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType, - unsigned ShiftImm, unsigned Alignment, bool isNegative, SMLoc S, - SMLoc E, SMLoc AlignmentLoc = SMLoc()) { + CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum, + ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment, + bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) { auto Op = std::make_unique<ARMOperand>(k_Memory); Op->Memory.BaseRegNum = BaseRegNum; Op->Memory.OffsetImm = OffsetImm; @@ -4899,7 +5012,7 @@ ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) { if (Tok.isNot(AsmToken::Identifier)) return MatchOperand_NoMatch; - if (!Tok.getString().equals_lower("csync")) + if (!Tok.getString().equals_insensitive("csync")) return MatchOperand_NoMatch; Parser.Lex(); // Eat identifier token. @@ -4919,7 +5032,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { if (Tok.is(AsmToken::Identifier)) { StringRef OptStr = Tok.getString(); - if (OptStr.equals_lower("sy")) + if (OptStr.equals_insensitive("sy")) Opt = ARM_ISB::SY; else return MatchOperand_NoMatch; @@ -5818,23 +5931,24 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { E = Parser.getTok().getLoc(); bool isNegative = getParser().getTok().is(AsmToken::Minus); - const MCExpr *Offset; + const MCExpr *Offset, *AdjustedOffset; if (getParser().parseExpression(Offset)) return true; - // The expression has to be a constant. Memory references with relocations - // don't come through here, as they use the <label> forms of the relevant - // instructions. - const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset); - if (!CE) - return Error (E, "constant expression expected"); - - // If the constant was #-0, represent it as - // std::numeric_limits<int32_t>::min(). - int32_t Val = CE->getValue(); - if (isNegative && Val == 0) - CE = MCConstantExpr::create(std::numeric_limits<int32_t>::min(), - getContext()); + if (const auto *CE = dyn_cast<MCConstantExpr>(Offset)) { + // If the constant was #-0, represent it as + // std::numeric_limits<int32_t>::min(). + int32_t Val = CE->getValue(); + if (isNegative && Val == 0) + CE = MCConstantExpr::create(std::numeric_limits<int32_t>::min(), + getContext()); + // Don't worry about range checking the value here. That's handled by + // the is*() predicates. + AdjustedOffset = CE; + } else + AdjustedOffset = Offset; + Operands.push_back(ARMOperand::CreateMem( + BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E)); // Now we should have the closing ']' if (Parser.getTok().isNot(AsmToken::RBrac)) @@ -5842,12 +5956,6 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { E = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat right bracket token. - // Don't worry about range checking the value here. That's handled by - // the is*() predicates. - Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0, - ARM_AM::no_shift, 0, 0, - false, S, E)); - // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { @@ -6086,7 +6194,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return true; // If this is VMRS, check for the apsr_nzcv operand. if (Mnemonic == "vmrs" && - Parser.getTok().getString().equals_lower("apsr_nzcv")) { + Parser.getTok().getString().equals_insensitive("apsr_nzcv")) { S = Parser.getTok().getLoc(); Parser.Lex(); Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); @@ -6222,10 +6330,10 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { } enum { - COFF = (1 << MCObjectFileInfo::IsCOFF), - ELF = (1 << MCObjectFileInfo::IsELF), - MACHO = (1 << MCObjectFileInfo::IsMachO), - WASM = (1 << MCObjectFileInfo::IsWasm), + COFF = (1 << MCContext::IsCOFF), + ELF = (1 << MCContext::IsELF), + MACHO = (1 << MCContext::IsMachO), + WASM = (1 << MCContext::IsWasm), }; static const struct PrefixEntry { const char *Spelling; @@ -6248,20 +6356,21 @@ bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) { } uint8_t CurrentFormat; - switch (getContext().getObjectFileInfo()->getObjectFileType()) { - case MCObjectFileInfo::IsMachO: + switch (getContext().getObjectFileType()) { + case MCContext::IsMachO: CurrentFormat = MACHO; break; - case MCObjectFileInfo::IsELF: + case MCContext::IsELF: CurrentFormat = ELF; break; - case MCObjectFileInfo::IsCOFF: + case MCContext::IsCOFF: CurrentFormat = COFF; break; - case MCObjectFileInfo::IsWasm: + case MCContext::IsWasm: CurrentFormat = WASM; break; - case MCObjectFileInfo::IsXCOFF: + case MCContext::IsGOFF: + case MCContext::IsXCOFF: llvm_unreachable("unexpected object format"); break; } @@ -7658,6 +7767,33 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, "source register and base register can't be identical"); return false; } + case ARM::t2LDR_PRE_imm: + case ARM::t2LDR_POST_imm: + case ARM::t2STR_PRE_imm: + case ARM::t2STR_POST_imm: { + // Rt must be different from Rn. + const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg()); + const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg()); + + if (Rt == Rn) + return Error(Operands[3]->getStartLoc(), + "destination register and base register can't be identical"); + if (Inst.getOpcode() == ARM::t2LDR_POST_imm || + Inst.getOpcode() == ARM::t2STR_POST_imm) { + int Imm = Inst.getOperand(2).getImm(); + if (Imm > 255 || Imm < -255) + return Error(Operands[5]->getStartLoc(), + "operand must be in range [-255, 255]"); + } + if (Inst.getOpcode() == ARM::t2STR_PRE_imm || + Inst.getOpcode() == ARM::t2STR_POST_imm) { + if (Inst.getOperand(0).getReg() == ARM::PC) { + return Error(Operands[3]->getStartLoc(), + "operand must be a register in range [r0, r14]"); + } + } + return false; + } case ARM::LDR_PRE_IMM: case ARM::LDR_PRE_REG: case ARM::t2LDR_PRE: @@ -7923,7 +8059,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; case ARM::t2B: { int op = (Operands[2]->isImm()) ? 2 : 3; - if (!static_cast<ARMOperand &>(*Operands[op]).isSignedOffset<24, 1>()) + ARMOperand &Operand = static_cast<ARMOperand &>(*Operands[op]); + // Delay the checks of symbolic expressions until they are resolved. + if (!isa<MCBinaryExpr>(Operand.getImm()) && + !Operand.isSignedOffset<24, 1>()) return Error(Operands[op]->getStartLoc(), "branch target out of range"); break; } @@ -8625,6 +8764,34 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, Inst = TmpInst; return true; } + // Aliases for imm syntax of LDR instructions. + case ARM::t2LDR_PRE_imm: + case ARM::t2LDR_POST_imm: { + MCInst TmpInst; + TmpInst.setOpcode(Inst.getOpcode() == ARM::t2LDR_PRE_imm ? ARM::t2LDR_PRE + : ARM::t2LDR_POST); + TmpInst.addOperand(Inst.getOperand(0)); // Rt + TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb + TmpInst.addOperand(Inst.getOperand(1)); // Rn + TmpInst.addOperand(Inst.getOperand(2)); // imm + TmpInst.addOperand(Inst.getOperand(3)); // CondCode + Inst = TmpInst; + return true; + } + // Aliases for imm syntax of STR instructions. + case ARM::t2STR_PRE_imm: + case ARM::t2STR_POST_imm: { + MCInst TmpInst; + TmpInst.setOpcode(Inst.getOpcode() == ARM::t2STR_PRE_imm ? ARM::t2STR_PRE + : ARM::t2STR_POST); + TmpInst.addOperand(Inst.getOperand(4)); // Rt_wb + TmpInst.addOperand(Inst.getOperand(0)); // Rt + TmpInst.addOperand(Inst.getOperand(1)); // Rn + TmpInst.addOperand(Inst.getOperand(2)); // imm + TmpInst.addOperand(Inst.getOperand(3)); // CondCode + Inst = TmpInst; + return true; + } // Aliases for alternate PC+imm syntax of LDR instructions. case ARM::t2LDRpcrel: // Select the narrow version if the immediate will fit. @@ -10835,10 +11002,9 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, /// parseDirective parses the arm specific directives bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { - const MCObjectFileInfo::Environment Format = - getContext().getObjectFileInfo()->getObjectFileType(); - bool IsMachO = Format == MCObjectFileInfo::IsMachO; - bool IsCOFF = Format == MCObjectFileInfo::IsCOFF; + const MCContext::Environment Format = getContext().getObjectFileType(); + bool IsMachO = Format == MCContext::IsMachO; + bool IsCOFF = Format == MCContext::IsCOFF; std::string IDVal = DirectiveID.getIdentifier().lower(); if (IDVal == ".word") @@ -10976,8 +11142,8 @@ void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { /// ::= .thumbfunc symbol_name bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { MCAsmParser &Parser = getParser(); - const auto Format = getContext().getObjectFileInfo()->getObjectFileType(); - bool IsMachO = Format == MCObjectFileInfo::IsMachO; + const auto Format = getContext().getObjectFileType(); + bool IsMachO = Format == MCContext::IsMachO; // Darwin asm has (optionally) function name after .thumb_func direction // ELF doesn't @@ -11000,6 +11166,12 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { "unexpected token in '.thumb_func' directive")) return true; + // .thumb_func implies .thumb + if (!isThumb()) + SwitchMode(); + + getParser().getStreamer().emitAssemblerFlag(MCAF_Code16); + NextSymbolIsThumb = true; return false; } @@ -11154,8 +11326,8 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { TagLoc = Parser.getTok().getLoc(); if (Parser.getTok().is(AsmToken::Identifier)) { StringRef Name = Parser.getTok().getIdentifier(); - Optional<unsigned> Ret = - ELFAttrs::attrTypeFromString(Name, ARMBuildAttrs::ARMAttributeTags); + Optional<unsigned> Ret = ELFAttrs::attrTypeFromString( + Name, ARMBuildAttrs::getARMAttributeTags()); if (!Ret.hasValue()) { Error(TagLoc, "attribute name not recognised: " + Name); return false; @@ -12060,9 +12232,7 @@ void ARMAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, } } -/// parseDirectiveArchExtension -/// ::= .arch_extension [no]feature -bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { +bool ARMAsmParser::enableArchExtFeature(StringRef Name, SMLoc &ExtLoc) { // FIXME: This structure should be moved inside ARMTargetParser // when we start to table-generate them, and we can use the ARM // flags below, that were generated by table-gen. @@ -12071,48 +12241,45 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { const FeatureBitset ArchCheck; const FeatureBitset Features; } Extensions[] = { - { ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC} }, - { ARM::AEK_CRYPTO, {Feature_HasV8Bit}, - {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, - { ARM::AEK_FP, {Feature_HasV8Bit}, - {ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8} }, - { (ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), - {Feature_HasV7Bit, Feature_IsNotMClassBit}, - {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM} }, - { ARM::AEK_MP, {Feature_HasV7Bit, Feature_IsNotMClassBit}, - {ARM::FeatureMP} }, - { ARM::AEK_SIMD, {Feature_HasV8Bit}, - {ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8} }, - { ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone} }, - // FIXME: Only available in A-class, isel not predicated - { ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization} }, - { ARM::AEK_FP16, {Feature_HasV8_2aBit}, - {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} }, - { ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS} }, - { ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB} }, - // FIXME: Unsupported extensions. - { ARM::AEK_OS, {}, {} }, - { ARM::AEK_IWMMXT, {}, {} }, - { ARM::AEK_IWMMXT2, {}, {} }, - { ARM::AEK_MAVERICK, {}, {} }, - { ARM::AEK_XSCALE, {}, {} }, + {ARM::AEK_CRC, {Feature_HasV8Bit}, {ARM::FeatureCRC}}, + {ARM::AEK_AES, + {Feature_HasV8Bit}, + {ARM::FeatureAES, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, + {ARM::AEK_SHA2, + {Feature_HasV8Bit}, + {ARM::FeatureSHA2, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, + {ARM::AEK_CRYPTO, + {Feature_HasV8Bit}, + {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8}}, + {ARM::AEK_FP, + {Feature_HasV8Bit}, + {ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, + {(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM), + {Feature_HasV7Bit, Feature_IsNotMClassBit}, + {ARM::FeatureHWDivThumb, ARM::FeatureHWDivARM}}, + {ARM::AEK_MP, + {Feature_HasV7Bit, Feature_IsNotMClassBit}, + {ARM::FeatureMP}}, + {ARM::AEK_SIMD, + {Feature_HasV8Bit}, + {ARM::FeatureNEON, ARM::FeatureVFP2_SP, ARM::FeatureFPARMv8}}, + {ARM::AEK_SEC, {Feature_HasV6KBit}, {ARM::FeatureTrustZone}}, + // FIXME: Only available in A-class, isel not predicated + {ARM::AEK_VIRT, {Feature_HasV7Bit}, {ARM::FeatureVirtualization}}, + {ARM::AEK_FP16, + {Feature_HasV8_2aBit}, + {ARM::FeatureFPARMv8, ARM::FeatureFullFP16}}, + {ARM::AEK_RAS, {Feature_HasV8Bit}, {ARM::FeatureRAS}}, + {ARM::AEK_LOB, {Feature_HasV8_1MMainlineBit}, {ARM::FeatureLOB}}, + // FIXME: Unsupported extensions. + {ARM::AEK_OS, {}, {}}, + {ARM::AEK_IWMMXT, {}, {}}, + {ARM::AEK_IWMMXT2, {}, {}}, + {ARM::AEK_MAVERICK, {}, {}}, + {ARM::AEK_XSCALE, {}, {}}, }; - - MCAsmParser &Parser = getParser(); - - if (getLexer().isNot(AsmToken::Identifier)) - return Error(getLexer().getLoc(), "expected architecture extension name"); - - StringRef Name = Parser.getTok().getString(); - SMLoc ExtLoc = Parser.getTok().getLoc(); - Lex(); - - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.arch_extension' directive")) - return true; - bool EnableFeature = true; - if (Name.startswith_lower("no")) { + if (Name.startswith_insensitive("no")) { EnableFeature = false; Name = Name.substr(2); } @@ -12140,9 +12307,36 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { } FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits()); setAvailableFeatures(Features); - return false; + return true; + } + return false; +} + +/// parseDirectiveArchExtension +/// ::= .arch_extension [no]feature +bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { + + MCAsmParser &Parser = getParser(); + + if (getLexer().isNot(AsmToken::Identifier)) + return Error(getLexer().getLoc(), "expected architecture extension name"); + + StringRef Name = Parser.getTok().getString(); + SMLoc ExtLoc = Parser.getTok().getLoc(); + Lex(); + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.arch_extension' directive")) + return true; + + if (Name == "nocrypto") { + enableArchExtFeature("nosha2", ExtLoc); + enableArchExtFeature("noaes", ExtLoc); } + if (enableArchExtFeature(Name, ExtLoc)) + return false; + return Error(ExtLoc, "unknown architectural extension: " + Name); } |
