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 SMLoc;
class AsmToken;
class MCParsedAsmOperand;
template <typename T> 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<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &Operands,
MCInst &Inst) = 0;
};
} // End llvm namespace

View File

@ -79,7 +79,7 @@ private:
/// @name Auto-generated Match Functions
/// {
bool MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<ARMOperand> &Operands,
MCInst &Inst) {
struct ARMOperand Op0 = Operands[0];
bool ARMAsmParser::
MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &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<ARMOperand, 7> Operands;
Operands.push_back(ARMOperand::CreateToken(Name));
SmallVectorImpl<MCParsedAsmOperand*> &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

View File

@ -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<X86Operand> &Operands,
bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &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<MCParsedAsmOperand*> &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<X86Operand, 8> Operands;
bool X86ATTAsmParser::
ParseInstruction(const StringRef &Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &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) {

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
/// 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));
}

View File

@ -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<MCParsedAsmOperand*, 8> 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);

View File

@ -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<MCParsedAsmOperand*"
<< "> &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<InstructionInfo*>::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<MCParsedAsmOperand*> "
"&Operands,\n MCInst &Inst) {\n";
// Emit the static match table; unused classes get initalized to 0 which is
// guaranteed to be InvalidMatchClass.