Match X86 register names to number.
authorDaniel Dunbar <daniel@zuster.org>
Wed, 29 Jul 2009 00:02:19 +0000 (00:02 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 29 Jul 2009 00:02:19 +0000 (00:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77404 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/Target.td
lib/Target/X86/AsmParser/X86AsmParser.cpp
lib/Target/X86/X86.td
utils/TableGen/AsmMatcherEmitter.cpp
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/CodeGenTarget.h

index 94ae94a14b57e2808b683a46c03e3d770a13cf33..bdb5abb517add869a903f53bb00d67e18fe36946 100644 (file)
@@ -410,6 +410,27 @@ def COPY_TO_REGCLASS : Instruction {
   let isAsCheapAsAMove = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// AsmParser - This class can be implemented by targets that wish to implement 
+// .s file parsing.
+//
+// Subtargets can have multiple different assembly parsers (e.g. AT&T vs Intel 
+// syntax on X86 for example).
+//
+class AsmParser {
+  // AsmWriterClassName - This specifies the suffix to use for the asmwriter
+  // class.  Generated AsmWriter classes are always prefixed with the target
+  // name.
+  string AsmParserClassName  = "AsmParser";
+  // Variant - AsmParsers can be of multiple different variants.  Variants are
+  // used to support targets that need to parser multiple formats for the 
+  // assembly language.
+  int Variant = 0;
+}
+def DefaultAsmParser : AsmParser;
+
+
 //===----------------------------------------------------------------------===//
 // AsmWriter - This class can be implemented by targets that need to customize
 // the format of the .s file writer.
@@ -445,6 +466,9 @@ class Target {
   // InstructionSet - Instruction set description for this target.
   InstrInfo InstructionSet;
 
+  // AssemblyParsers - The AsmParser instances available for this target.
+  list<AsmParser> AssemblyParsers = [DefaultAsmParser];
+
   // AssemblyWriters - The AsmWriter instances available for this target.
   list<AsmWriter> AssemblyWriters = [DefaultAsmWriter];
 }
index 12e9f937fc2ce097705b45883754c4300c0f2c73..f172c1d22aab958be5d805e7aad4912fbf7f7549 100644 (file)
@@ -42,6 +42,13 @@ private:
   bool ParseOperand(X86Operand &Op);
 
   bool ParseMemOperand(X86Operand &Op);
+  
+  /// @name Auto-generated Match Functions
+  /// {  
+
+  bool MatchRegisterName(const StringRef &Name, unsigned &RegNo);
+
+  /// }
 
 public:
   X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
@@ -118,10 +125,17 @@ struct X86Operand {
 //
 
 bool X86ATTAsmParser::ParseRegister(X86Operand &Op) {
-  assert(getLexer().is(AsmToken::Register) && "Invalid token kind!");
+  AsmToken Tok = getLexer().getTok();
+  assert(Tok.is(AsmToken::Register) && "Invalid token kind!");
 
-  // FIXME: Decode register number.
-  Op = X86Operand::CreateReg(123);
+  // FIXME: Validate register for the current architecture; we have to do
+  // validation later, so maybe there is no need for this here.
+  unsigned RegNo;
+  assert(Tok.getString().startswith("%") && "Invalid register name!");
+  if (MatchRegisterName(Tok.getString().substr(1), RegNo))
+    return Error(Tok.getLoc(), "invalid register name");
+
+  Op = X86Operand::CreateReg(RegNo);
   getLexer().Lex(); // Eat register token.
 
   return false;
@@ -308,3 +322,5 @@ extern "C" void LLVMInitializeX86AsmParser() {
   RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target);
   RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
 }
+
+#include "X86GenAsmMatcher.inc"
index 47861d5a67dc973279b9bb3d399ad8031410d074..effbddc8501431e9ae2ce61dbe460e43fab60a90 100644 (file)
@@ -178,6 +178,12 @@ include "X86CallingConv.td"
 // Assembly Printers
 //===----------------------------------------------------------------------===//
 
+// Currently the X86 assembly parser only supports ATT syntax.
+def ATTAsmParser : AsmParser {
+  string AsmParserClassName  = "ATTAsmParser";
+  int Variant = 0;
+}
+
 // The X86 target supports two different syntaxes for emitting machine code.
 // This is controlled by the -x86-asm-syntax={att|intel}
 def ATTAsmWriter : AsmWriter {
@@ -189,10 +195,11 @@ def IntelAsmWriter : AsmWriter {
   int Variant = 1;
 }
 
-
 def X86 : Target {
   // Information about the instructions...
   let InstructionSet = X86InstrInfo;
 
+  let AssemblyParsers = [ATTAsmParser];
+
   let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
 }
index 1d4ad0947aee3d852abe7d80726b8bd65ce902d6..d00ff202ad00831b3708289533fd43481c58d844 100644 (file)
@@ -20,17 +20,17 @@ using namespace llvm;
 void AsmMatcherEmitter::run(raw_ostream &OS) {
   CodeGenTarget Target;
   const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
+  Record *AsmParser = Target.getAsmParser();
+  std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
 
   std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");
 
   EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
-  OS << "namespace llvm {\n\n";
 
   // Emit the function to match a register name to number.
 
-  if (!Namespace.empty())
-    OS << "namespace " << Namespace << " {\n";
-  OS << "bool MatchRegisterName(const std::string &Name, unsigned &RegNo) {\n";
+  OS << "bool " << Target.getName() << ClassName
+     << "::MatchRegisterName(const StringRef &Name, unsigned &RegNo) {\n";
 
   // FIXME: TableGen should have a fast string matcher generator.
   for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
@@ -44,8 +44,4 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
   }
   OS << "  return true;\n";
   OS << "}\n";
-
-  if (!Namespace.empty())
-    OS << "}\n";
-  OS << "} // End llvm namespace \n";
 }
index ed703be944ac6f2e2b128da5744847beb278d217..0849d4f832fd517d550d016e10f3a0127afff773 100644 (file)
 #include <algorithm>
 using namespace llvm;
 
+static cl::opt<unsigned>
+AsmParserNum("asmparsernum", cl::init(0),
+             cl::desc("Make -gen-asm-parser emit assembly parser #N"));
+
 static cl::opt<unsigned>
 AsmWriterNum("asmwriternum", cl::init(0),
              cl::desc("Make -gen-asm-writer emit assembly writer #N"));
@@ -133,6 +137,15 @@ Record *CodeGenTarget::getInstructionSet() const {
   return TargetRec->getValueAsDef("InstructionSet");
 }
 
+/// getAsmParser - Return the AssemblyParser definition for this target.
+///
+Record *CodeGenTarget::getAsmParser() const {
+  std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
+  if (AsmParserNum >= LI.size())
+    throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!";
+  return LI[AsmParserNum];
+}
+
 /// getAsmWriter - Return the AssemblyWriter definition for this target.
 ///
 Record *CodeGenTarget::getAsmWriter() const {
index 0ec9955814603dc8dd632cc3fdb564ab632fa94d..e763795ce0be92d4d45ad84e2ec58e8dc233ca22 100644 (file)
@@ -87,6 +87,10 @@ public:
   ///
   Record *getInstructionSet() const;
 
+  /// getAsmParser - Return the AssemblyParser definition for this target.
+  ///
+  Record *getAsmParser() const;
+
   /// getAsmWriter - Return the AssemblyWriter definition for this target.
   ///
   Record *getAsmWriter() const;