mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
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. llvm-svn: 93469
This commit is contained in:
parent
953a94cb69
commit
882cb240a6
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user