From 19906729a490744ce3071d20e3d514cadc12e6c5 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Wed, 13 Jul 2011 18:49:30 +0000 Subject: [PATCH] Improve ARM assembly parsing diagnostics a bit. Catch potential cascading errors on a malformed so_reg operand and bail after the first error. Add some tests for the diagnostics we do want. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135055 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 54 ++++++++++++++--------- test/MC/ARM/diagnostics.s | 43 ++++++++++++++++++ 2 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 test/MC/ARM/diagnostics.s diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 035907dd0a5..c72b206db9e 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -53,7 +53,7 @@ class ARMAsmParser : public TargetAsmParser { int TryParseRegister(); virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); bool TryParseRegisterWithWriteBack(SmallVectorImpl &); - bool TryParseShiftRegister(SmallVectorImpl &); + int TryParseShiftRegister(SmallVectorImpl &); bool ParseRegisterList(SmallVectorImpl &); bool ParseMemory(SmallVectorImpl &, ARMII::AddrMode AddrMode); @@ -1017,11 +1017,12 @@ int ARMAsmParser::TryParseRegister() { return RegNum; } -/// Try to parse a register name. The token must be an Identifier when called, -/// and if it is a register name the token is eaten and the register number is -/// returned. Otherwise return -1. -/// -bool ARMAsmParser::TryParseShiftRegister( +// Try to parse a shifter (e.g., "lsl "). On success, return 0. +// If a recoverable error occurs, return 1. If an irrecoverable error +// occurs, return -1. An irrecoverable error is one where tokens have been +// consumed in the process of trying to parse the shifter (i.e., when it is +// indeed a shifter operand, but malformed). +int ARMAsmParser::TryParseShiftRegister( SmallVectorImpl &Operands) { SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -1038,7 +1039,7 @@ bool ARMAsmParser::TryParseShiftRegister( .Default(ARM_AM::no_shift); if (ShiftTy == ARM_AM::no_shift) - return true; + return 1; Parser.Lex(); // Eat the operator. @@ -1062,12 +1063,16 @@ bool ARMAsmParser::TryParseShiftRegister( Parser.Lex(); // Eat hash. SMLoc ImmLoc = Parser.getTok().getLoc(); const MCExpr *ShiftExpr = 0; - if (getParser().ParseExpression(ShiftExpr)) - return Error(ImmLoc, "invalid immediate shift value"); + if (getParser().ParseExpression(ShiftExpr)) { + Error(ImmLoc, "invalid immediate shift value"); + return -1; + } // The expression must be evaluatable as an immediate. const MCConstantExpr *CE = dyn_cast(ShiftExpr); - if (!CE) - return Error(ImmLoc, "invalid immediate shift value"); + if (!CE) { + Error(ImmLoc, "invalid immediate shift value"); + return -1; + } // Range check the immediate. // lsl, ror: 0 <= imm <= 31 // lsr, asr: 0 <= imm <= 32 @@ -1075,24 +1080,28 @@ bool ARMAsmParser::TryParseShiftRegister( if (Imm < 0 || ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) || ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) { - return Error(ImmLoc, "immediate shift value out of range"); + Error(ImmLoc, "immediate shift value out of range"); + return -1; } } else if (Parser.getTok().is(AsmToken::Identifier)) { ShiftReg = TryParseRegister(); SMLoc L = Parser.getTok().getLoc(); - if (ShiftReg == -1) - return Error (L, "expected immediate or register in shift operand"); - } else - return Error (Parser.getTok().getLoc(), + if (ShiftReg == -1) { + Error (L, "expected immediate or register in shift operand"); + return -1; + } + } else { + Error (Parser.getTok().getLoc(), "expected immediate or register in shift operand"); + return -1; + } } - Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, ShiftReg, Imm, S, Parser.getTok().getLoc())); - return false; + return 0; } @@ -1737,15 +1746,18 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl &Operands, default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); return true; - case AsmToken::Identifier: + case AsmToken::Identifier: { if (!TryParseRegisterWithWriteBack(Operands)) return false; - if (!TryParseShiftRegister(Operands)) + int Res = TryParseShiftRegister(Operands); + if (Res == 0) // success return false; - + else if (Res == -1) // irrecoverable error + return true; // Fall though for the Identifier case that is not a register or a // special name. + } case AsmToken::Integer: // things like 1f and 2b as a branch targets case AsmToken::Dot: { // . as a branch target // This was not a register so parse other operands that start with an diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s new file mode 100644 index 00000000000..dab84c1df10 --- /dev/null +++ b/test/MC/ARM/diagnostics.s @@ -0,0 +1,43 @@ +@ RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2> %t +@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s + +@ Check for various assembly diagnostic messages on invalid input. + + @ Out of range shift immediate values. + adc r1, r2, r3, lsl #invalid + adc r4, r5, r6, lsl #-1 + adc r4, r5, r6, lsl #32 + adc r4, r5, r6, lsr #-1 + adc r4, r5, r6, lsr #33 + adc r4, r5, r6, asr #-1 + adc r4, r5, r6, asr #33 + adc r4, r5, r6, ror #-1 + adc r4, r5, r6, ror #32 + +@ CHECK-ERRORS: error: invalid immediate shift value +@ CHECK-ERRORS: adc r1, r2, r3, lsl #invalid +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, lsl #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, lsl #32 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, lsr #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, lsr #33 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, asr #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, asr #33 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, ror #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: adc r4, r5, r6, ror #32 +@ CHECK-ERRORS: ^