diff options
Diffstat (limited to 'lib/Target/X86/AsmParser')
| -rw-r--r-- | lib/Target/X86/AsmParser/Makefile | 1 | ||||
| -rw-r--r-- | lib/Target/X86/AsmParser/X86AsmLexer.cpp | 118 | ||||
| -rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 119 |
3 files changed, 215 insertions, 23 deletions
diff --git a/lib/Target/X86/AsmParser/Makefile b/lib/Target/X86/AsmParser/Makefile index 288b985daa28d..25fb0a2836dba 100644 --- a/lib/Target/X86/AsmParser/Makefile +++ b/lib/Target/X86/AsmParser/Makefile @@ -8,7 +8,6 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMX86AsmParser -CXXFLAGS = -fno-rtti # Hack: we need to include 'main' x86 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/X86/AsmParser/X86AsmLexer.cpp b/lib/Target/X86/AsmParser/X86AsmLexer.cpp index 1a62044a60ef8..a58f58e033254 100644 --- a/lib/Target/X86/AsmParser/X86AsmLexer.cpp +++ b/lib/Target/X86/AsmParser/X86AsmLexer.cpp @@ -7,8 +7,11 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Target/TargetAsmLexer.h" #include "llvm/Target/TargetRegistry.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "X86.h" @@ -19,18 +22,119 @@ namespace { class X86AsmLexer : public TargetAsmLexer { const MCAsmInfo &AsmInfo; + + bool tentativeIsValid; + AsmToken tentativeToken; + + const AsmToken &lexTentative() { + tentativeToken = getLexer()->Lex(); + tentativeIsValid = true; + return tentativeToken; + } + + const AsmToken &lexDefinite() { + if(tentativeIsValid) { + tentativeIsValid = false; + return tentativeToken; + } + else { + return getLexer()->Lex(); + } + } + + AsmToken LexTokenATT(); + AsmToken LexTokenIntel(); protected: - AsmToken LexToken(); + AsmToken LexToken() { + if (!Lexer) { + SetError(SMLoc(), "No MCAsmLexer installed"); + return AsmToken(AsmToken::Error, "", 0); + } + + switch (AsmInfo.getAssemblerDialect()) { + default: + SetError(SMLoc(), "Unhandled dialect"); + return AsmToken(AsmToken::Error, "", 0); + case 0: + return LexTokenATT(); + case 1: + return LexTokenIntel(); + } + } public: X86AsmLexer(const Target &T, const MCAsmInfo &MAI) - : TargetAsmLexer(T), AsmInfo(MAI) { + : TargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) { } }; } -AsmToken X86AsmLexer::LexToken() { - return AsmToken(AsmToken::Error, "", 0); +static unsigned MatchRegisterName(StringRef Name); + +AsmToken X86AsmLexer::LexTokenATT() { + const AsmToken lexedToken = lexDefinite(); + + switch (lexedToken.getKind()) { + default: + return AsmToken(lexedToken); + case AsmToken::Error: + SetError(Lexer->getErrLoc(), Lexer->getErr()); + return AsmToken(lexedToken); + case AsmToken::Percent: + { + const AsmToken &nextToken = lexTentative(); + if (nextToken.getKind() == AsmToken::Identifier) { + unsigned regID = MatchRegisterName(nextToken.getString()); + + if (regID) { + lexDefinite(); + + StringRef regStr(lexedToken.getString().data(), + lexedToken.getString().size() + + nextToken.getString().size()); + + return AsmToken(AsmToken::Register, + regStr, + static_cast<int64_t>(regID)); + } + else { + return AsmToken(lexedToken); + } + } + else { + return AsmToken(lexedToken); + } + } + } +} + +AsmToken X86AsmLexer::LexTokenIntel() { + const AsmToken &lexedToken = lexDefinite(); + + switch(lexedToken.getKind()) { + default: + return AsmToken(lexedToken); + case AsmToken::Error: + SetError(Lexer->getErrLoc(), Lexer->getErr()); + return AsmToken(lexedToken); + case AsmToken::Identifier: + { + std::string upperCase = lexedToken.getString().str(); + std::string lowerCase = LowercaseString(upperCase); + StringRef lowerRef(lowerCase); + + unsigned regID = MatchRegisterName(lowerRef); + + if (regID) { + return AsmToken(AsmToken::Register, + lexedToken.getString(), + static_cast<int64_t>(regID)); + } + else { + return AsmToken(lexedToken); + } + } + } } extern "C" void LLVMInitializeX86AsmLexer() { @@ -38,6 +142,6 @@ extern "C" void LLVMInitializeX86AsmLexer() { RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target); } -//#define REGISTERS_ONLY -//#include "../X86GenAsmMatcher.inc" -//#undef REGISTERS_ONLY +#define REGISTERS_ONLY +#include "X86GenAsmMatcher.inc" +#undef REGISTERS_ONLY diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 7a9218e743c15..84d7bb7a6f3c3 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -10,6 +10,7 @@ #include "llvm/Target/TargetAsmParser.h" #include "X86.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" @@ -67,7 +68,7 @@ public: /// @name Auto-generated Match Functions /// { -static unsigned MatchRegisterName(const StringRef &Name); +static unsigned MatchRegisterName(StringRef Name); /// } @@ -172,8 +173,25 @@ struct X86Operand : public MCParsedAsmOperand { bool isMem() const { return Kind == Memory; } + bool isAbsMem() const { + return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && + !getMemIndexReg() && getMemScale() == 1; + } + + bool isNoSegMem() const { + return Kind == Memory && !getMemSegReg(); + } + bool isReg() const { return Kind == Register; } + void addExpr(MCInst &Inst, const MCExpr *Expr) const { + // Add as immediates when possible. + if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + else + Inst.addOperand(MCOperand::CreateExpr(Expr)); + } + void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -181,26 +199,35 @@ struct X86Operand : public MCParsedAsmOperand { void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateExpr(getImm())); + addExpr(Inst, getImm()); } void addImmSExt8Operands(MCInst &Inst, unsigned N) const { // FIXME: Support user customization of the render method. assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateExpr(getImm())); + addExpr(Inst, getImm()); } void addMemOperands(MCInst &Inst, unsigned N) const { - assert((N == 4 || N == 5) && "Invalid number of operands!"); - + assert((N == 5) && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); Inst.addOperand(MCOperand::CreateImm(getMemScale())); Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); + addExpr(Inst, getMemDisp()); + Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); + } + + void addAbsMemOperands(MCInst &Inst, unsigned N) const { + assert((N == 1) && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + } - // FIXME: What a hack. - if (N == 5) - Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); + void addNoSegMemOperands(MCInst &Inst, unsigned N) const { + assert((N == 4) && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); + Inst.addOperand(MCOperand::CreateImm(getMemScale())); + Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); + addExpr(Inst, getMemDisp()); } static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { @@ -222,10 +249,24 @@ struct X86Operand : public MCParsedAsmOperand { return Res; } + /// Create an absolute memory operand. + static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, + SMLoc EndLoc) { + X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc); + Res->Mem.SegReg = 0; + Res->Mem.Disp = Disp; + Res->Mem.BaseReg = 0; + Res->Mem.IndexReg = 0; + Res->Mem.Scale = 1; + return Res; + } + + /// Create a generalized memory operand. static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) { - // We should never just have a displacement, that would be an immediate. + // We should never just have a displacement, that should be parsed as an + // absolute memory operand. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); // The scale should always be one of {1,2,4,8}. @@ -259,6 +300,42 @@ bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, // FIXME: Validate register for the current architecture; we have to do // validation later, so maybe there is no need for this here. RegNo = MatchRegisterName(Tok.getString()); + + // Parse %st(1) and "%st" as "%st(0)" + if (RegNo == 0 && Tok.getString() == "st") { + RegNo = X86::ST0; + EndLoc = Tok.getLoc(); + Parser.Lex(); // Eat 'st' + + // Check to see if we have '(4)' after %st. + if (getLexer().isNot(AsmToken::LParen)) + return false; + // Lex the paren. + getParser().Lex(); + + const AsmToken &IntTok = Parser.getTok(); + if (IntTok.isNot(AsmToken::Integer)) + return Error(IntTok.getLoc(), "expected stack index"); + switch (IntTok.getIntVal()) { + case 0: RegNo = X86::ST0; break; + case 1: RegNo = X86::ST1; break; + case 2: RegNo = X86::ST2; break; + case 3: RegNo = X86::ST3; break; + case 4: RegNo = X86::ST4; break; + case 5: RegNo = X86::ST5; break; + case 6: RegNo = X86::ST6; break; + case 7: RegNo = X86::ST7; break; + default: return Error(IntTok.getLoc(), "invalid stack index"); + } + + if (getParser().Lex().isNot(AsmToken::RParen)) + return Error(Parser.getTok().getLoc(), "expected ')'"); + + EndLoc = Tok.getLoc(); + Parser.Lex(); // Eat ')' + return false; + } + if (RegNo == 0) return Error(Tok.getLoc(), "invalid register name"); @@ -300,8 +377,8 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() { // We have to disambiguate a parenthesized expression "(4+5)" from the start // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The - // only way to do this without lookahead is to eat the ( and see what is after - // it. + // only way to do this without lookahead is to eat the '(' and see what is + // after it. const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); if (getLexer().isNot(AsmToken::LParen)) { SMLoc ExprEnd; @@ -312,7 +389,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() { if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. if (SegReg == 0) - return X86Operand::CreateImm(Disp, MemStart, ExprEnd); + return X86Operand::CreateMem(Disp, MemStart, ExprEnd); return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); } @@ -339,7 +416,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() { if (getLexer().isNot(AsmToken::LParen)) { // Unless we have a segment register, treat this as an immediate. if (SegReg == 0) - return X86Operand::CreateImm(Disp, LParenLoc, ExprEnd); + return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd); return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd); } @@ -424,8 +501,20 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() { bool X86ATTAsmParser:: ParseInstruction(const StringRef &Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - - Operands.push_back(X86Operand::CreateToken(Name, NameLoc)); + // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to + // represent alternative syntaxes in the .td file, without requiring + // instruction duplication. + StringRef PatchedName = StringSwitch<StringRef>(Name) + .Case("sal", "shl") + .Case("salb", "shlb") + .Case("sall", "shll") + .Case("salq", "shlq") + .Case("salw", "shlw") + .Case("repe", "rep") + .Case("repz", "rep") + .Case("repnz", "repne") + .Default(Name); + Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); if (getLexer().isNot(AsmToken::EndOfStatement)) { |
