diff options
author | Simon Dardis <simon.dardis@imgtec.com> | 2016-10-18 15:17:17 +0000 |
---|---|---|
committer | Simon Dardis <simon.dardis@imgtec.com> | 2016-10-18 15:17:17 +0000 |
commit | 858915f054ef80a89d285ffb4b0a50e32b08defe (patch) | |
tree | 90881ce0c80a609a9beae24ed3016a7e6bd727fe /llvm/lib | |
parent | af6ff2a91bd65ae5ed417314713e24190e428a45 (diff) | |
download | bcm5719-llvm-858915f054ef80a89d285ffb4b0a50e32b08defe.tar.gz bcm5719-llvm-858915f054ef80a89d285ffb4b0a50e32b08defe.zip |
[mips][ias] Handle more complicated expressions for memory operands
This patch teaches ias for mips to handle expressions such as
(8*4)+(8*31)($sp). Such expression typically occur from the expansion
of multiple macro definitions.
This partially resolves PR/30383.
Thanks to Sean Bruno for reporting the issue!
Reviewers: zoran.jovanovic, vkalintiris
Differential Revision: https://reviews.llvm.org/D24667
llvm-svn: 284485
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index ec8873289d6..70a5e50748b 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -4553,8 +4553,60 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this)); return MatchOperand_Success; } - Error(Parser.getTok().getLoc(), "'(' expected"); - return MatchOperand_ParseFail; + MCBinaryExpr::Opcode Opcode; + // GAS and LLVM treat comparison operators different. GAS will generate -1 + // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is + // highly unlikely to be found in a memory offset expression, we don't + // handle them. + switch (Tok.getKind()) { + case AsmToken::Plus: + Opcode = MCBinaryExpr::Add; + Parser.Lex(); + break; + case AsmToken::Minus: + Opcode = MCBinaryExpr::Sub; + Parser.Lex(); + break; + case AsmToken::Star: + Opcode = MCBinaryExpr::Mul; + Parser.Lex(); + break; + case AsmToken::Pipe: + Opcode = MCBinaryExpr::Or; + Parser.Lex(); + break; + case AsmToken::Amp: + Opcode = MCBinaryExpr::And; + Parser.Lex(); + break; + case AsmToken::LessLess: + Opcode = MCBinaryExpr::Shl; + Parser.Lex(); + break; + case AsmToken::GreaterGreater: + Opcode = MCBinaryExpr::LShr; + Parser.Lex(); + break; + case AsmToken::Caret: + Opcode = MCBinaryExpr::Xor; + Parser.Lex(); + break; + case AsmToken::Slash: + Opcode = MCBinaryExpr::Div; + Parser.Lex(); + break; + case AsmToken::Percent: + Opcode = MCBinaryExpr::Mod; + Parser.Lex(); + break; + default: + Error(Parser.getTok().getLoc(), "'(' or expression expected"); + return MatchOperand_ParseFail; + } + const MCExpr * NextExpr; + if (getParser().parseExpression(NextExpr)) + return MatchOperand_ParseFail; + IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext()); } Parser.Lex(); // Eat the '(' token. |