X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FAsmParser%2FARMAsmParser.cpp;h=4b083244b2413eea9f6b7be09f10f54e38fe8e4c;hb=38e59891ee4417a9be2f8146ce0ba3269e38ac21;hp=403f96c69e581da12911348f8b1024ab4e24241c;hpb=2685a29a8d4ced7791bb671e28f9fe51c74eb3bb;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 403f96c69e5..4b083244b24 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -8,16 +8,19 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAsmLexer.h" -#include "llvm/MC/MCAsmParser.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmParser.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" using namespace llvm; namespace { @@ -44,15 +47,24 @@ private: bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } - bool ParseRegister(ARMOperand &Op); + bool MaybeParseRegister(OwningPtr &Op, bool ParseWriteBack); + + bool ParseRegisterList(OwningPtr &Op); - bool ParseRegisterList(ARMOperand &Op); + bool ParseMemory(OwningPtr &Op); - bool ParseMemory(ARMOperand &Op); + bool ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum, + SMLoc &E); - bool ParseShift(enum ShiftType *St, const MCExpr *&ShiftAmount); + bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E); - bool ParseOperand(ARMOperand &Op); + bool ParseOperand(OwningPtr &Op); bool ParseDirectiveWord(unsigned Size, SMLoc L); @@ -69,14 +81,14 @@ private: /// @name Auto-generated Match Functions /// { - bool MatchInstruction(SmallVectorImpl &Operands, + bool MatchInstruction(const SmallVectorImpl &Operands, MCInst &Inst); /// MatchRegisterName - Match the given string to a register name and return /// its register number, or -1 if there is no match. To allow return values /// to be used directly in register lists, arm registers have values between /// 0 and 15. - int MatchRegisterName(const StringRef &Name); + int MatchRegisterName(StringRef Name); /// } @@ -85,25 +97,26 @@ public: ARMAsmParser(const Target &T, MCAsmParser &_Parser) : TargetAsmParser(T), Parser(_Parser) {} - virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst); + virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl &Operands); virtual bool ParseDirective(AsmToken DirectiveID); }; -} // end anonymous namespace - -namespace { - /// ARMOperand - Instances of this class represent a parsed ARM machine /// instruction. -struct ARMOperand { - enum { +struct ARMOperand : public MCParsedAsmOperand { +private: + ARMOperand() {} +public: + enum KindTy { Token, Register, Immediate, Memory } Kind; + SMLoc StartLoc, EndLoc; union { struct { @@ -119,23 +132,52 @@ struct ARMOperand { struct { const MCExpr *Val; } Imm; - + // This is for all forms of ARM address expressions struct { unsigned BaseRegNum; - bool OffsetIsReg; - const MCExpr *Offset; // used when OffsetIsReg is false unsigned OffsetRegNum; // used when OffsetIsReg is true - bool OffsetRegShifted; // only used when OffsetIsReg is true - enum ShiftType ShiftType; // used when OffsetRegShifted is true + const MCExpr *Offset; // used when OffsetIsReg is false const MCExpr *ShiftAmount; // used when OffsetRegShifted is true - bool Preindexed; - bool Postindexed; - bool Negative; // only used when OffsetIsReg is true - bool Writeback; + enum ShiftType ShiftType; // used when OffsetRegShifted is true + unsigned + OffsetRegShifted : 1, // only used when OffsetIsReg is true + Preindexed : 1, + Postindexed : 1, + OffsetIsReg : 1, + Negative : 1, // only used when OffsetIsReg is true + Writeback : 1; } Mem; }; + + ARMOperand(KindTy K, SMLoc S, SMLoc E) + : Kind(K), StartLoc(S), EndLoc(E) {} + + ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() { + Kind = o.Kind; + StartLoc = o.StartLoc; + EndLoc = o.EndLoc; + switch (Kind) { + case Token: + Tok = o.Tok; + break; + case Register: + Reg = o.Reg; + break; + case Immediate: + Imm = o.Imm; + break; + case Memory: + Mem = o.Mem; + break; + } + } + + /// getStartLoc - Get the location of the first token of this operand. + SMLoc getStartLoc() const { return StartLoc; } + /// getEndLoc - Get the location of the last token of this operand. + SMLoc getEndLoc() const { return EndLoc; } StringRef getToken() const { assert(Kind == Token && "Invalid access!"); @@ -161,60 +203,74 @@ struct ARMOperand { Inst.addOperand(MCOperand::CreateReg(getReg())); } - static ARMOperand CreateToken(StringRef Str) { - ARMOperand Res; - Res.Kind = Token; - Res.Tok.Data = Str.data(); - Res.Tok.Length = Str.size(); - return Res; + static void CreateToken(OwningPtr &Op, StringRef Str, + SMLoc S) { + Op.reset(new ARMOperand); + Op->Kind = Token; + Op->Tok.Data = Str.data(); + Op->Tok.Length = Str.size(); + Op->StartLoc = S; + Op->EndLoc = S; } - static ARMOperand CreateReg(unsigned RegNum, bool Writeback) { - ARMOperand Res; - Res.Kind = Register; - Res.Reg.RegNum = RegNum; - Res.Reg.Writeback = Writeback; - return Res; + static void CreateReg(OwningPtr &Op, unsigned RegNum, + bool Writeback, SMLoc S, SMLoc E) { + Op.reset(new ARMOperand); + Op->Kind = Register; + Op->Reg.RegNum = RegNum; + Op->Reg.Writeback = Writeback; + + Op->StartLoc = S; + Op->EndLoc = E; } - static ARMOperand CreateImm(const MCExpr *Val) { - ARMOperand Res; - Res.Kind = Immediate; - Res.Imm.Val = Val; - return Res; + static void CreateImm(OwningPtr &Op, const MCExpr *Val, + SMLoc S, SMLoc E) { + Op.reset(new ARMOperand); + Op->Kind = Immediate; + Op->Imm.Val = Val; + + Op->StartLoc = S; + Op->EndLoc = E; } - static ARMOperand CreateMem(unsigned BaseRegNum, bool OffsetIsReg, - const MCExpr *Offset, unsigned OffsetRegNum, - bool OffsetRegShifted, enum ShiftType ShiftType, - const MCExpr *ShiftAmount, bool Preindexed, - bool Postindexed, bool Negative, bool Writeback) { - ARMOperand Res; - Res.Kind = Memory; - Res.Mem.BaseRegNum = BaseRegNum; - Res.Mem.OffsetIsReg = OffsetIsReg; - Res.Mem.Offset = Offset; - Res.Mem.OffsetRegNum = OffsetRegNum; - Res.Mem.OffsetRegShifted = OffsetRegShifted; - Res.Mem.ShiftType = ShiftType; - Res.Mem.ShiftAmount = ShiftAmount; - Res.Mem.Preindexed = Preindexed; - Res.Mem.Postindexed = Postindexed; - Res.Mem.Negative = Negative; - Res.Mem.Writeback = Writeback; - return Res; + static void CreateMem(OwningPtr &Op, + unsigned BaseRegNum, bool OffsetIsReg, + const MCExpr *Offset, unsigned OffsetRegNum, + bool OffsetRegShifted, enum ShiftType ShiftType, + const MCExpr *ShiftAmount, bool Preindexed, + bool Postindexed, bool Negative, bool Writeback, + SMLoc S, SMLoc E) { + Op.reset(new ARMOperand); + Op->Kind = Memory; + Op->Mem.BaseRegNum = BaseRegNum; + Op->Mem.OffsetIsReg = OffsetIsReg; + Op->Mem.Offset = Offset; + Op->Mem.OffsetRegNum = OffsetRegNum; + Op->Mem.OffsetRegShifted = OffsetRegShifted; + Op->Mem.ShiftType = ShiftType; + Op->Mem.ShiftAmount = ShiftAmount; + Op->Mem.Preindexed = Preindexed; + Op->Mem.Postindexed = Postindexed; + Op->Mem.Negative = Negative; + Op->Mem.Writeback = Writeback; + + Op->StartLoc = S; + Op->EndLoc = E; } }; } // end anonymous namespace. -// Try to parse a register name. The token must be an Identifier when called, -// and if it is a register name a Reg operand is created, the token is eaten -// and false is returned. Else true is returned and no token is eaten. -// TODO this is likely to change to allow different register types and or to -// parse for a specific register type. -bool ARMAsmParser::ParseRegister(ARMOperand &Op) { - const AsmToken &Tok = getLexer().getTok(); +/// Try to parse a register name. The token must be an Identifier when called, +/// and if it is a register name a Reg operand is created, the token is eaten +/// and false is returned. Else true is returned and no token is eaten. +/// TODO this is likely to change to allow different register types and or to +/// parse for a specific register type. +bool ARMAsmParser::MaybeParseRegister + (OwningPtr &Op, bool ParseWriteBack) { + SMLoc S, E; + const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); // FIXME: Validate register for the current architecture; we have to do @@ -224,43 +280,53 @@ bool ARMAsmParser::ParseRegister(ARMOperand &Op) { RegNum = MatchRegisterName(Tok.getString()); if (RegNum == -1) return true; - getLexer().Lex(); // Eat identifier token. + + S = Tok.getLoc(); + + Parser.Lex(); // Eat identifier token. + + E = Parser.getTok().getLoc(); bool Writeback = false; - const AsmToken &ExclaimTok = getLexer().getTok(); - if (ExclaimTok.is(AsmToken::Exclaim)) { - Writeback = true; - getLexer().Lex(); // Eat exclaim token + if (ParseWriteBack) { + const AsmToken &ExclaimTok = Parser.getTok(); + if (ExclaimTok.is(AsmToken::Exclaim)) { + E = ExclaimTok.getLoc(); + Writeback = true; + Parser.Lex(); // Eat exclaim token + } } - Op = ARMOperand::CreateReg(RegNum, Writeback); + ARMOperand::CreateReg(Op, RegNum, Writeback, S, E); return false; } -// 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) && +/// 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(OwningPtr &Op) { + SMLoc S, E; + assert(Parser.getTok().is(AsmToken::LCurly) && "Token is not an Left Curly Brace"); - getLexer().Lex(); // Eat left curly brace token. + S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat left curly brace token. - const AsmToken &RegTok = getLexer().getTok(); + const AsmToken &RegTok = Parser.getTok(); SMLoc RegLoc = RegTok.getLoc(); if (RegTok.isNot(AsmToken::Identifier)) return Error(RegLoc, "register expected"); int RegNum = MatchRegisterName(RegTok.getString()); if (RegNum == -1) return Error(RegLoc, "register expected"); - getLexer().Lex(); // Eat identifier token. + Parser.Lex(); // Eat identifier token. unsigned RegList = 1 << RegNum; int HighRegNum = RegNum; // TODO ranges like "{Rn-Rm}" - while (getLexer().getTok().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. + while (Parser.getTok().is(AsmToken::Comma)) { + Parser.Lex(); // Eat comma token. - const AsmToken &RegTok = getLexer().getTok(); + const AsmToken &RegTok = Parser.getTok(); SMLoc RegLoc = RegTok.getLoc(); if (RegTok.isNot(AsmToken::Identifier)) return Error(RegLoc, "register expected"); @@ -275,32 +341,34 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { RegList |= 1 << RegNum; HighRegNum = RegNum; - getLexer().Lex(); // Eat identifier token. + Parser.Lex(); // Eat identifier token. } - const AsmToken &RCurlyTok = getLexer().getTok(); + const AsmToken &RCurlyTok = Parser.getTok(); if (RCurlyTok.isNot(AsmToken::RCurly)) return Error(RCurlyTok.getLoc(), "'}' expected"); - getLexer().Lex(); // Eat left curly brace token. + E = RCurlyTok.getLoc(); + Parser.Lex(); // Eat left curly brace token. return false; } -// 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) { - assert(getLexer().getTok().is(AsmToken::LBrac) && +/// 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(OwningPtr &Op) { + SMLoc S, E; + assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not an Left Bracket"); - getLexer().Lex(); // Eat left bracket token. + S = Parser.getTok().getLoc(); + Parser.Lex(); // Eat left bracket token. - const AsmToken &BaseRegTok = getLexer().getTok(); + const AsmToken &BaseRegTok = Parser.getTok(); if (BaseRegTok.isNot(AsmToken::Identifier)) return Error(BaseRegTok.getLoc(), "register expected"); - int BaseRegNum = MatchRegisterName(BaseRegTok.getString()); - if (BaseRegNum == -1) + if (MaybeParseRegister(Op, false)) return Error(BaseRegTok.getLoc(), "register expected"); - getLexer().Lex(); // Eat identifier token. + int BaseRegNum = Op->getReg(); bool Preindexed = false; bool Postindexed = false; @@ -308,80 +376,45 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { bool Negative = false; bool Writeback = false; - // First look for preindexed address forms: - // [Rn, +/-Rm] - // [Rn, #offset] - // [Rn, +/-Rm, shift] - // that is after the "[Rn" we now have see if the next token is a comma. - const AsmToken &Tok = getLexer().getTok(); + // First look for preindexed address forms, that is after the "[Rn" we now + // have to see if the next token is a comma. + const AsmToken &Tok = Parser.getTok(); if (Tok.is(AsmToken::Comma)) { Preindexed = true; - 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()); - bool OffsetRegShifted = false; + Parser.Lex(); // Eat comma token. + int OffsetRegNum; + bool OffsetRegShifted; 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; - } - } - 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; - } - const AsmToken &RBracTok = getLexer().getTok(); + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, + Offset, OffsetIsReg, OffsetRegNum, E)) + return true; + const AsmToken &RBracTok = Parser.getTok(); if (RBracTok.isNot(AsmToken::RBrac)) return Error(RBracTok.getLoc(), "']' expected"); - getLexer().Lex(); // Eat right bracket token. + E = RBracTok.getLoc(); + Parser.Lex(); // Eat right bracket token. - const AsmToken &ExclaimTok = getLexer().getTok(); + const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { + E = ExclaimTok.getLoc(); Writeback = true; - getLexer().Lex(); // Eat exclaim token + Parser.Lex(); // Eat exclaim token } - Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, - OffsetRegShifted, ShiftType, ShiftAmount, - Preindexed, Postindexed, Negative, Writeback); + ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, + OffsetRegShifted, ShiftType, ShiftAmount, + Preindexed, Postindexed, Negative, Writeback, S, E); return false; } // The "[Rn" we have so far was not followed by a comma. else if (Tok.is(AsmToken::RBrac)) { - // This is a post indexing addressing forms: - // [Rn], #offset - // [Rn], +/-Rm - // [Rn], +/-Rm, shift - // that is a ']' follows after the "[Rn". + // This is a post indexing addressing forms, that is a ']' follows after + // the "[Rn". Postindexed = true; Writeback = true; - getLexer().Lex(); // Eat right bracket token. + E = Tok.getLoc(); + Parser.Lex(); // Eat right bracket token. int OffsetRegNum = 0; bool OffsetRegShifted = false; @@ -389,98 +422,134 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { const MCExpr *ShiftAmount; const MCExpr *Offset; - const AsmToken &NextTok = getLexer().getTok(); + const AsmToken &NextTok = Parser.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 - } - - // 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; - } + return Error(NextTok.getLoc(), "',' expected"); + Parser.Lex(); // Eat comma token. + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, + ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, + E)) + return true; } - Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, - OffsetRegShifted, ShiftType, ShiftAmount, - Preindexed, Postindexed, Negative, Writeback); + ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, + OffsetRegShifted, ShiftType, ShiftAmount, + Preindexed, Postindexed, Negative, Writeback, S, E); return false; } return true; } +/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," +/// we will parse the following (were +/- means that a plus or minus is +/// optional): +/// +/-Rm +/// +/-Rm, shift +/// #offset +/// we return false on success or an error otherwise. +bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum, + SMLoc &E) { + OwningPtr Op; + Negative = false; + OffsetRegShifted = false; + OffsetIsReg = false; + OffsetRegNum = -1; + const AsmToken &NextTok = Parser.getTok(); + E = NextTok.getLoc(); + if (NextTok.is(AsmToken::Plus)) + Parser.Lex(); // Eat plus token. + else if (NextTok.is(AsmToken::Minus)) { + Negative = true; + Parser.Lex(); // Eat minus token + } + // See if there is a register following the "[Rn," or "[Rn]," we have so far. + const AsmToken &OffsetRegTok = Parser.getTok(); + if (OffsetRegTok.is(AsmToken::Identifier)) { + OffsetIsReg = !MaybeParseRegister(Op, false); + if (OffsetIsReg) { + E = Op->getEndLoc(); + OffsetRegNum = Op->getReg(); + } + } + // If we parsed a register as the offset then their can be a shift after that + if (OffsetRegNum != -1) { + // Look for a comma then a shift + const AsmToken &Tok = Parser.getTok(); + if (Tok.is(AsmToken::Comma)) { + Parser.Lex(); // Eat comma token. + + const AsmToken &Tok = Parser.getTok(); + if (ParseShift(ShiftType, ShiftAmount, E)) + return Error(Tok.getLoc(), "shift expected"); + OffsetRegShifted = true; + } + } + else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" + // Look for #offset following the "[Rn," or "[Rn]," + const AsmToken &HashTok = Parser.getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + + Parser.Lex(); // Eat hash token. + + if (getParser().ParseExpression(Offset)) + return true; + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + } + return false; +} + /// ParseShift as one of these two: /// ( lsl | lsr | asr | ror ) , # shift_amount /// rrx /// and returns true if it parses a shift otherwise it returns false. -bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) { - const AsmToken &Tok = getLexer().getTok(); +bool ARMAsmParser::ParseShift(ShiftType &St, + const MCExpr *&ShiftAmount, + SMLoc &E) { + const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return true; - const StringRef &ShiftName = Tok.getString(); + StringRef ShiftName = Tok.getString(); if (ShiftName == "lsl" || ShiftName == "LSL") - *St = Lsl; + St = Lsl; else if (ShiftName == "lsr" || ShiftName == "LSR") - *St = Lsr; + St = Lsr; else if (ShiftName == "asr" || ShiftName == "ASR") - *St = Asr; + St = Asr; else if (ShiftName == "ror" || ShiftName == "ROR") - *St = Ror; + St = Ror; else if (ShiftName == "rrx" || ShiftName == "RRX") - *St = Rrx; + St = Rrx; else return true; - getLexer().Lex(); // Eat shift type token. + Parser.Lex(); // Eat shift type token. - // For all but a Rotate right there must be a '#' and a shift amount - if (*St != Rrx) { - // Look for # following the shift type - const AsmToken &HashTok = getLexer().getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. + // Rrx stands alone. + if (St == Rrx) + return false; - if (getParser().ParseExpression(ShiftAmount)) - return true; - } + // Otherwise, there must be a '#' and a shift amount. + const AsmToken &HashTok = Parser.getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + Parser.Lex(); // Eat hash token. + + if (getParser().ParseExpression(ShiftAmount)) + return true; return false; } -// A hack to allow some testing, to be replaced by a real table gen version. -int ARMAsmParser::MatchRegisterName(const StringRef &Name) { +/// A hack to allow some testing, to be replaced by a real table gen version. +int ARMAsmParser::MatchRegisterName(StringRef Name) { if (Name == "r0" || Name == "R0") return 0; else if (Name == "r1" || Name == "R1") @@ -518,12 +587,13 @@ int ARMAsmParser::MatchRegisterName(const StringRef &Name) { return -1; } -// A hack to allow some testing, to be replaced by a real table gen version. -bool ARMAsmParser::MatchInstruction(SmallVectorImpl &Operands, - MCInst &Inst) { - struct ARMOperand Op0 = Operands[0]; +/// A hack to allow some testing, to be replaced by a real table gen version. +bool ARMAsmParser:: +MatchInstruction(const SmallVectorImpl &Operands, + MCInst &Inst) { + ARMOperand &Op0 = *(ARMOperand*)Operands[0]; assert(Op0.Kind == ARMOperand::Token && "First operand not a Token"); - const StringRef &Mnemonic = Op0.getToken(); + StringRef Mnemonic = Op0.getToken(); if (Mnemonic == "add" || Mnemonic == "stmfd" || Mnemonic == "str" || @@ -549,19 +619,23 @@ bool ARMAsmParser::MatchInstruction(SmallVectorImpl &Operands, return true; } -// Parse a arm instruction operand. For now this parses the operand regardless -// of the mnemonic. -bool ARMAsmParser::ParseOperand(ARMOperand &Op) { +/// Parse a arm instruction operand. For now this parses the operand regardless +/// of the mnemonic. +bool ARMAsmParser::ParseOperand(OwningPtr &Op) { + SMLoc S, E; + switch (getLexer().getKind()) { case AsmToken::Identifier: - if (!ParseRegister(Op)) + if (!MaybeParseRegister(Op, true)) return false; // 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; + S = Parser.getTok().getLoc(); if (getParser().ParseExpression(IdVal)) return true; - Op = ARMOperand::CreateImm(IdVal); + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + ARMOperand::CreateImm(Op, IdVal, S, E); return false; case AsmToken::LBrac: return ParseMemory(Op); @@ -570,45 +644,43 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) { case AsmToken::Hash: // #42 -> immediate. // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate - getLexer().Lex(); + S = Parser.getTok().getLoc(); + Parser.Lex(); const MCExpr *ImmVal; if (getParser().ParseExpression(ImmVal)) return true; - Op = ARMOperand::CreateImm(ImmVal); + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + ARMOperand::CreateImm(Op, ImmVal, S, E); return false; default: - return Error(getLexer().getTok().getLoc(), "unexpected token in operand"); + return Error(Parser.getTok().getLoc(), "unexpected token in operand"); } } -// Parse an arm instruction mnemonic followed by its operands. -bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { - SmallVector Operands; - - Operands.push_back(ARMOperand::CreateToken(Name)); +/// Parse an arm instruction mnemonic followed by its operands. +bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl &Operands) { + OwningPtr Op; + ARMOperand::CreateToken(Op, Name, NameLoc); + + Operands.push_back(Op.take()); - SMLoc Loc = getLexer().getTok().getLoc(); if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. - Operands.push_back(ARMOperand()); - if (ParseOperand(Operands.back())) - return true; + OwningPtr Op; + if (ParseOperand(Op)) return true; + Operands.push_back(Op.take()); while (getLexer().is(AsmToken::Comma)) { - getLexer().Lex(); // Eat the comma. + Parser.Lex(); // Eat the comma. // Parse and remember the operand. - Operands.push_back(ARMOperand()); - if (ParseOperand(Operands.back())) - return true; + if (ParseOperand(Op)) return true; + Operands.push_back(Op.take()); } } - if (!MatchInstruction(Operands, Inst)) - return false; - - Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented"); - return true; + return false; } /// ParseDirective parses the arm specific directives @@ -636,7 +708,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { if (getParser().ParseExpression(Value)) return true; - getParser().getStreamer().EmitValue(Value, Size); + getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/); if (getLexer().is(AsmToken::EndOfStatement)) break; @@ -644,11 +716,11 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { // FIXME: Improve diagnostic. if (getLexer().isNot(AsmToken::Comma)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); } } - getLexer().Lex(); + Parser.Lex(); return false; } @@ -657,7 +729,7 @@ bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); // TODO: set thumb mode // TODO: tell the MC streamer the mode @@ -668,15 +740,15 @@ bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) { /// ParseDirectiveThumbFunc /// ::= .thumbfunc symbol_name bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.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. + StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier(); + Parser.Lex(); // Consume the identifier token. if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(L, "unexpected token in directive"); - getLexer().Lex(); + Parser.Lex(); // TODO: mark symbol as a thumb symbol // getParser().getStreamer().Emit???(); @@ -686,25 +758,20 @@ bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) { /// ParseDirectiveSyntax /// ::= .syntax unified | divided bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.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; - } + StringRef Mode = Tok.getString(); + if (Mode == "unified" || Mode == "UNIFIED") + Parser.Lex(); + else if (Mode == "divided" || Mode == "DIVIDED") + Parser.Lex(); 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(); + return Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Parser.Lex(); // TODO tell the MC streamer the mode // getParser().getStreamer().Emit???(); @@ -714,33 +781,31 @@ bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) { /// ParseDirectiveCode /// ::= .code 16 | 32 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { - const AsmToken &Tok = getLexer().getTok(); + const AsmToken &Tok = Parser.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; - } + int64_t Val = Parser.getTok().getIntVal(); + if (Val == 16) + Parser.Lex(); + else if (Val == 32) + Parser.Lex(); 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(); + return Error(Parser.getTok().getLoc(), "unexpected token in directive"); + Parser.Lex(); // TODO tell the MC streamer the mode // getParser().getStreamer().Emit???(); return false; } -// Force static initialization. +extern "C" void LLVMInitializeARMAsmLexer(); + +/// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterAsmParser X(TheARMTarget); RegisterAsmParser Y(TheThumbTarget); + LLVMInitializeARMAsmLexer(); }