From 7bc44dcb0cfd9f8eaac2893fedc5daabacee5692 Mon Sep 17 00:00:00 2001 From: Toma Tabacu Date: Thu, 25 Jun 2015 09:52:02 +0000 Subject: [PATCH] [mips] [IAS] Fix parsing of memory offset expressions with parenthesis depth >1. Summary: In an expression such as "(((a+b)+c)+d)", parseParenExpression() would only parse the "a+b)+c", which would result in an error later on in the parser. This means that we can only parse one level of inner parentheses. In order to fix this, I added a new function called parseParenExprOfDepth(), which parses a specified number of trailing parenthesis expressions (except for the outermost parenthesis), and changed MipsAsmParser to use it in parseMemOffset instead of parseParenExpression(). Reviewers: dsanders, rafael Reviewed By: dsanders, rafael Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9742 llvm-svn: 240625 --- llvm/include/llvm/MC/MCParser/MCAsmParser.h | 11 +++++++++ llvm/lib/MC/MCParser/AsmParser.cpp | 23 +++++++++++++++++++ .../Target/Mips/AsmParser/MipsAsmParser.cpp | 7 ++++-- llvm/test/MC/Mips/expr1.s | 15 ++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h index 0538b9457f9e..ac8706d99505 100644 --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -197,6 +197,17 @@ public: /// \brief Ensure that we have a valid section set in the streamer. Otherwise, /// report an error and switch to .text. virtual void checkForValidSection() = 0; + + /// \brief Parse an arbitrary expression of a specified parenthesis depth, + /// assuming that the initial '(' characters have already been consumed. + /// + /// \param ParenDepth - Specifies how many trailing expressions outside the + /// current parentheses we have to parse. + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, + SMLoc &EndLoc) = 0; }; /// \brief Create an MCAsmParser instance. diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index c4f0d441f1dd..2245a466e62a 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -234,6 +234,8 @@ public: bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, + SMLoc &EndLoc) override; bool parseAbsoluteExpression(int64_t &Res) override; /// \brief Parse an identifier or string (as a quoted identifier) @@ -1066,6 +1068,27 @@ bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc); } +bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, + SMLoc &EndLoc) { + if (parseParenExpr(Res, EndLoc)) + return true; + + for (; ParenDepth > 0; --ParenDepth) { + if (parseBinOpRHS(1, Res, EndLoc)) + return true; + + // We don't Lex() the last RParen. + // This is the same behavior as parseParenExpression(). + if (ParenDepth - 1 > 0) { + if (Lexer.isNot(AsmToken::RParen)) + return TokError("expected ')' in parentheses expression"); + EndLoc = Lexer.getTok().getEndLoc(); + Lex(); + } + } + return false; +} + bool AsmParser::parseAbsoluteExpression(int64_t &Res) { const MCExpr *Expr; diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 03dbcb2c45b0..e323192a0ec6 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3105,9 +3105,12 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { MCAsmParser &Parser = getParser(); SMLoc S; bool Result = true; + unsigned NumOfLParen = 0; - while (getLexer().getKind() == AsmToken::LParen) + while (getLexer().getKind() == AsmToken::LParen) { Parser.Lex(); + ++NumOfLParen; + } switch (getLexer().getKind()) { default: @@ -3118,7 +3121,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { case AsmToken::Minus: case AsmToken::Plus: if (isParenExpr) - Result = getParser().parseParenExpression(Res, S); + Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S); else Result = (getParser().parseExpression(Res)); while (getLexer().getKind() == AsmToken::RParen) diff --git a/llvm/test/MC/Mips/expr1.s b/llvm/test/MC/Mips/expr1.s index 7959315a809a..4af61636355f 100644 --- a/llvm/test/MC/Mips/expr1.s +++ b/llvm/test/MC/Mips/expr1.s @@ -16,6 +16,11 @@ # 32R2-EL: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16 # 32R2-EL: lw $4, %lo(foo+8)($4) # encoding: [0x08'A',A,0x84,0x8c] # 32R2-EL: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_Mips_LO16 +# 32R2-EL: lw $4, 10($4) # encoding: [0x0a,0x00,0x84,0x8c] +# 32R2-EL: lw $4, 15($4) # encoding: [0x0f,0x00,0x84,0x8c] +# 32R2-EL: lw $4, 21($4) # encoding: [0x15,0x00,0x84,0x8c] +# 32R2-EL: lw $4, 28($4) # encoding: [0x1c,0x00,0x84,0x8c] +# 32R2-EL: lw $4, 6($4) # encoding: [0x06,0x00,0x84,0x8c] # 32R2-EL: .space 64 # MM-32R2-EL: .text @@ -30,6 +35,11 @@ # MM-32R2-EL: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16 # MM-32R2-EL: lw $4, %lo(foo+8)($4) # encoding: [0x84'A',0xfc'A',0x08,0x00] # MM-32R2-EL: # fixup A - offset: 0, value: foo@ABS_LO, kind: fixup_MICROMIPS_LO16 +# MM-32R2-EL: lw $4, 10($4) # encoding: [0x84,0xfc,0x0a,0x00] +# MM-32R2-EL: lw $4, 15($4) # encoding: [0x84,0xfc,0x0f,0x00] +# MM-32R2-EL: lw $4, 21($4) # encoding: [0x84,0xfc,0x15,0x00] +# MM-32R2-EL: lw $4, 28($4) # encoding: [0x84,0xfc,0x1c,0x00] +# MM-32R2-EL: lw $4, 6($4) # encoding: [0x84,0xfc,0x06,0x00] # MM-32R2-EL: .space 64 .globl foo @@ -40,5 +50,10 @@ foo: lw $4,%lo (2 * 4) + foo($4) lw $4,%lo((2 * 4) + foo)($4) lw $4,(((%lo ((2 * 4) + foo))))($4) + lw $4, (((1+2)+3)+4)($4) + lw $4, ((((1+2)+3)+4)+5)($4) + lw $4, (((((1+2)+3)+4)+5)+6)($4) + lw $4, ((((((1+2)+3)+4)+5)+6)+7)($4) + lw $4, (%lo((1+2)+65536)+3)($4) .space 64 .end foo