diff options
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 232 |
1 files changed, 180 insertions, 52 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 7438ea9..403f96c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -56,6 +56,14 @@ private: bool ParseDirectiveWord(unsigned Size, SMLoc L); + bool ParseDirectiveThumb(SMLoc L); + + bool ParseDirectiveThumbFunc(SMLoc L); + + bool ParseDirectiveCode(SMLoc L); + + bool ParseDirectiveSyntax(SMLoc L); + // TODO - For now hacked versions of the next two are in here in this file to // allow some parser testing until the table gen versions are implemented. @@ -230,8 +238,8 @@ bool ARMAsmParser::ParseRegister(ARMOperand &Op) { return false; } -// Try to parse a register list. The first token must be a '{' when called -// for now. +// Parse a register list, return false if successful else return true or an +// error. The first token must be a '{' when called. bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { assert(getLexer().getTok().is(AsmToken::LCurly) && "Token is not an Left Curly Brace"); @@ -277,7 +285,8 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { return false; } -// Try to parse an arm memory expression. It must start with a '[' token. +// Parse an arm memory expression, return false if successful else return true +// or an error. The first token must be a '[' when called. // TODO Only preindexing and postindexing addressing are started, unindexed // with option, etc are still to do. bool ARMAsmParser::ParseMemory(ARMOperand &Op) { @@ -374,50 +383,55 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { Writeback = true; getLexer().Lex(); // Eat right bracket token. - const AsmToken &CommaTok = getLexer().getTok(); - if (CommaTok.isNot(AsmToken::Comma)) - return Error(CommaTok.getLoc(), "',' expected"); - getLexer().Lex(); // Eat comma token. - - const AsmToken &NextTok = getLexer().getTok(); - if (NextTok.is(AsmToken::Plus)) - getLexer().Lex(); // Eat plus token. - else if (NextTok.is(AsmToken::Minus)) { - Negative = true; - getLexer().Lex(); // Eat minus token - } - - // See if there is a register following the "[Rn]," we have so far. - const AsmToken &OffsetRegTok = getLexer().getTok(); - int OffsetRegNum = MatchRegisterName(OffsetRegTok.getString()); + int OffsetRegNum = 0; bool OffsetRegShifted = false; enum ShiftType ShiftType; const MCExpr *ShiftAmount; const MCExpr *Offset; - if (OffsetRegNum != -1) { - OffsetIsReg = true; - getLexer().Lex(); // Eat identifier token for the offset register. - // Look for a comma then a shift - const AsmToken &Tok = getLexer().getTok(); - if (Tok.is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. - const AsmToken &Tok = getLexer().getTok(); - if (ParseShift(&ShiftType, ShiftAmount)) - return Error(Tok.getLoc(), "shift expected"); - OffsetRegShifted = true; + const AsmToken &NextTok = getLexer().getTok(); + if (NextTok.isNot(AsmToken::EndOfStatement)) { + if (NextTok.isNot(AsmToken::Comma)) + return Error(NextTok.getLoc(), "',' expected"); + getLexer().Lex(); // Eat comma token. + + const AsmToken &PlusMinusTok = getLexer().getTok(); + if (PlusMinusTok.is(AsmToken::Plus)) + getLexer().Lex(); // Eat plus token. + else if (PlusMinusTok.is(AsmToken::Minus)) { + Negative = true; + getLexer().Lex(); // Eat minus token } - } - else { // "[Rn]," we have so far was not followed by "Rm" - // Look for #offset following the "[Rn]," - const AsmToken &HashTok = getLexer().getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. - if (getParser().ParseExpression(Offset)) - return true; + // See if there is a register following the "[Rn]," we have so far. + const AsmToken &OffsetRegTok = getLexer().getTok(); + OffsetRegNum = MatchRegisterName(OffsetRegTok.getString()); + if (OffsetRegNum != -1) { + OffsetIsReg = true; + getLexer().Lex(); // Eat identifier token for the offset register. + // Look for a comma then a shift + const AsmToken &Tok = getLexer().getTok(); + if (Tok.is(AsmToken::Comma)) { + getLexer().Lex(); // Eat comma token. + + const AsmToken &Tok = getLexer().getTok(); + if (ParseShift(&ShiftType, ShiftAmount)) + return Error(Tok.getLoc(), "shift expected"); + OffsetRegShifted = true; + } + } + else { // "[Rn]," we have so far was not followed by "Rm" + // Look for #offset following the "[Rn]," + const AsmToken &HashTok = getLexer().getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + getLexer().Lex(); // Eat hash token. + + if (getParser().ParseExpression(Offset)) + return true; + } } + Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, OffsetRegShifted, ShiftType, ShiftAmount, Preindexed, Postindexed, Negative, Writeback); @@ -465,7 +479,7 @@ bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) { return false; } -// A hack to allow some testing +// A hack to allow some testing, to be replaced by a real table gen version. int ARMAsmParser::MatchRegisterName(const StringRef &Name) { if (Name == "r0" || Name == "R0") return 0; @@ -504,7 +518,7 @@ int ARMAsmParser::MatchRegisterName(const StringRef &Name) { return -1; } -// A hack to allow some testing +// A hack to allow some testing, to be replaced by a real table gen version. bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, MCInst &Inst) { struct ARMOperand Op0 = Operands[0]; @@ -516,40 +530,58 @@ bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, Mnemonic == "ldmfd" || Mnemonic == "ldr" || Mnemonic == "mov" || - Mnemonic == "sub") + Mnemonic == "sub" || + Mnemonic == "bl" || + Mnemonic == "push" || + Mnemonic == "blx" || + Mnemonic == "pop") { + // Hard-coded to a valid instruction, till we have a real matcher. + Inst = MCInst(); + Inst.setOpcode(ARM::MOVr); + Inst.addOperand(MCOperand::CreateReg(2)); + Inst.addOperand(MCOperand::CreateReg(2)); + Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::CreateReg(0)); return false; + } return true; } -// TODO - this is a work in progress +// Parse a arm instruction operand. For now this parses the operand regardless +// of the mnemonic. bool ARMAsmParser::ParseOperand(ARMOperand &Op) { switch (getLexer().getKind()) { case AsmToken::Identifier: if (!ParseRegister(Op)) return false; - // TODO parse other operands that start with an identifier like labels - return Error(getLexer().getTok().getLoc(), "labels not yet supported"); + // This was not a register so parse other operands that start with an + // identifier (like labels) as expressions and create them as immediates. + const MCExpr *IdVal; + if (getParser().ParseExpression(IdVal)) + return true; + Op = ARMOperand::CreateImm(IdVal); + return false; case AsmToken::LBrac: - if (!ParseMemory(Op)) - return false; + return ParseMemory(Op); case AsmToken::LCurly: - if (!ParseRegisterList(Op)) - return false; + return ParseRegisterList(Op); case AsmToken::Hash: // #42 -> immediate. // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate getLexer().Lex(); - const MCExpr *Val; - if (getParser().ParseExpression(Val)) + const MCExpr *ImmVal; + if (getParser().ParseExpression(ImmVal)) return true; - Op = ARMOperand::CreateImm(Val); + Op = ARMOperand::CreateImm(ImmVal); return false; default: return Error(getLexer().getTok().getLoc(), "unexpected token in operand"); } } +// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { SmallVector<ARMOperand, 7> Operands; @@ -579,10 +611,19 @@ bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { return true; } +/// ParseDirective parses the arm specific directives bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getIdentifier(); if (IDVal == ".word") return ParseDirectiveWord(4, DirectiveID.getLoc()); + else if (IDVal == ".thumb") + return ParseDirectiveThumb(DirectiveID.getLoc()); + else if (IDVal == ".thumb_func") + return ParseDirectiveThumbFunc(DirectiveID.getLoc()); + else if (IDVal == ".code") + return ParseDirectiveCode(DirectiveID.getLoc()); + else if (IDVal == ".syntax") + return ParseDirectiveSyntax(DirectiveID.getLoc()); return true; } @@ -611,6 +652,93 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { return false; } +/// ParseDirectiveThumb +/// ::= .thumb +bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + + // TODO: set thumb mode + // TODO: tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveThumbFunc +/// ::= .thumbfunc symbol_name +bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) + return Error(L, "unexpected token in .syntax directive"); + StringRef SymbolName = getLexer().getTok().getIdentifier(); + getLexer().Lex(); // Consume the identifier token. + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(L, "unexpected token in directive"); + getLexer().Lex(); + + // TODO: mark symbol as a thumb symbol + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveSyntax +/// ::= .syntax unified | divided +bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Identifier)) + return Error(L, "unexpected token in .syntax directive"); + const StringRef &Mode = Tok.getString(); + bool unified_syntax; + if (Mode == "unified" || Mode == "UNIFIED") { + getLexer().Lex(); + unified_syntax = true; + } + else if (Mode == "divided" || Mode == "DIVIDED") { + getLexer().Lex(); + unified_syntax = false; + } + else + return Error(L, "unrecognized syntax mode in .syntax directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); + getLexer().Lex(); + + // TODO tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + +/// ParseDirectiveCode +/// ::= .code 16 | 32 +bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { + const AsmToken &Tok = getLexer().getTok(); + if (Tok.isNot(AsmToken::Integer)) + return Error(L, "unexpected token in .code directive"); + int64_t Val = getLexer().getTok().getIntVal(); + bool thumb_mode; + if (Val == 16) { + getLexer().Lex(); + thumb_mode = true; + } + else if (Val == 32) { + getLexer().Lex(); + thumb_mode = false; + } + else + return Error(L, "invalid operand to .code directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getTok().getLoc(), "unexpected token in directive"); + getLexer().Lex(); + + // TODO tell the MC streamer the mode + // getParser().getStreamer().Emit???(); + return false; +} + // Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterAsmParser<ARMAsmParser> X(TheARMTarget); |