[llvm] dee70a0 - [TableGen] Generate `getRegClassFromMatchKind()` for AsmMatchers

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 12:55:20 PDT 2026


Author: Alexander Richardson
Date: 2026-08-04T12:55:16-07:00
New Revision: dee70a0fc948ce9060f4225ee5b707af4287e5dc

URL: https://github.com/llvm/llvm-project/commit/dee70a0fc948ce9060f4225ee5b707af4287e5dc
DIFF: https://github.com/llvm/llvm-project/commit/dee70a0fc948ce9060f4225ee5b707af4287e5dc.diff

LOG: [TableGen] Generate `getRegClassFromMatchKind()` for AsmMatchers

This helper can be useful in validateTargetOperandClass to get the
MCRegisterClass for the MCK_* enum.
Migrate the RVY logic to use this new generated function. Checking all
register classes instead of just the RVY ones will marginally slow down
validateTargetOperandClass, but since this is already a slow path it
should not matter.

If multiple RegisterOperands share a ParserMatchClass but map to different
RegisterClasses, omit them from the generated getRegClassFromMatchKind
mapping function. I originally tried to emit an error here, but it turns
out there are many targets that rely on sharing the ParserMatchClass with
different (but similar) RegisterClasses so ignoring them is safer.

Reviewed By: lenary

Pull Request: https://github.com/llvm/llvm-project/pull/200453

Added: 
    llvm/test/TableGen/getRegClassFromMatchKind.td

Modified: 
    llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
    llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
    llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
    llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
    llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
    llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
    llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/utils/TableGen/AsmMatcherEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
index 841907f0e46fd..6e06c82dc2b7a 100644
--- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
+++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCParser/AsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"

diff  --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index 8f7a147dc02e2..b45a2a160167a 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -17,6 +17,7 @@
 #include "llvm/MC/MCParser/AsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"

diff  --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
index 6621bdce4cbce..3d1e37f03e072 100644
--- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
+++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
@@ -20,6 +20,7 @@
 #include "llvm/MC/MCParser/MCAsmParser.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"

diff  --git a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
index 954b515afa9be..3a680cbd5e2da 100644
--- a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
+++ b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
@@ -15,6 +15,7 @@
 #include "llvm/MC/MCParser/AsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/TargetRegistry.h"
 

diff  --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
index bb0ea34651b62..086db07506fea 100644
--- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
+++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
@@ -20,6 +20,7 @@
 #include "llvm/MC/MCParser/AsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"

diff  --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index ebbab6b4828c4..652c4715ec525 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -31,6 +31,7 @@
 #include "llvm/MC/MCParser/MCAsmParserUtils.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"

diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 258239083d3dc..3f87b133181f5 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -20,6 +20,7 @@
 #include "llvm/MC/MCParser/MCAsmParser.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbolELF.h"

diff  --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
index 761cbaaedd22d..44ebabe15415f 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -26,6 +26,7 @@
 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"

diff  --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
index cc58efcd7b005..7d9dcdd3c7dbd 100644
--- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -21,6 +21,7 @@
 #include "llvm/MC/MCParser/MCAsmParser.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 475c73c6f81b2..f30d6fb1d3639 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -26,6 +26,7 @@
 #include "llvm/MC/MCParser/AsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSectionWasm.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"

diff  --git a/llvm/test/TableGen/getRegClassFromMatchKind.td b/llvm/test/TableGen/getRegClassFromMatchKind.td
new file mode 100644
index 0000000000000..fc3506035dc7a
--- /dev/null
+++ b/llvm/test/TableGen/getRegClassFromMatchKind.td
@@ -0,0 +1,170 @@
+// RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s | FileCheck %s --check-prefixes=CHECK,UNIQUE
+// RUN: llvm-tblgen -gen-register-info -I %p/../../include %s -o %t.inc
+// RUN: FileCheck %s --check-prefix=REGINFO-ENUM --input-file=%tEnums.inc
+// RUN: FileCheck %s --check-prefix=REGINFO-DESC --input-file=%tMCDesc.inc
+// RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s -DAMBIGUOUS | FileCheck %s --check-prefixes=CHECK
+
+/// This test verifies that TableGen's AsmMatcherEmitter correctly generates
+/// the target-independent `getRegClassFromMatchKind` mapping function.
+///
+/// It specifically verifies that:
+/// - Explicit named target RegisterClasses (like `RegClass`) are mapped.
+/// - RegisterOperands with custom ParserMatchClass (like `SpecialRegOp`)
+///   are mapped to their underlying RegisterClass (unless there are multiple
+///   uses of the same ParserMatchClass with 
diff erent RegisterClasses).
+/// - RegClassByHwMode (like `HwModeRC`) are NOT mapped.
+/// - Singleton registers (like `Reg` used literally in `bar` instruction)
+///   which generate implicit `MCK_Reg` match classes are NOT mapped.
+/// - Non-register class operands (like the custom immediate `MyImmOp`
+///   in `baz` instruction) are NOT mapped.
+/// - All register classes are covered by the generated function (checking enums)
+
+
+include "llvm/Target/Target.td"
+
+def ArchInstrInfo : InstrInfo { }
+
+def ArchAsmParserVariant : AsmParserVariant {
+  let Variant = 0;
+  let Name = "Arch";
+}
+
+def Arch : Target {
+  let InstructionSet = ArchInstrInfo;
+  let AssemblyParserVariants = [ArchAsmParserVariant];
+}
+
+let Namespace = "Arch" in {
+  def Reg : Register<"reg">;
+  def Reg2 : Register<"reg2">;
+}
+
+/// Use "Arch" as namespace to match the Target name.
+/// RegisterClasses are expected to be mapped.
+def RegClass : RegisterClass<"Arch", [i32], 0, (add Reg, Reg2)>;
+def RegClass2 : RegisterClass<"Arch", [i32], 0, (add Reg2)>;
+def RegClass3 : RegisterClass<"Arch", [i32], 0, (add Reg)>;
+
+def ModeA : HwMode<[]>;
+def ModeB : HwMode<[]>;
+
+/// RegClassByHwMode is NOT expected to be mapped directly.
+def HwModeRC : RegClassByHwMode<[ModeA, ModeB], [RegClass, RegClass2]>;
+
+def MyImmAsmOperand : AsmOperandClass {
+  let Name = "MyImm";
+}
+
+/// Non-register operands are NOT expected to be mapped.
+def MyImmOp : Operand<i32> {
+  let ParserMatchClass = MyImmAsmOperand;
+}
+
+def foo : Instruction {
+  let Size = 2;
+  let OutOperandList = (outs);
+  let InOperandList = (ins RegClass:$src);
+  let AsmString = "foo $src";
+  let Namespace = "Arch";
+}
+
+/// Singleton registers are NOT expected to be mapped.
+def bar : Instruction {
+  let Size = 2;
+  let OutOperandList = (outs);
+  let InOperandList = (ins);
+  let AsmString = "bar reg"; // uses Reg literally, making it a singleton register
+  let Namespace = "Arch";
+}
+
+def baz : Instruction {
+  let Size = 2;
+  let OutOperandList = (outs);
+  let InOperandList = (ins MyImmOp:$imm);
+  let AsmString = "baz $imm"; // uses MyImmAsmOperand
+  let Namespace = "Arch";
+}
+
+  def SpecialRegAsmOperand : AsmOperandClass {
+  let Name = "SpecialRegOperand";
+  let ParserMethod = "parseRegister";
+  let DiagnosticType = "InvalidSpecialReg";
+}
+
+/// RegisterOperands with custom ParserMatchClass are expected to be mapped
+/// to their underlying RegisterClass.
+def SpecialRegOp : RegisterOperand<RegClass> {
+  let ParserMatchClass = SpecialRegAsmOperand;
+}
+
+#ifdef AMBIGUOUS
+/// This should cause MCK_SpecialRegOperand to be omitted from mapping because it is ambiguous.
+def ZAmbiguousRegOp : RegisterOperand<RegClass3> {
+  let ParserMatchClass = SpecialRegAsmOperand;
+}
+#endif
+
+def qux : Instruction {
+  let Size = 2;
+  let OutOperandList = (outs);
+  let InOperandList = (ins SpecialRegOp:$src);
+  let AsmString = "qux $src";
+  let Namespace = "Arch";
+}
+
+def hwmode_op : RegisterOperand<HwModeRC>;
+
+def qux2 : Instruction {
+  let Size = 2;
+  let OutOperandList = (outs);
+  let InOperandList = (ins hwmode_op:$src);
+  let AsmString = "qux2 $src";
+  let Namespace = "Arch";
+}
+
+// CHECK:      enum MatchClassKind {
+// CHECK-NEXT:   InvalidMatchClass = 0,
+// CHECK-NEXT:   OptionalMatchClass = 1,
+// CHECK-NEXT:   MCK_LAST_TOKEN = OptionalMatchClass,
+// CHECK-NEXT:   MCK_RegClass2, // register class 'RegClass2'
+// CHECK-NEXT:   MCK_RegClass3, // register class 'RegClass3,Reg'
+// CHECK-NEXT:   MCK_RegClass, // register class 'RegClass'
+// CHECK-NEXT:   MCK_LAST_REGISTER = MCK_RegClass,
+// CHECK-NEXT:   MCK_RegByHwMode_HwModeRC, // register class by hwmode
+// CHECK-NEXT:   MCK_LAST_REGCLASS_BY_HWMODE = MCK_RegByHwMode_HwModeRC,
+// CHECK-NEXT:   MCK_Imm, // user defined class 'ImmAsmOperand'
+// CHECK-NEXT:   MCK_MyImm, // user defined class 'MyImmAsmOperand'
+// CHECK-NEXT:   MCK_SpecialRegOperand, // user defined class 'SpecialRegAsmOperand'
+// CHECK-NEXT:   NumMatchClassKinds
+// CHECK-NEXT: };
+
+// CHECK:      {{\[\[}}maybe_unused]] static const MCRegisterClass *getRegClassFromMatchKind(MatchClassKind Kind) {
+// CHECK-NEXT:   switch (Kind) {
+// CHECK-NEXT:   case MCK_RegClass2:
+// CHECK-NEXT:     return &getArchMCRegisterClass(Arch::RegClass2RegClassID);
+// CHECK-NEXT:   case MCK_RegClass3:
+// CHECK-NEXT:     return &getArchMCRegisterClass(Arch::RegClass3RegClassID);
+// CHECK-NEXT:   case MCK_RegClass:
+// CHECK-NEXT:     return &getArchMCRegisterClass(Arch::RegClassRegClassID);
+// UNIQUE-NEXT:  case MCK_SpecialRegOperand:
+// UNIQUE-NEXT:    return &getArchMCRegisterClass(Arch::RegClassRegClassID);
+// CHECK-NEXT:   default:
+// CHECK-NEXT:     return nullptr;
+// CHECK-NEXT:   }
+// CHECK-NEXT: }
+
+// REGINFO-ENUM:      // Register classes
+// REGINFO-ENUM-EMPTY:
+// REGINFO-ENUM-NEXT: namespace Arch {
+// REGINFO-ENUM-EMPTY:
+// REGINFO-ENUM-NEXT: enum {
+// REGINFO-ENUM-NEXT:   RegClassRegClassID = 0,
+// REGINFO-ENUM-NEXT:   RegClass2RegClassID = 1,
+// REGINFO-ENUM-NEXT:   RegClass3RegClassID = 2,
+// REGINFO-ENUM-EMPTY:
+// REGINFO-ENUM-NEXT: };
+
+// REGINFO-DESC: extern const MCRegisterClassStorage<3, 4, 3, 3, 1, 0> ArchMCRegisterClassStorage = {
+// REGINFO-DESC:   Arch::RegClassRegClassID,
+// REGINFO-DESC:   Arch::RegClass2RegClassID,
+// REGINFO-DESC:   Arch::RegClass3RegClassID,

diff  --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index e32111ed46b8e..119a3da036d91 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2546,6 +2546,83 @@ static void emitTokenDiagFunction(AsmMatcherInfo &Info, raw_ostream &OS) {
   OS << "}\n\n";
 }
 
+// Returns true if ClassName corresponds to a RegisterClass defined in the
+// target description (and thus has a generated RegClassID), rather than a
+// singleton register or an anonymous derived register class.
+static bool isDefinedRegisterClass(const AsmMatcherInfo &Info,
+                                   StringRef ClassName) {
+  for (const auto &RC : Info.Target.getRegBank().getRegClasses()) {
+    if (RC.getName() == ClassName)
+      return true;
+  }
+  return false;
+}
+
+static void emitGetRegClassFromMatchKindFunc(AsmMatcherInfo &Info,
+                                             raw_ostream &OS) {
+  OS << "[[maybe_unused]] static const MCRegisterClass "
+        "*getRegClassFromMatchKind(MatchClassKind Kind) {\n";
+  OS << "  switch (Kind) {\n";
+
+  // Emit the straightforward RegisterClass mapping.
+  for (const auto &CI : Info.Classes) {
+    if (CI.isRegisterClass() && !CI.ValueName.empty() &&
+        isDefinedRegisterClass(Info, CI.ClassName)) {
+      OS << "  case " << CI.Name << ":\n";
+      OS << "    return &get" << Info.Target.getName() << "MCRegisterClass("
+         << Info.Target.getName() << "::" << CI.ClassName << "RegClassID);\n";
+    }
+  }
+
+  // Next Collect RegisterOperand MCK_* -> RegisterClass mappings and emit
+  // it for all non-ambiguous RegisterOperands.
+  // Many targets reuse the same ParserMatchClass for 
diff erent register
+  // classes so we can't emit a these unconditionally.
+  std::map<const ClassInfo *, const ClassInfo *> UserClassToRegClassMap;
+  for (const Record *RO :
+       Info.Records.getAllDerivedDefinitions("RegisterOperand")) {
+    const RecordVal *R = RO->getValue("ParserMatchClass");
+    if (!R)
+      continue;
+    const DefInit *DI = dyn_cast<DefInit>(R->getValue());
+    if (!DI)
+      continue;
+    const Record *PMC = DI->getDef();
+    const Record *RC = RO->getValueAsDef("RegClass");
+    if (!RC || !RC->isSubClassOf("RegisterClassLike"))
+      continue;
+    auto PMC_It = Info.AsmOperandClasses.find(PMC);
+    auto RC_It = Info.RegisterClassClasses.find(RC);
+    if (PMC_It == Info.AsmOperandClasses.end() ||
+        RC_It == Info.RegisterClassClasses.end())
+      continue;
+    const ClassInfo *UserCI = PMC_It->second;
+    const ClassInfo *RegCI = RC_It->second;
+
+    auto It = UserClassToRegClassMap.find(UserCI);
+    if (It == UserClassToRegClassMap.end()) {
+      UserClassToRegClassMap[UserCI] = RegCI;
+    } else if (It->second && It->second != RegCI) {
+      // TODO: Warn about ambiguous ParserMatchClass mapping when we can.
+      // Many targets currently have ambiguous mappings.
+      It->second = nullptr; // Mark as ambiguous
+    }
+  }
+  for (const auto [UserCI, RegCI] : UserClassToRegClassMap) {
+    if (RegCI && isDefinedRegisterClass(Info, RegCI->ClassName)) {
+      OS << "  case " << UserCI->Name << ":\n";
+      OS << "    return &get" << Info.Target.getName() << "MCRegisterClass("
+         << Info.Target.getName() << "::" << RegCI->ClassName
+         << "RegClassID);\n";
+    }
+  }
+
+  OS << "  default:\n";
+  OS << "    return nullptr;\n";
+  OS << "  }\n";
+  OS << "}\n\n";
+}
+
 /// emitValidateOperandClass - Emit the function to validate an operand class.
 static void emitValidateOperandClass(const CodeGenTarget &Target,
                                      AsmMatcherInfo &Info, raw_ostream &OS) {
@@ -3554,6 +3631,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
   // Emit a function to map register classes to operand match failure codes.
   emitRegisterMatchErrorFunc(Info, OS);
 
+  // Emit a function to map MatchClassKind to MCRegisterClass.
+  emitGetRegClassFromMatchKindFunc(Info, OS);
+
   // Emit the routine to match token strings to their match class.
   emitMatchTokenString(Target, Info.Classes, OS);
 


        


More information about the llvm-commits mailing list