aboutsummaryrefslogtreecommitdiffstats
path: root/utils/TableGen/AsmMatcherEmitter.cpp
blob: 45a1c8622aa956b9864be0916d1fe770d1b1f691 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits a target specifier matcher for converting parsed
// assembly operands in the MCInst structures.
//
//===----------------------------------------------------------------------===//

#include "AsmMatcherEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
using namespace llvm;

static std::string FlattenVariants(const std::string &AsmString,
                                   unsigned Index) {
  StringRef Cur = AsmString;
  std::string Res = "";
  
  for (;;) {
    std::pair<StringRef, StringRef> Split = Cur.split('{');

    Res += Split.first;
    if (Split.second.empty())
      break;

    std::pair<StringRef, StringRef> Inner = Cur.split('}');
    StringRef Selection = Inner.first;
    for (unsigned i = 0; i != Index; ++i)
      Selection = Selection.split('|').second;
    Selection = Selection.split('|').first;

    Res += Selection;

    Cur = Inner.second;
  } 

  return Res;
}

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);

  // Emit the function to match a register name to number.

  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) {
    const CodeGenRegister &Reg = Registers[i];
    if (Reg.TheDef->getValueAsString("AsmName").empty())
      continue;

    OS << "  if (Name == \"" 
       << Reg.TheDef->getValueAsString("AsmName") << "\")\n"
       << "    return RegNo=" << i + 1 << ", false;\n";
  }
  OS << "  return true;\n";
  OS << "}\n";

  // Emit the function to match instructions.  
  std::vector<const CodeGenInstruction*> NumberedInstructions;
  Target.getInstructionsByEnumValue(NumberedInstructions);

  const std::map<std::string, CodeGenInstruction> &Instructions =
    Target.getInstructions();
  for (std::map<std::string, CodeGenInstruction>::const_iterator 
         it = Instructions.begin(), ie = Instructions.end(); it != ie; ++it) {
    const CodeGenInstruction &CGI = it->second;

    if (it->first != "SUB8rr")
      continue;

    /*
def SUB8rr  : I<0x28, MRMDestReg, (outs GR8:$dst), (ins GR8:$src1, GR8:$src2),
                "sub{b}\t{$src2, $dst|$dst, $src2}",
                [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)),
                 (implicit EFLAGS)]>;
    */

    outs() << it->first << " "
           << FlattenVariants(CGI.AsmString, 0)
           << "\n";
  }
}