From 0e2771f4c4a6e1ffc664eb23487087f824340255 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 29 Jul 2009 00:02:19 +0000 Subject: [PATCH] Match X86 register names to number. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77404 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/Target.td | 24 +++++++++++++++++++++++ lib/Target/X86/AsmParser/X86AsmParser.cpp | 22 ++++++++++++++++++--- lib/Target/X86/X86.td | 9 ++++++++- utils/TableGen/AsmMatcherEmitter.cpp | 12 ++++-------- utils/TableGen/CodeGenTarget.cpp | 13 ++++++++++++ utils/TableGen/CodeGenTarget.h | 4 ++++ 6 files changed, 72 insertions(+), 12 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 94ae94a14b5..bdb5abb517a 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -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 AssemblyParsers = [DefaultAsmParser]; + // AssemblyWriters - The AsmWriter instances available for this target. list AssemblyWriters = [DefaultAsmWriter]; } diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 12e9f937fc2..f172c1d22aa 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -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 X(TheX86_32Target); RegisterAsmParser Y(TheX86_64Target); } + +#include "X86GenAsmMatcher.inc" diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 47861d5a67d..effbddc8501 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -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]; } diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1d4ad0947ae..d00ff202ad0 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -20,17 +20,17 @@ using namespace llvm; void AsmMatcherEmitter::run(raw_ostream &OS) { CodeGenTarget Target; const std::vector &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"; } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index ed703be944a..0849d4f832f 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -22,6 +22,10 @@ #include using namespace llvm; +static cl::opt +AsmParserNum("asmparsernum", cl::init(0), + cl::desc("Make -gen-asm-parser emit assembly parser #N")); + static cl::opt 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 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 { diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 0ec99558146..e763795ce0b 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -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; -- 2.34.1