Split the TargetAsmParser "ParseInstruction" interface in half:

the new ParseInstruction method just parses and returns a list of
target operands.  A new MatchInstruction interface is used to
turn the operand list into an MCInst.

This requires new/deleting all the operands, but it also gives 
targets the ability to use polymorphic operands if they want to. 


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93469 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-01-14 22:21:20 +00:00
parent 74a265686d
commit 9898671a74
6 changed files with 77 additions and 52 deletions

View File

@ -17,6 +17,8 @@ class StringRef;
class Target; class Target;
class SMLoc; class SMLoc;
class AsmToken; class AsmToken;
class MCParsedAsmOperand;
template <typename T> class SmallVectorImpl;
/// TargetAsmParser - Generic interface to target specific assembly parsers. /// TargetAsmParser - Generic interface to target specific assembly parsers.
class TargetAsmParser { class TargetAsmParser {
@ -43,10 +45,11 @@ public:
// //
/// \param AP - The current parser object. /// \param AP - The current parser object.
/// \param Name - The instruction name. /// \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. /// \return True on failure.
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
MCInst &Inst) = 0; SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
/// ParseDirective - Parse a target specific assembler directive /// ParseDirective - Parse a target specific assembler directive
/// ///
@ -59,6 +62,14 @@ public:
/// ///
/// \param ID - the identifier token of the directive. /// \param ID - the identifier token of the directive.
virtual bool ParseDirective(AsmToken DirectiveID) = 0; 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<MCParsedAsmOperand*> &Operands,
MCInst &Inst) = 0;
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -79,7 +79,7 @@ private:
/// @name Auto-generated Match Functions /// @name Auto-generated Match Functions
/// { /// {
bool MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCInst &Inst); MCInst &Inst);
/// MatchRegisterName - Match the given string to a register name and return /// MatchRegisterName - Match the given string to a register name and return
@ -96,7 +96,7 @@ public:
: TargetAsmParser(T), Parser(_Parser) {} : TargetAsmParser(T), Parser(_Parser) {}
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
MCInst &Inst); SmallVectorImpl<MCParsedAsmOperand*> &Operands);
virtual bool ParseDirective(AsmToken DirectiveID); 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. /// A hack to allow some testing, to be replaced by a real table gen version.
bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, bool ARMAsmParser::
MCInst &Inst) { MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
struct ARMOperand Op0 = Operands[0]; MCInst &Inst) {
ARMOperand &Op0 = *(ARMOperand*)Operands[0];
assert(Op0.Kind == ARMOperand::Token && "First operand not a Token"); assert(Op0.Kind == ARMOperand::Token && "First operand not a Token");
const StringRef &Mnemonic = Op0.getToken(); const StringRef &Mnemonic = Op0.getToken();
if (Mnemonic == "add" || if (Mnemonic == "add" ||
@ -581,33 +582,26 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
/// Parse an arm instruction mnemonic followed by its operands. /// Parse an arm instruction mnemonic followed by its operands.
bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc, bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc,
MCInst &Inst) { SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SmallVector<ARMOperand, 7> Operands; Operands.push_back(new ARMOperand(ARMOperand::CreateToken(Name)));
Operands.push_back(ARMOperand::CreateToken(Name));
SMLoc Loc = getLexer().getTok().getLoc(); SMLoc Loc = getLexer().getTok().getLoc();
if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand. // Read the first operand.
Operands.push_back(ARMOperand()); ARMOperand Op;
if (ParseOperand(Operands.back())) if (ParseOperand(Op)) return true;
return true; Operands.push_back(new ARMOperand(Op));
while (getLexer().is(AsmToken::Comma)) { while (getLexer().is(AsmToken::Comma)) {
getLexer().Lex(); // Eat the comma. getLexer().Lex(); // Eat the comma.
// Parse and remember the operand. // Parse and remember the operand.
Operands.push_back(ARMOperand()); if (ParseOperand(Op)) return true;
if (ParseOperand(Operands.back())) Operands.push_back(new ARMOperand(Op));
return true;
} }
} }
if (!MatchInstruction(Operands, Inst)) return false;
return false;
Error(Loc, "ARMAsmParser::ParseInstruction only partly implemented");
return true;
} }
/// ParseDirective parses the arm specific directives /// ParseDirective parses the arm specific directives

View File

@ -7,6 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Target/TargetAsmParser.h"
#include "X86.h" #include "X86.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
@ -47,7 +48,7 @@ private:
/// @name Auto-generated Match Functions /// @name Auto-generated Match Functions
/// { /// {
bool MatchInstruction(SmallVectorImpl<X86Operand> &Operands, bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCInst &Inst); MCInst &Inst);
/// MatchRegisterName - Match the given string to a register name, or 0 if /// MatchRegisterName - Match the given string to a register name, or 0 if
@ -61,7 +62,7 @@ public:
: TargetAsmParser(T), Parser(_Parser) {} : TargetAsmParser(T), Parser(_Parser) {}
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc, virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
MCInst &Inst); SmallVectorImpl<MCParsedAsmOperand*> &Operands);
virtual bool ParseDirective(AsmToken DirectiveID); virtual bool ParseDirective(AsmToken DirectiveID);
}; };
@ -402,11 +403,11 @@ bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
return false; return false;
} }
bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, bool X86ATTAsmParser::
SMLoc NameLoc, MCInst &Inst) { ParseInstruction(const StringRef &Name, SMLoc NameLoc,
SmallVector<X86Operand, 8> Operands; SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Operands.push_back(X86Operand::CreateToken(Name)); Operands.push_back(new X86Operand(X86Operand::CreateToken(Name)));
SMLoc Loc = getLexer().getTok().getLoc(); SMLoc Loc = getLexer().getTok().getLoc();
if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getLexer().isNot(AsmToken::EndOfStatement)) {
@ -414,31 +415,27 @@ bool X86ATTAsmParser::ParseInstruction(const StringRef &Name,
// Parse '*' modifier. // Parse '*' modifier.
if (getLexer().is(AsmToken::Star)) { if (getLexer().is(AsmToken::Star)) {
getLexer().Lex(); // Eat the star. getLexer().Lex(); // Eat the star.
Operands.push_back(X86Operand::CreateToken("*")); Operands.push_back(new X86Operand(X86Operand::CreateToken("*")));
} }
// Read the first operand. // Read the first operand.
Operands.push_back(X86Operand()); X86Operand Op;
if (ParseOperand(Operands.back())) if (ParseOperand(Op))
return true; return true;
Operands.push_back(new X86Operand(Op));
while (getLexer().is(AsmToken::Comma)) { while (getLexer().is(AsmToken::Comma)) {
getLexer().Lex(); // Eat the comma. getLexer().Lex(); // Eat the comma.
// Parse and remember the operand. // Parse and remember the operand.
Operands.push_back(X86Operand()); if (ParseOperand(Op))
if (ParseOperand(Operands.back()))
return true; return true;
Operands.push_back(new X86Operand(Op));
} }
} }
if (!MatchInstruction(Operands, Inst)) return false;
return false;
// FIXME: We should give nicer diagnostics about the exact failure.
Error(Loc, "unrecognized instruction");
return true;
} }
bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) { bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {

View File

@ -44,7 +44,7 @@ void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg,
/// ReturnError - Set the error to the specified string at the specified /// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return AsmToken::Error. /// location. This is defined to always return AsmToken::Error.
AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { 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)); return AsmToken(AsmToken::Error, StringRef(Loc, 0));
} }

View File

@ -18,6 +18,7 @@
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
#include "llvm/MC/MCParsedAsmOperand.h"
#include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
@ -710,16 +711,34 @@ bool AsmParser::ParseStatement() {
return false; return false;
} }
MCInst Inst;
if (getTargetParser().ParseInstruction(IDVal, IDLoc, Inst)) SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands))
// FIXME: Leaking ParsedOperands on failure.
return true; return true;
if (Lexer.isNot(AsmToken::EndOfStatement)) if (Lexer.isNot(AsmToken::EndOfStatement))
// FIXME: Leaking ParsedOperands on failure.
return TokError("unexpected token in argument list"); return TokError("unexpected token in argument list");
// Eat the end of statement marker. // Eat the end of statement marker.
Lexer.Lex(); 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. // Instruction is good, process it.
Out.EmitInstruction(Inst); Out.EmitInstruction(Inst);

View File

@ -961,8 +961,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
CvtOS << "static bool ConvertToMCInst(ConversionKind Kind, MCInst &Inst, " CvtOS << "static bool ConvertToMCInst(ConversionKind Kind, MCInst &Inst, "
<< "unsigned Opcode,\n" << "unsigned Opcode,\n"
<< " SmallVectorImpl<" << " const SmallVectorImpl<MCParsedAsmOperand*"
<< Target.getName() << "Operand> &Operands) {\n"; << "> &Operands) {\n";
CvtOS << " Inst.setOpcode(Opcode);\n"; CvtOS << " Inst.setOpcode(Opcode);\n";
CvtOS << " switch (Kind) {\n"; CvtOS << " switch (Kind) {\n";
CvtOS << " default:\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 << "// Unified function for converting operants to MCInst instances.\n\n";
OS << "enum ConversionKind {\n"; OS << "enum ConversionKind {\n";
// TargetOperandClass - This is the target's operand class, like X86Operand.
std::string TargetOperandClass = Target.getName() + "Operand";
for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(), for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) { ie = Infos.end(); it != ie; ++it) {
InstructionInfo &II = **it; InstructionInfo &II = **it;
@ -1050,8 +1053,9 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
CvtOS << " Operands[" << MIOperandList[i].second CvtOS << " ((" << TargetOperandClass << "*)Operands["
<< "]." << Op.Class->RenderMethod << MIOperandList[i].second
<< "])->" << Op.Class->RenderMethod
<< "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
CurIndex += Op.OperandInfo->MINumOperands; CurIndex += Op.OperandInfo->MINumOperands;
} }
@ -1111,8 +1115,9 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target,
static void EmitClassifyOperand(CodeGenTarget &Target, static void EmitClassifyOperand(CodeGenTarget &Target,
AsmMatcherInfo &Info, AsmMatcherInfo &Info,
raw_ostream &OS) { raw_ostream &OS) {
OS << "static MatchClassKind ClassifyOperand(" OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
<< Target.getName() << "Operand &Operand) {\n"; << " " << Target.getName() << "Operand &Operand = *("
<< Target.getName() << "Operand*)GOp;\n";
// Classify tokens. // Classify tokens.
OS << " if (Operand.isToken())\n"; OS << " if (Operand.isToken())\n";
@ -1467,9 +1472,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size()); MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size());
OS << "bool " << Target.getName() << ClassName OS << "bool " << Target.getName() << ClassName
<< "::MatchInstruction(" << "::\nMatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> "
<< "SmallVectorImpl<" << Target.getName() << "Operand> &Operands, " "&Operands,\n MCInst &Inst) {\n";
<< "MCInst &Inst) {\n";
// Emit the static match table; unused classes get initalized to 0 which is // Emit the static match table; unused classes get initalized to 0 which is
// guaranteed to be InvalidMatchClass. // guaranteed to be InvalidMatchClass.