diff --git a/include/llvm/Target/TargetAsmParser.h b/include/llvm/Target/TargetAsmParser.h index a265610f2f2..1d3da8b2c62 100644 --- a/include/llvm/Target/TargetAsmParser.h +++ b/include/llvm/Target/TargetAsmParser.h @@ -17,6 +17,8 @@ class StringRef; class Target; class SMLoc; class AsmToken; +class MCParsedAsmOperand; +template class SmallVectorImpl; /// TargetAsmParser - Generic interface to target specific assembly parsers. class TargetAsmParser { @@ -43,10 +45,11 @@ public: // /// \param AP - The current parser object. /// \param Name - The instruction name. - /// \param Inst [out] - On success, the parsed instruction. + /// \param Operands [out] - The list of parsed operands, this returns + /// ownership of them to the caller. /// \return True on failure. virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, - MCInst &Inst) = 0; + SmallVectorImpl &Operands) = 0; /// ParseDirective - Parse a target specific assembler directive /// @@ -59,6 +62,14 @@ public: /// /// \param ID - the identifier token of the directive. virtual bool ParseDirective(AsmToken DirectiveID) = 0; + + /// MatchInstruction - Recognize a series of operands of a parsed instruction + /// as an actual MCInst. This returns false and fills in Inst on success and + /// returns true on failure to match. + virtual bool + MatchInstruction(const SmallVectorImpl &Operands, + MCInst &Inst) = 0; + }; } // End llvm namespace diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 9288384508c..132738efdfb 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -79,7 +79,7 @@ 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 @@ -96,7 +96,7 @@ public: : TargetAsmParser(T), Parser(_Parser) {} virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, - MCInst &Inst); + SmallVectorImpl &Operands); virtual bool ParseDirective(AsmToken DirectiveID); }; @@ -517,9 +517,10 @@ int ARMAsmParser::MatchRegisterName(const StringRef &Name) { } /// 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]; +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(); if (Mnemonic == "add" || @@ -581,33 +582,26 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) { /// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc, - MCInst &Inst) { - SmallVector Operands; - - Operands.push_back(ARMOperand::CreateToken(Name)); + SmallVectorImpl &Operands) { + Operands.push_back(new ARMOperand(ARMOperand::CreateToken(Name))); SMLoc Loc = getLexer().getTok().getLoc(); if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. - Operands.push_back(ARMOperand()); - if (ParseOperand(Operands.back())) - return true; + ARMOperand Op; + if (ParseOperand(Op)) return true; + Operands.push_back(new ARMOperand(Op)); while (getLexer().is(AsmToken::Comma)) { getLexer().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(new ARMOperand(Op)); } } - if (!MatchInstruction(Operands, Inst)) - return false; - - Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented"); - return true; + return false; } /// ParseDirective parses the arm specific directives diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index d431aa67957..c4ae5d220b3 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Target/TargetAsmParser.h" #include "X86.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" @@ -47,7 +48,7 @@ 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, or 0 if @@ -61,7 +62,7 @@ public: : TargetAsmParser(T), Parser(_Parser) {} virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, - MCInst &Inst); + SmallVectorImpl &Operands); virtual bool ParseDirective(AsmToken DirectiveID); }; @@ -402,11 +403,11 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) { return false; } -bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, - SMLoc NameLoc, MCInst &Inst) { - SmallVector Operands; +bool X86ATTAsmParser:: +ParseInstruction(const StringRef &Name, SMLoc NameLoc, + SmallVectorImpl &Operands) { - Operands.push_back(X86Operand::CreateToken(Name)); + Operands.push_back(new X86Operand(X86Operand::CreateToken(Name))); SMLoc Loc = getLexer().getTok().getLoc(); if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -414,31 +415,27 @@ bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, // Parse '*' modifier. if (getLexer().is(AsmToken::Star)) { getLexer().Lex(); // Eat the star. - Operands.push_back(X86Operand::CreateToken("*")); + Operands.push_back(new X86Operand(X86Operand::CreateToken("*"))); } // Read the first operand. - Operands.push_back(X86Operand()); - if (ParseOperand(Operands.back())) + X86Operand Op; + if (ParseOperand(Op)) return true; + Operands.push_back(new X86Operand(Op)); + while (getLexer().is(AsmToken::Comma)) { getLexer().Lex(); // Eat the comma. // Parse and remember the operand. - Operands.push_back(X86Operand()); - if (ParseOperand(Operands.back())) + if (ParseOperand(Op)) return true; + Operands.push_back(new X86Operand(Op)); } } - if (!MatchInstruction(Operands, Inst)) - return false; - - // FIXME: We should give nicer diagnostics about the exact failure. - - Error(Loc, "unrecognized instruction"); - return true; + return false; } bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) { diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp index 99055c6855e..ba0d247d46c 100644 --- a/tools/llvm-mc/AsmLexer.cpp +++ b/tools/llvm-mc/AsmLexer.cpp @@ -44,7 +44,7 @@ void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg, /// ReturnError - Set the error to the specified string at the specified /// location. This is defined to always return AsmToken::Error. AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { - SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); + PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); return AsmToken(AsmToken::Error, StringRef(Loc, 0)); } diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 4ef3a7fc355..bd0e0e259dc 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCParsedAsmOperand.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" @@ -710,16 +711,34 @@ bool AsmParser::ParseStatement() { return false; } - MCInst Inst; - if (getTargetParser().ParseInstruction(IDVal, IDLoc, Inst)) + + SmallVector ParsedOperands; + if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands)) + // FIXME: Leaking ParsedOperands on failure. return true; if (Lexer.isNot(AsmToken::EndOfStatement)) + // FIXME: Leaking ParsedOperands on failure. return TokError("unexpected token in argument list"); // Eat the end of statement marker. Lexer.Lex(); + + MCInst Inst; + + bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst); + + // Free any parsed operands. + for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) + delete ParsedOperands[i]; + + if (MatchFail) { + // FIXME: We should give nicer diagnostics about the exact failure. + Error(IDLoc, "unrecognized instruction"); + return true; + } + // Instruction is good, process it. Out.EmitInstruction(Inst); diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 3eac9d201b7..019908bd599 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -961,8 +961,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, CvtOS << "static bool ConvertToMCInst(ConversionKind Kind, MCInst &Inst, " << "unsigned Opcode,\n" - << " SmallVectorImpl<" - << Target.getName() << "Operand> &Operands) {\n"; + << " const SmallVectorImpl &Operands) {\n"; CvtOS << " Inst.setOpcode(Opcode);\n"; CvtOS << " switch (Kind) {\n"; CvtOS << " default:\n"; @@ -972,6 +972,9 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, OS << "// Unified function for converting operants to MCInst instances.\n\n"; OS << "enum ConversionKind {\n"; + // TargetOperandClass - This is the target's operand class, like X86Operand. + std::string TargetOperandClass = Target.getName() + "Operand"; + for (std::vector::const_iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { InstructionInfo &II = **it; @@ -1050,8 +1053,9 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; - CvtOS << " Operands[" << MIOperandList[i].second - << "]." << Op.Class->RenderMethod + CvtOS << " ((" << TargetOperandClass << "*)Operands[" + << MIOperandList[i].second + << "])->" << Op.Class->RenderMethod << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; CurIndex += Op.OperandInfo->MINumOperands; } @@ -1111,8 +1115,9 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target, static void EmitClassifyOperand(CodeGenTarget &Target, AsmMatcherInfo &Info, raw_ostream &OS) { - OS << "static MatchClassKind ClassifyOperand(" - << Target.getName() << "Operand &Operand) {\n"; + OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n" + << " " << Target.getName() << "Operand &Operand = *(" + << Target.getName() << "Operand*)GOp;\n"; // Classify tokens. OS << " if (Operand.isToken())\n"; @@ -1467,9 +1472,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size()); OS << "bool " << Target.getName() << ClassName - << "::MatchInstruction(" - << "SmallVectorImpl<" << Target.getName() << "Operand> &Operands, " - << "MCInst &Inst) {\n"; + << "::\nMatchInstruction(const SmallVectorImpl " + "&Operands,\n MCInst &Inst) {\n"; // Emit the static match table; unused classes get initalized to 0 which is // guaranteed to be InvalidMatchClass.