Split the TargetAsmParser "ParseInstruction" interface in half:
authorChris Lattner <sabre@nondot.org>
Thu, 14 Jan 2010 22:21:20 +0000 (22:21 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 14 Jan 2010 22:21:20 +0000 (22:21 +0000)
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

include/llvm/Target/TargetAsmParser.h
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/X86/AsmParser/X86AsmParser.cpp
tools/llvm-mc/AsmLexer.cpp
tools/llvm-mc/AsmParser.cpp
utils/TableGen/AsmMatcherEmitter.cpp

index a265610f2f2a61444f5c8f395940a7254054dd84..1d3da8b2c62cb2aee72385f61327d241a33d3e61 100644 (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
index 9288384508c626b7456d79faac61cc8153a66030..132738efdfb3d92890d31e7324fcc613ad5d3cf8 100644 (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
index d431aa67957890d7f46596282f77ad2a7c82f568..c4ae5d220b3266de137f12ab4ca94ea93acd8ca0 100644 (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) {
index 99055c6855ed05abcf2ff2ceb36f6f917f066edd..ba0d247d46cd4772dacf31a359aee6f537f39afb 100644 (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));
 }
 
index 4ef3a7fc3559ef99826e208cf895446c0bca371f..bd0e0e259dcdfdfae2cdedd79e8549c4cccefe05 100644 (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);
   
index 3eac9d201b72bd441e45393a55b75108756ac672..019908bd599b234a1b0503d154ccfd5c0af291a6 100644 (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.