Index: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td @@ -184,7 +184,7 @@ // ARM special operands for disassembly only. // -def SetEndAsmOperand : ImmAsmOperand { +def SetEndAsmOperand : ImmAsmOperand<0,1> { let Name = "SetEndImm"; let ParserMethod = "parseSetEndImm"; } @@ -221,25 +221,25 @@ // 16 imm6<5:4> = '01', 16 - is encoded in imm6<3:0> // 32 imm6<5> = '1', 32 - is encoded in imm6<4:0> // 64 64 - is encoded in imm6<5:0> -def shr_imm8_asm_operand : ImmAsmOperand { let Name = "ShrImm8"; } +def shr_imm8_asm_operand : ImmAsmOperand<1,8> { let Name = "ShrImm8"; } def shr_imm8 : Operand, ImmLeaf 0 && Imm <= 8; }]> { let EncoderMethod = "getShiftRight8Imm"; let DecoderMethod = "DecodeShiftRight8Imm"; let ParserMatchClass = shr_imm8_asm_operand; } -def shr_imm16_asm_operand : ImmAsmOperand { let Name = "ShrImm16"; } +def shr_imm16_asm_operand : ImmAsmOperand<1,16> { let Name = "ShrImm16"; } def shr_imm16 : Operand, ImmLeaf 0 && Imm <= 16; }]> { let EncoderMethod = "getShiftRight16Imm"; let DecoderMethod = "DecodeShiftRight16Imm"; let ParserMatchClass = shr_imm16_asm_operand; } -def shr_imm32_asm_operand : ImmAsmOperand { let Name = "ShrImm32"; } +def shr_imm32_asm_operand : ImmAsmOperand<1,32> { let Name = "ShrImm32"; } def shr_imm32 : Operand, ImmLeaf 0 && Imm <= 32; }]> { let EncoderMethod = "getShiftRight32Imm"; let DecoderMethod = "DecodeShiftRight32Imm"; let ParserMatchClass = shr_imm32_asm_operand; } -def shr_imm64_asm_operand : ImmAsmOperand { let Name = "ShrImm64"; } +def shr_imm64_asm_operand : ImmAsmOperand<1,64> { let Name = "ShrImm64"; } def shr_imm64 : Operand, ImmLeaf 0 && Imm <= 64; }]> { let EncoderMethod = "getShiftRight64Imm"; let DecoderMethod = "DecodeShiftRight64Imm"; @@ -957,7 +957,7 @@ } // PKH instructions -def PKHLSLAsmOperand : ImmAsmOperand { +def PKHLSLAsmOperand : ImmAsmOperand<0,31> { let Name = "PKHLSLImm"; let ParserMethod = "parsePKHLSLImm"; } Index: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td @@ -441,7 +441,16 @@ // // Immediate operands with a shared generic asm render method. -class ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; } +class ImmAsmOperand : AsmOperandClass { + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; + let DiagnosticType = "ImmRange" # Low # "_" # High; +} + +class ImmAsmOperandMinusOne : AsmOperandClass { + let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; + let DiagnosticType = "ImmRange" # Low # "_" # High; +} // Operands that are part of a memory addressing mode. class MemOperand : Operand { let OperandType = "OPERAND_MEMORY"; } @@ -663,35 +672,45 @@ }]>; /// imm0_1 predicate - Immediate in the range [0,1]. -def Imm0_1AsmOperand: ImmAsmOperand { let Name = "Imm0_1"; } +def Imm0_1AsmOperand: ImmAsmOperand<0,1> { let Name = "Imm0_1"; } def imm0_1 : Operand { let ParserMatchClass = Imm0_1AsmOperand; } /// imm0_3 predicate - Immediate in the range [0,3]. -def Imm0_3AsmOperand: ImmAsmOperand { let Name = "Imm0_3"; } +def Imm0_3AsmOperand: ImmAsmOperand<0,3> { let Name = "Imm0_3"; } def imm0_3 : Operand { let ParserMatchClass = Imm0_3AsmOperand; } /// imm0_7 predicate - Immediate in the range [0,7]. -def Imm0_7AsmOperand: ImmAsmOperand { let Name = "Imm0_7"; } +def Imm0_7AsmOperand: ImmAsmOperand<0,7> { + let Name = "Imm0_7"; +} def imm0_7 : Operand, ImmLeaf= 0 && Imm < 8; }]> { let ParserMatchClass = Imm0_7AsmOperand; } +/// imm8_255 predicate - Immediate in the range [8,255]. +def Imm8_255AsmOperand: ImmAsmOperand<8,255> { let Name = "Imm8_255"; } +def imm8_255 : Operand, ImmLeaf= 8 && Imm < 256; +}]> { + let ParserMatchClass = Imm8_255AsmOperand; +} + /// imm8 predicate - Immediate is exactly 8. -def Imm8AsmOperand: ImmAsmOperand { let Name = "Imm8"; } +def Imm8AsmOperand: ImmAsmOperand<8,8> { let Name = "Imm8"; } def imm8 : Operand, ImmLeaf { let ParserMatchClass = Imm8AsmOperand; } /// imm16 predicate - Immediate is exactly 16. -def Imm16AsmOperand: ImmAsmOperand { let Name = "Imm16"; } +def Imm16AsmOperand: ImmAsmOperand<16,16> { let Name = "Imm16"; } def imm16 : Operand, ImmLeaf { let ParserMatchClass = Imm16AsmOperand; } /// imm32 predicate - Immediate is exactly 32. -def Imm32AsmOperand: ImmAsmOperand { let Name = "Imm32"; } +def Imm32AsmOperand: ImmAsmOperand<32,32> { let Name = "Imm32"; } def imm32 : Operand, ImmLeaf { let ParserMatchClass = Imm32AsmOperand; } @@ -699,25 +718,25 @@ def imm8_or_16 : ImmLeaf; /// imm1_7 predicate - Immediate in the range [1,7]. -def Imm1_7AsmOperand: ImmAsmOperand { let Name = "Imm1_7"; } +def Imm1_7AsmOperand: ImmAsmOperand<1,7> { let Name = "Imm1_7"; } def imm1_7 : Operand, ImmLeaf 0 && Imm < 8; }]> { let ParserMatchClass = Imm1_7AsmOperand; } /// imm1_15 predicate - Immediate in the range [1,15]. -def Imm1_15AsmOperand: ImmAsmOperand { let Name = "Imm1_15"; } +def Imm1_15AsmOperand: ImmAsmOperand<1,15> { let Name = "Imm1_15"; } def imm1_15 : Operand, ImmLeaf 0 && Imm < 16; }]> { let ParserMatchClass = Imm1_15AsmOperand; } /// imm1_31 predicate - Immediate in the range [1,31]. -def Imm1_31AsmOperand: ImmAsmOperand { let Name = "Imm1_31"; } +def Imm1_31AsmOperand: ImmAsmOperand<1,31> { let Name = "Imm1_31"; } def imm1_31 : Operand, ImmLeaf 0 && Imm < 32; }]> { let ParserMatchClass = Imm1_31AsmOperand; } /// imm0_15 predicate - Immediate in the range [0,15]. -def Imm0_15AsmOperand: ImmAsmOperand { +def Imm0_15AsmOperand: ImmAsmOperand<0,15> { let Name = "Imm0_15"; let DiagnosticType = "ImmRange0_15"; } @@ -728,7 +747,7 @@ } /// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. -def Imm0_31AsmOperand: ImmAsmOperand { let Name = "Imm0_31"; } +def Imm0_31AsmOperand: ImmAsmOperand<0,31> { let Name = "Imm0_31"; } def imm0_31 : Operand, ImmLeaf= 0 && Imm < 32; }]> { @@ -736,15 +755,15 @@ } /// imm0_32 predicate - True if the 32-bit immediate is in the range [0,32]. -def Imm0_32AsmOperand: ImmAsmOperand { let Name = "Imm0_32"; } +def Imm0_32AsmOperand: ImmAsmOperand<0,32> { let Name = "Imm0_32"; } def imm0_32 : Operand, ImmLeaf= 0 && Imm < 32; + return Imm >= 0 && Imm < 33; }]> { let ParserMatchClass = Imm0_32AsmOperand; } /// imm0_63 predicate - True if the 32-bit immediate is in the range [0,63]. -def Imm0_63AsmOperand: ImmAsmOperand { let Name = "Imm0_63"; } +def Imm0_63AsmOperand: ImmAsmOperand<0,63> { let Name = "Imm0_63"; } def imm0_63 : Operand, ImmLeaf= 0 && Imm < 64; }]> { @@ -752,7 +771,7 @@ } /// imm0_239 predicate - Immediate in the range [0,239]. -def Imm0_239AsmOperand : ImmAsmOperand { +def Imm0_239AsmOperand : ImmAsmOperand<0,239> { let Name = "Imm0_239"; let DiagnosticType = "ImmRange0_239"; } @@ -761,13 +780,13 @@ } /// imm0_255 predicate - Immediate in the range [0,255]. -def Imm0_255AsmOperand : ImmAsmOperand { let Name = "Imm0_255"; } +def Imm0_255AsmOperand : ImmAsmOperand<0,255> { let Name = "Imm0_255"; } def imm0_255 : Operand, ImmLeaf= 0 && Imm < 256; }]> { let ParserMatchClass = Imm0_255AsmOperand; } -/// imm0_65535 - An immediate is in the range [0.65535]. -def Imm0_65535AsmOperand: ImmAsmOperand { let Name = "Imm0_65535"; } +/// imm0_65535 - An immediate is in the range [0,65535]. +def Imm0_65535AsmOperand: ImmAsmOperand<0,65535> { let Name = "Imm0_65535"; } def imm0_65535 : Operand, ImmLeaf= 0 && Imm < 65536; }]> { @@ -785,19 +804,23 @@ // FIXME: This really needs a Thumb version separate from the ARM version. // While the range is the same, and can thus use the same match class, // the encoding is different so it should have a different encoder method. -def Imm0_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm0_65535Expr"; } +def Imm0_65535ExprAsmOperand: AsmOperandClass { + let Name = "Imm0_65535Expr"; + let RenderMethod = "addImmOperands"; +} + def imm0_65535_expr : Operand { let EncoderMethod = "getHiLo16ImmOpValue"; let ParserMatchClass = Imm0_65535ExprAsmOperand; } -def Imm256_65535ExprAsmOperand: ImmAsmOperand { let Name = "Imm256_65535Expr"; } +def Imm256_65535ExprAsmOperand: ImmAsmOperand<256,65535> { let Name = "Imm256_65535Expr"; } def imm256_65535_expr : Operand { let ParserMatchClass = Imm256_65535ExprAsmOperand; } /// imm24b - True if the 32-bit immediate is encodable in 24 bits. -def Imm24bitAsmOperand: ImmAsmOperand { let Name = "Imm24bit"; } +def Imm24bitAsmOperand: ImmAsmOperand<0,0xffffff> { let Name = "Imm24bit"; } def imm24b : Operand, ImmLeaf= 0 && Imm <= 0xffffff; }]> { @@ -826,7 +849,9 @@ return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, SDLoc(N), MVT::i32); }]>; -def Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; } +def Imm1_32AsmOperand: ImmAsmOperandMinusOne<1,32> { + let Name = "Imm1_32"; +} def imm1_32 : Operand, PatLeaf<(imm), [{ uint64_t Imm = N->getZExtValue(); return Imm > 0 && Imm <= 32; @@ -840,7 +865,7 @@ return CurDAG->getTargetConstant((int)N->getZExtValue() - 1, SDLoc(N), MVT::i32); }]>; -def Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; } +def Imm1_16AsmOperand: ImmAsmOperandMinusOne<1,16> { let Name = "Imm1_16"; } def imm1_16 : Operand, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }], imm1_16_XFORM> { let PrintMethod = "printImmPlusOneOperand"; Index: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td @@ -19,7 +19,7 @@ unsigned Imm = N->getZExtValue(); return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), SDLoc(N), MVT::i32); }]>; -def ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; } +def ThumbSRImmAsmOperand: ImmAsmOperand<1,32> { let Name = "ImmThumbSR"; } def imm_sr : Operand, PatLeaf<(imm), [{ uint64_t Imm = N->getZExtValue(); return Imm > 0 && Imm <= 32; @@ -53,9 +53,6 @@ return ~((uint32_t)N->getZExtValue()) < 256; }]>; -def imm8_255 : ImmLeaf= 8 && Imm < 256; -}]>; def imm8_255_neg : PatLeaf<(i32 imm), [{ unsigned Val = -N->getZExtValue(); return Val >= 8 && Val < 256; Index: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td @@ -76,7 +76,11 @@ // t2_so_imm - Match a 32-bit immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit // immediate splatted into multiple bytes of the word. -def t2_so_imm_asmoperand : ImmAsmOperand { let Name = "T2SOImm"; } +def t2_so_imm_asmoperand : AsmOperandClass { + let Name = "T2SOImm"; + let RenderMethod = "addImmOperands"; + +} def t2_so_imm : Operand, ImmLeaf { @@ -116,8 +120,8 @@ let ParserMatchClass = t2_so_imm_neg_asmoperand; } -/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. -def imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; } +/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0,4095]. +def imm0_4095_asmoperand: ImmAsmOperand<0,4095> { let Name = "Imm0_4095"; } def imm0_4095 : Operand, ImmLeaf= 0 && Imm < 4096; }]> { Index: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -915,40 +915,37 @@ int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); return Val != -1; } - bool isFBits16() const { + + template + bool isImmediate() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; int64_t Value = CE->getValue(); - return Value >= 0 && Value <= 16; + return Value >= N && Value <= M; } - bool isFBits32() const { + template + bool isImmediateS4() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); if (!CE) return false; int64_t Value = CE->getValue(); - return Value >= 1 && Value <= 32; + return ((Value & 3) == 0) && Value >= N && Value <= M; + } + bool isFBits16() const { + return isImmediate<0, 17>(); + } + bool isFBits32() const { + return isImmediate<1, 33>(); } bool isImm8s4() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020; + return isImmediateS4<-1020, 1020>(); } bool isImm0_1020s4() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return ((Value & 3) == 0) && Value >= 0 && Value <= 1020; + return isImmediateS4<0, 1020>(); } bool isImm0_508s4() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return ((Value & 3) == 0) && Value >= 0 && Value <= 508; + return isImmediateS4<0, 508>(); } bool isImm0_508s4Neg() const { if (!isImm()) return false; @@ -958,27 +955,6 @@ // explicitly exclude zero. we want that to use the normal 0_508 version. return ((Value & 3) == 0) && Value > 0 && Value <= 508; } - bool isImm0_239() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 240; - } - bool isImm0_255() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 256; - } - bool isImm0_4095() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 4096; - } bool isImm0_4095Neg() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); @@ -986,145 +962,17 @@ int64_t Value = -CE->getValue(); return Value > 0 && Value < 4096; } - bool isImm0_1() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 2; - } - bool isImm0_3() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 4; - } bool isImm0_7() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 8; - } - bool isImm0_15() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 16; - } - bool isImm0_31() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 32; - } - bool isImm0_63() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 64; - } - bool isImm8() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value == 8; - } - bool isImm16() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value == 16; - } - bool isImm32() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value == 32; - } - bool isShrImm8() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value <= 8; - } - bool isShrImm16() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value <= 16; - } - bool isShrImm32() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value <= 32; - } - bool isShrImm64() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value <= 64; - } - bool isImm1_7() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 8; - } - bool isImm1_15() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 16; - } - bool isImm1_31() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 32; + return isImmediate<0, 7>(); } bool isImm1_16() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 17; + return isImmediate<1, 16>(); } bool isImm1_32() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 33; + return isImmediate<1, 32>(); } - bool isImm0_32() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 33; - } - bool isImm0_65535() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 65536; + bool isImm8_255() const { + return isImmediate<8, 255>(); } bool isImm256_65535Expr() const { if (!isImm()) return false; @@ -1145,32 +993,16 @@ return Value >= 0 && Value < 65536; } bool isImm24bit() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value <= 0xffffff; + return isImmediate<0, 0xffffff + 1>(); } bool isImmThumbSR() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value < 33; + return isImmediate<1, 33>(); } bool isPKHLSLImm() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value >= 0 && Value < 32; + return isImmediate<0, 32>(); } bool isPKHASRImm() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return false; - int64_t Value = CE->getValue(); - return Value > 0 && Value <= 32; + return isImmediate<0, 33>(); } bool isAdrLabel() const { // If we have an immediate that's not a constant, treat it as a label @@ -9158,6 +8990,13 @@ MatchResult = MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm, PendConditionalInstruction, Out); + SMLoc ErrorLoc; + if (ErrorInfo < Operands.size()) { + ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + } + switch (MatchResult) { case Match_Success: // Context sensitive operand constraints aren't handled by the matcher, @@ -9247,16 +9086,52 @@ return Error(IDLoc, "instruction variant requires ARMv8 or later"); case Match_RequiresFlagSetting: return Error(IDLoc, "no flag-preserving variant of this instruction available"); - case Match_ImmRange0_15: { - SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc(); - if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; + case Match_ImmRange0_1: + return Error(ErrorLoc, "immediate operand must be in the range [0,1]"); + case Match_ImmRange0_3: + return Error(ErrorLoc, "immediate operand must be in the range [0,3]"); + case Match_ImmRange0_7: + return Error(ErrorLoc, "immediate operand must be in the range [0,7]"); + case Match_ImmRange0_15: return Error(ErrorLoc, "immediate operand must be in the range [0,15]"); - } - case Match_ImmRange0_239: { - SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc(); - if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; + case Match_ImmRange0_31: + return Error(ErrorLoc, "immediate operand must be in the range [0,31]"); + case Match_ImmRange0_32: + return Error(ErrorLoc, "immediate operand must be in the range [0,32]"); + case Match_ImmRange0_63: + return Error(ErrorLoc, "immediate operand must be in the range [0,63]"); + case Match_ImmRange0_239: return Error(ErrorLoc, "immediate operand must be in the range [0,239]"); - } + case Match_ImmRange0_255: + return Error(ErrorLoc, "immediate operand must be in the range [0,255]"); + case Match_ImmRange0_4095: + return Error(ErrorLoc, "immediate operand must be in the range [0,4095]"); + case Match_ImmRange0_65535: + return Error(ErrorLoc, "immediate operand must be in the range [0,65535]"); + case Match_ImmRange1_7: + return Error(ErrorLoc, "immediate operand must be in the range [1,7]"); + case Match_ImmRange1_8: + return Error(ErrorLoc, "immediate operand must be in the range [1,8]"); + case Match_ImmRange1_15: + return Error(ErrorLoc, "immediate operand must be in the range [1,15]"); + case Match_ImmRange1_16: + return Error(ErrorLoc, "immediate operand must be in the range [1,16]"); + case Match_ImmRange1_31: + return Error(ErrorLoc, "immediate operand must be in the range [1,31]"); + case Match_ImmRange1_32: + return Error(ErrorLoc, "immediate operand must be in the range [1,32]"); + case Match_ImmRange1_64: + return Error(ErrorLoc, "immediate operand must be in the range [1,64]"); + case Match_ImmRange8_8: + return Error(ErrorLoc, "immediate operand must be 8."); + case Match_ImmRange16_16: + return Error(ErrorLoc, "immediate operand must be 16."); + case Match_ImmRange32_32: + return Error(ErrorLoc, "immediate operand must be 32."); + case Match_ImmRange256_65535: + return Error(ErrorLoc, "immediate operand must be in the range [255,65535]"); + case Match_ImmRange0_16777215: + return Error(ErrorLoc, "immediate operand must be in the range [0,0xffffff]"); case Match_AlignedMemoryRequiresNone: case Match_DupAlignedMemoryRequiresNone: case Match_AlignedMemoryRequires16: Index: llvm/trunk/test/MC/ARM/basic-arm-instructions-v8.1a.s =================================================================== --- llvm/trunk/test/MC/ARM/basic-arm-instructions-v8.1a.s +++ llvm/trunk/test/MC/ARM/basic-arm-instructions-v8.1a.s @@ -192,10 +192,10 @@ //CHECK-ERROR: error: too few operands for instruction //CHECK-ERROR: setpan //CHECK-ERROR: ^ -//CHECK-ERROR: error: invalid operand for instruction +//CHECK-ERROR: error: immediate operand must be in the range [0,1] //CHECK-ERROR: setpan #-1 //CHECK-ERROR: ^ -//CHECK-ERROR: error: invalid operand for instruction +//CHECK-ERROR: error: immediate operand must be in the range [0,1] //CHECK-ERROR: setpan #2 //CHECK-ERROR: ^ Index: llvm/trunk/test/MC/ARM/diagnostics.s =================================================================== --- llvm/trunk/test/MC/ARM/diagnostics.s +++ llvm/trunk/test/MC/ARM/diagnostics.s @@ -93,17 +93,19 @@ @ Out of range 16-bit immediate on BKPT bkpt #65536 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,65535] +@ CHECK-ERRORS: bkpt #65536 +@ CHECK-ERRORS: ^ @ Out of range immediates for v8 HLT instruction. hlt #65536 hlt #-1 -@CHECK-ERRORS: error: invalid operand for instruction +@CHECK-ERRORS: error: immediate operand must be in the range [0,65535] @CHECK-ERRORS: hlt #65536 -@CHECK-ERRORS: ^ -@CHECK-ERRORS: error: invalid operand for instruction +@CHECK-ERRORS: ^ +@CHECK-ERRORS: error: immediate operand must be in the range [0,65535] @CHECK-ERRORS: hlt #-1 -@CHECK-ERRORS: ^ +@CHECK-ERRORS: ^ @ Illegal condition code for v8 HLT instruction. hlteq #2 @@ -123,10 +125,14 @@ cdp2 p7, #2, c1, c1, c1, #8 cdp2 p7, #1, c1, c1, c1, #8 -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS-V8: error: invalid operand for instruction +@ CHECK-ERRORS-V8: error: invalid operand for instruction +@ CHECK-ERRORS-V8: error: invalid operand for instruction +@ CHECK-ERRORS-V8: error: invalid operand for instruction @ Out of range immediates for DBG dbg #-1 @@ -136,6 +142,7 @@ @ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ Double-check that we're synced up with the right diagnostics. @ CHECK-ERRORS: dbg #16 +@ CHECK-ERRORS: ^ @ Out of range immediate for MCR/MCR2/MCRR/MCRR2 mcr p7, #8, r5, c1, c1, #4 @@ -144,10 +151,10 @@ mcr2 p7, #1, r5, c1, c1, #8 mcrr p7, #16, r5, r4, c1 mcrr2 p7, #16, r5, r4, c1 -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] @ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V8: error: invalid operand for instruction @@ -161,16 +168,20 @@ @ Out of range immediate for MOV movw r9, 0x10000 @ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: movw r9, 0x10000 +@ CHECK-ERRORS: ^ @ Invalid 's' bit usage for MOVW movs r6, #0xffff movwseq r9, #0xffff -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,255] @ CHECK-ERRORS: error: instruction 'movw' can not set flags, but 's' suffix specified @ Out of range immediate for MOVT movt r9, 0x10000 @ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: movt r9, 0x10000 +@ CHECK-ERRORS: ^ @ Out of range immediates for MRC/MRC2/MRRC/MRRC2 mrc p14, #8, r1, c1, c2, #4 @@ -179,10 +190,10 @@ mrc2 p14, #0, r1, c1, c2, #9 mrrc p7, #16, r5, r4, c1 mrrc2 p7, #17, r5, r4, c1 -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] @ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V8: error: invalid operand for instruction @@ -242,10 +253,10 @@ ssat r8, #1, r10, lsl fred ssat r8, #1, r10, lsl #fred -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [1,32] @ CHECK-ERRORS: ssat r8, #0, r10, lsl #8 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [1,32] @ CHECK-ERRORS: ssat r8, #33, r10, lsl #8 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: 'lsr' shift amount must be in range [0,31] @@ -274,10 +285,10 @@ ssat16 r2, #0, r7 ssat16 r3, #17, r5 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [1,16] @ CHECK-ERRORS: ssat16 r2, #0, r7 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [1,16] @ CHECK-ERRORS: ssat16 r3, #17, r5 @ CHECK-ERRORS: ^ @@ -292,7 +303,7 @@ @ Out of range immediate on SVC svc #0x1000000 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,0xffffff] @ CHECK-ERRORS: svc #0x1000000 @ CHECK-ERRORS: ^ @@ -407,7 +418,7 @@ @ Bad CPS instruction format. cps f,#1 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,31] @ CHECK-ERRORS: cps f,#1 @ CHECK-ERRORS: ^ Index: llvm/trunk/test/MC/ARM/negative-immediates-fail.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates-fail.s +++ llvm/trunk/test/MC/ARM/negative-immediates-fail.s @@ -10,4 +10,4 @@ # CHECK: error: invalid operand for instruction ADD.W r0, r0, #0xFF01FF01 -# CHECK: error: invalid operand for instruction +# CHECK: error: immediate operand must be in the range [0,7] Index: llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s =================================================================== --- llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s +++ llvm/trunk/test/MC/ARM/negative-immediates-thumb1-fail.s @@ -6,10 +6,10 @@ # CHECK: error: instruction requires: arm-mode ADDs r0, #0xFFFFFEFF -# CHECK: error: invalid operand for instruction +# CHECK: error: immediate operand must be in the range [0,255] SUBs r1, r0, #0xFFFFFFF5 # CHECK: error: instruction requires: arm-mode SUBs r0, #0xFFFFFEFF -# CHECK: error: invalid operand for instruction +# CHECK: error: immediate operand must be in the range [0,255] Index: llvm/trunk/test/MC/ARM/thumb-diagnostics.s =================================================================== --- llvm/trunk/test/MC/ARM/thumb-diagnostics.s +++ llvm/trunk/test/MC/ARM/thumb-diagnostics.s @@ -28,7 +28,7 @@ @ Out of range immediates for ASR instruction. asrs r2, r3, #33 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,32] @ CHECK-ERRORS: asrs r2, r3, #33 @ CHECK-ERRORS: ^ @@ -51,7 +51,7 @@ @CHECK-ERRORS-V8: error: instruction requires: arm-mode @CHECK-ERRORS-V8: hlt #64 @CHECK-ERRORS-V8: ^ -@CHECK-ERRORS: error: invalid operand for instruction +@CHECK-ERRORS: error: immediate operand must be in the range [0,65535] @CHECK-ERRORS: hlt #-1 @CHECK-ERRORS: ^ @@ -153,10 +153,10 @@ @ Out of range immediates for LSL instruction. lsls r4, r5, #-1 lsls r4, r5, #32 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,31] @ CHECK-ERRORS: lsls r4, r5, #-1 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,31] @ CHECK-ERRORS: lsls r4, r5, #32 @ CHECK-ERRORS: ^ @@ -184,7 +184,7 @@ @ Out of range immediate for SVC instruction. svc #-1 svc #256 -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,0xffffff] @ CHECK-ERRORS: svc #-1 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: instruction requires: arm-mode Index: llvm/trunk/test/MC/ARM/thumb-not-mclass.s =================================================================== --- llvm/trunk/test/MC/ARM/thumb-not-mclass.s +++ llvm/trunk/test/MC/ARM/thumb-not-mclass.s @@ -22,5 +22,5 @@ setend be setend le -@ CHECK: error: invalid operand for instruction -@ CHECK: error: invalid operand for instruction +@ CHECK: error: immediate operand must be in the range [0,1] +@ CHECK: error: immediate operand must be in the range [0,1] Index: llvm/trunk/test/MC/ARM/thumb2-diagnostics.s =================================================================== --- llvm/trunk/test/MC/ARM/thumb2-diagnostics.s +++ llvm/trunk/test/MC/ARM/thumb2-diagnostics.s @@ -39,10 +39,10 @@ mrc2 p14, #0, r1, c1, c2, #9 mrrc p7, #16, r5, r4, c1 mrrc2 p7, #17, r5, r4, c1 -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction -@ CHECK-ERRORS: error: invalid operand for instruction +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] +@ CHECK-ERRORS: error: immediate operand must be in the range [0,7] @ CHECK-ERRORS: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15] @ CHECK-ERRORS-V8: error: invalid operand for instruction @@ -79,8 +79,7 @@ mov r0, foo2 movw r0, foo2 movt r0, foo2 -@ CHECK-ERRORS: error: immediate expression for mov requires :lower16: or :upper16 -@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: instruction requires: arm-mode @ CHECK-ERRORS: error: immediate expression for mov requires :lower16: or :upper16 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: immediate expression for mov requires :lower16: or :upper16 Index: llvm/trunk/test/MC/ARM/udf-arm-diagnostics.s =================================================================== --- llvm/trunk/test/MC/ARM/udf-arm-diagnostics.s +++ llvm/trunk/test/MC/ARM/udf-arm-diagnostics.s @@ -13,7 +13,7 @@ udf #65536 -@ CHECK: error: invalid operand for instruction +@ CHECK: error: immediate operand must be in the range [0,65535] @ CHECK: udf #65536 @ CHECK: ^ Index: llvm/trunk/test/MC/ARM/udf-thumb-2-diagnostics.s =================================================================== --- llvm/trunk/test/MC/ARM/udf-thumb-2-diagnostics.s +++ llvm/trunk/test/MC/ARM/udf-thumb-2-diagnostics.s @@ -19,7 +19,7 @@ udf.w #65536 -@ CHECK: error: invalid operand for instruction +@ CHECK: error: immediate operand must be in the range [0,65535] @ CHECK: udf.w #65536 @ CHECK: ^