diff options
| author | Sjoerd Meijer <sjoerd.meijer@arm.com> | 2017-04-03 14:50:04 +0000 |
|---|---|---|
| committer | Sjoerd Meijer <sjoerd.meijer@arm.com> | 2017-04-03 14:50:04 +0000 |
| commit | 1179470ff8c710b4f609e2c052d3de84b9296eb8 (patch) | |
| tree | 7b74c6af6995b2faed0bd282cdfee73ccde37983 /llvm/lib/Target | |
| parent | 0b8949e6ed1497040c5dd3e375f65457f8003b1c (diff) | |
| download | bcm5719-llvm-1179470ff8c710b4f609e2c052d3de84b9296eb8.tar.gz bcm5719-llvm-1179470ff8c710b4f609e2c052d3de84b9296eb8.zip | |
ARMAsmParser: clean up of isImmediate functions
- we are now using immediate AsmOperands so that the range check functions are
tablegen'ed.
- Big bonus is that error messages become much more accurate, i.e. instead of a
useless "invalid operand" error message it will not say that the immediate
operand must in range [x,y], which is why regression tests needed updating.
More tablegen operand descriptions could probably benefit from using
immediateAsmOperand, but this is a first good step to get rid of most of the
nearly identical range check functions. I will address the remaining immediate
operands in next clean ups.
Differential Revision: https://reviews.llvm.org/D31333
llvm-svn: 299358
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrFormats.td | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrInfo.td | 73 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 277 |
5 files changed, 139 insertions, 238 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 97ab97b52d2..1bbe7f0d275 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -184,7 +184,7 @@ def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> { // ARM special operands for disassembly only. // -def SetEndAsmOperand : ImmAsmOperand { +def SetEndAsmOperand : ImmAsmOperand<0,1> { let Name = "SetEndImm"; let ParserMethod = "parseSetEndImm"; } @@ -221,25 +221,25 @@ def banked_reg : Operand<i32> { // 16 imm6<5:4> = '01', 16 - <imm> is encoded in imm6<3:0> // 32 imm6<5> = '1', 32 - <imm> is encoded in imm6<4:0> // 64 64 - <imm> 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<i32>, ImmLeaf<i32, [{ return Imm > 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<i32>, ImmLeaf<i32, [{ return Imm > 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<i32>, ImmLeaf<i32, [{ return Imm > 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<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 64; }]> { let EncoderMethod = "getShiftRight64Imm"; let DecoderMethod = "DecodeShiftRight64Imm"; @@ -957,7 +957,7 @@ class ADivA1I<bits<3> opcod, dag oops, dag iops, } // PKH instructions -def PKHLSLAsmOperand : ImmAsmOperand { +def PKHLSLAsmOperand : ImmAsmOperand<0,31> { let Name = "PKHLSLImm"; let ParserMethod = "parsePKHLSLImm"; } diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index eeb4a8148a1..f94b3090800 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -441,7 +441,16 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{ // // Immediate operands with a shared generic asm render method. -class ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; } +class ImmAsmOperand<int Low, int High> : AsmOperandClass { + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; + let DiagnosticType = "ImmRange" # Low # "_" # High; +} + +class ImmAsmOperandMinusOne<int Low, int High> : AsmOperandClass { + let PredicateMethod = "isImmediate<" # Low # "," # High # ">"; + let DiagnosticType = "ImmRange" # Low # "_" # High; +} // Operands that are part of a memory addressing mode. class MemOperand : Operand<i32> { let OperandType = "OPERAND_MEMORY"; } @@ -663,35 +672,45 @@ def arm_i32imm : PatLeaf<(imm), [{ }]>; /// 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<i32> { 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<i32> { 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<i32>, ImmLeaf<i32, [{ return Imm >= 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<i32>, ImmLeaf<i32, [{ + return Imm >= 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<i32>, ImmLeaf<i32, [{ return Imm == 8; }]> { 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<i32>, ImmLeaf<i32, [{ return Imm == 16; }]> { 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<i32>, ImmLeaf<i32, [{ return Imm == 32; }]> { let ParserMatchClass = Imm32AsmOperand; } @@ -699,25 +718,25 @@ def imm32 : Operand<i32>, ImmLeaf<i32, [{ return Imm == 32; }]> { def imm8_or_16 : ImmLeaf<i32, [{ return Imm == 8 || Imm == 16;}]>; /// 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<i32>, ImmLeaf<i32, [{ return Imm > 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<i32>, ImmLeaf<i32, [{ return Imm > 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<i32>, ImmLeaf<i32, [{ return Imm > 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 @@ def imm0_15 : Operand<i32>, ImmLeaf<i32, [{ } /// 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]> { @@ -736,15 +755,15 @@ def imm0_31 : Operand<i32>, ImmLeaf<i32, [{ } /// 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<i32>, ImmLeaf<i32, [{ - return Imm >= 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> { @@ -752,7 +771,7 @@ def imm0_63 : Operand<i32>, ImmLeaf<i32, [{ } /// 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 @@ def imm0_239 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 240; }]> { } /// 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<i32>, ImmLeaf<i32, [{ return Imm >= 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 65536; }]> { @@ -785,19 +804,23 @@ def imm0_65535_neg : Operand<i32>, ImmLeaf<i32, [{ // 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<i32> { 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<i32> { 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm <= 0xffffff; }]> { @@ -826,7 +849,9 @@ def imm1_32_XFORM: SDNodeXForm<imm, [{ 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<i32>, PatLeaf<(imm), [{ uint64_t Imm = N->getZExtValue(); return Imm > 0 && Imm <= 32; @@ -840,7 +865,7 @@ def imm1_16_XFORM: SDNodeXForm<imm, [{ 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<i32>, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }], imm1_16_XFORM> { let PrintMethod = "printImmPlusOneOperand"; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index c372bcdc262..f2f426e8670 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -19,7 +19,7 @@ def imm_sr_XFORM: SDNodeXForm<imm, [{ 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<i32>, PatLeaf<(imm), [{ uint64_t Imm = N->getZExtValue(); return Imm > 0 && Imm <= 32; @@ -53,9 +53,6 @@ def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; -def imm8_255 : ImmLeaf<i32, [{ - return Imm >= 8 && Imm < 256; -}]>; def imm8_255_neg : PatLeaf<(i32 imm), [{ unsigned Val = -N->getZExtValue(); return Val >= 8 && Val < 256; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index b52a7ceaf65..ec201204235 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -76,7 +76,11 @@ def t2_so_imm_notSext16_XFORM : SDNodeXForm<imm, [{ // 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<i32>, ImmLeaf<i32, [{ return ARM_AM::getT2SOImmVal(Imm) != -1; }]> { @@ -116,8 +120,8 @@ def t2_so_imm_neg : Operand<i32>, ImmLeaf<i32, [{ 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<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 4096; }]> { diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 233a5c7fee1..f421d3ac169 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -915,40 +915,37 @@ public: int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue())); return Val != -1; } - bool isFBits16() const { + + template<int64_t N, int64_t M> + bool isImmediate() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); if (!CE) return false; int64_t Value = CE->getValue(); - return Value >= 0 && Value <= 16; + return Value >= N && Value <= M; } - bool isFBits32() const { + template<int64_t N, int64_t M> + bool isImmediateS4() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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 @@ public: // 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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(getImm()); @@ -986,145 +962,17 @@ public: int64_t Value = -CE->getValue(); return Value > 0 && Value < 4096; } - bool isImm0_1() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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 @@ public: return Value >= 0 && Value < 65536; } bool isImm24bit() const { - if (!isImm()) return false; - const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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<MCConstantExpr>(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 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 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 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 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: |

