diff options
| author | Bradley Smith <bradley.smith@arm.com> | 2014-05-12 11:49:16 +0000 |
|---|---|---|
| committer | Bradley Smith <bradley.smith@arm.com> | 2014-05-12 11:49:16 +0000 |
| commit | bbec45a4f1cf23c2d064bb92cd3f0b3596c41a4c (patch) | |
| tree | 15de5432e3aa436758c4304f280e527e3f252135 /llvm/lib/Target | |
| parent | fb4333b093352de9298fff0f5307d60953a3520b (diff) | |
| download | bcm5719-llvm-bbec45a4f1cf23c2d064bb92cd3f0b3596c41a4c.tar.gz bcm5719-llvm-bbec45a4f1cf23c2d064bb92cd3f0b3596c41a4c.zip | |
[ARM64] Add proper bounds checking/diagnostics to logical shifts
llvm-svn: 208540
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM64/ARM64InstrFormats.td | 28 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM64/ARM64InstrInfo.td | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 29 |
3 files changed, 43 insertions, 22 deletions
diff --git a/llvm/lib/Target/ARM64/ARM64InstrFormats.td b/llvm/lib/Target/ARM64/ARM64InstrFormats.td index 4e97a99ef68..8cbdaf558a8 100644 --- a/llvm/lib/Target/ARM64/ARM64InstrFormats.td +++ b/llvm/lib/Target/ARM64/ARM64InstrFormats.td @@ -108,6 +108,18 @@ class ArithmeticShifterOperand<int width> : AsmOperandClass { def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>; def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>; +// Shifter operand for logical register shifted encodings. +class LogicalShifterOperand<int width> : AsmOperandClass { + let SuperClasses = [ShifterOperand]; + let Name = "LogicalShifter" # width; + let PredicateMethod = "isLogicalShifter<" # width # ">"; + let RenderMethod = "addLogicalShifterOperands"; + let DiagnosticType = "AddSubRegShift" # width; +} + +def LogicalShifterOperand32 : LogicalShifterOperand<32>; +def LogicalShifterOperand64 : LogicalShifterOperand<64>; + // Shifter operand for logical vector 128/64-bit shifted encodings. def LogicalVecShifterOperand : AsmOperandClass { let SuperClasses = [ShifterOperand]; @@ -525,20 +537,24 @@ def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>; // An arithmetic shifter operand: // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror // {5-0} - imm6 -def logical_shift : Operand<i32> { +class logical_shift<int width> : Operand<i32> { let PrintMethod = "printShifter"; - let ParserMatchClass = ShifterOperand; + let ParserMatchClass = !cast<AsmOperandClass>( + "LogicalShifterOperand" # width); } -class logical_shifted_reg<ValueType Ty, RegisterClass regclass> +def logical_shift32 : logical_shift<32>; +def logical_shift64 : logical_shift<64>; + +class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop> : Operand<Ty>, ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> { let PrintMethod = "printShiftedRegister"; - let MIOperandInfo = (ops regclass, logical_shift); + let MIOperandInfo = (ops regclass, shiftop); } -def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>; -def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>; +def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>; +def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>; // A logical vector shifter operand: // {7-6} - shift type: 00 = lsl diff --git a/llvm/lib/Target/ARM64/ARM64InstrInfo.td b/llvm/lib/Target/ARM64/ARM64InstrInfo.td index 46ba5bbb658..d674b918c8f 100644 --- a/llvm/lib/Target/ARM64/ARM64InstrInfo.td +++ b/llvm/lib/Target/ARM64/ARM64InstrInfo.td @@ -671,9 +671,9 @@ def : InstAlias<"tst $src1, $src2", (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, 0)>; def : InstAlias<"tst $src1, $src2, $sh", - (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift:$sh)>; + (ANDSWrs WZR, GPR32:$src1, GPR32:$src2, logical_shift32:$sh)>; def : InstAlias<"tst $src1, $src2, $sh", - (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift:$sh)>; + (ANDSXrs XZR, GPR64:$src1, GPR64:$src2, logical_shift64:$sh)>; def : InstAlias<"mvn $Wd, $Wm", (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, 0)>; @@ -681,9 +681,9 @@ def : InstAlias<"mvn $Xd, $Xm", (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, 0)>; def : InstAlias<"mvn $Wd, $Wm, $sh", - (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift:$sh)>; + (ORNWrs GPR32:$Wd, WZR, GPR32:$Wm, logical_shift32:$sh)>; def : InstAlias<"mvn $Xd, $Xm, $sh", - (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift:$sh)>; + (ORNXrs GPR64:$Xd, XZR, GPR64:$Xm, logical_shift64:$sh)>; def : Pat<(not GPR32:$Wm), (ORNWrr WZR, GPR32:$Wm)>; def : Pat<(not GPR64:$Xm), (ORNXrr XZR, GPR64:$Xm)>; diff --git a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp index b2583a0f124..760c2fcb59c 100644 --- a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp +++ b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp @@ -845,6 +845,18 @@ public: ST == ARM64_AM::ASR) && ARM64_AM::getShiftValue(Shifter.Val) < width; } + template <unsigned width> + bool isLogicalShifter() const { + if (!isShifter()) + return false; + + // A logical shifter is LSL, LSR, ASR or ROR. + ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(Shifter.Val); + return (ST == ARM64_AM::LSL || ST == ARM64_AM::LSR || + ST == ARM64_AM::ASR || ST == ARM64_AM::ROR) && + ARM64_AM::getShiftValue(Shifter.Val) < width; + } + bool isMovImm32Shifter() const { if (!isShifter()) return false; @@ -1453,6 +1465,11 @@ public: Inst.addOperand(MCOperand::CreateImm(getShifter())); } + void addLogicalShifterOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getShifter())); + } + void addMovImm32ShifterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(getShifter())); @@ -3677,18 +3694,6 @@ bool ARM64AsmParser::validateInstruction(MCInst &Inst, // in the instructions being checked and this keeps the nested conditionals // to a minimum. switch (Inst.getOpcode()) { - case ARM64::ANDWrs: - case ARM64::ANDSWrs: - case ARM64::EORWrs: - case ARM64::ORRWrs: { - if (!Inst.getOperand(3).isImm()) - return Error(Loc[3], "immediate value expected"); - int64_t shifter = Inst.getOperand(3).getImm(); - ARM64_AM::ShiftType ST = ARM64_AM::getShiftType(shifter); - if (ST == ARM64_AM::LSL && shifter > 31) - return Error(Loc[3], "shift value out of range"); - return false; - } case ARM64::ADDSWri: case ARM64::ADDSXri: case ARM64::ADDWri: |

