llvm-mc: Match a few X86 instructions.
[oota-llvm.git] / utils / TableGen / AsmMatcherEmitter.cpp
1 //===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This tablegen backend emits a target specifier matcher for converting parsed
11 // assembly operands in the MCInst structures.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "AsmMatcherEmitter.h"
16 #include "CodeGenTarget.h"
17 #include "Record.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Support/Debug.h"
20 #include <set>
21 #include <list>
22 using namespace llvm;
23
24 /// FlattenVariants - Flatten an .td file assembly string by selecting the
25 /// variant at index \arg N.
26 static std::string FlattenVariants(const std::string &AsmString,
27                                    unsigned N) {
28   StringRef Cur = AsmString;
29   std::string Res = "";
30   
31   for (;;) {
32     // Add the prefix until the next '{', and split out the contents in the
33     // braces.
34     std::pair<StringRef, StringRef> Inner, Split = Cur.split('{');
35
36     Res += Split.first;
37     if (Split.second.empty())
38       break;
39
40     Inner = Split.second.split('}');
41
42     // Select the Nth variant (or empty).
43     StringRef Selection = Inner.first;
44     for (unsigned i = 0; i != N; ++i)
45       Selection = Selection.split('|').second;
46     Res += Selection.split('|').first;
47
48     Cur = Inner.second;
49   } 
50
51   return Res;
52 }
53
54 /// TokenizeAsmString - Tokenize a simplified assembly string.
55 static void TokenizeAsmString(const std::string &AsmString, 
56                               SmallVectorImpl<StringRef> &Tokens) {
57   unsigned Prev = 0;
58   bool InTok = true;
59   for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
60     switch (AsmString[i]) {
61     case '*':
62     case '!':
63     case ' ':
64     case '\t':
65     case ',':
66       if (InTok) {
67         Tokens.push_back(StringRef(&AsmString[Prev], i - Prev));
68         InTok = false;
69       }
70       if (AsmString[i] == '*' || AsmString[i] == '!')
71         Tokens.push_back(StringRef(&AsmString[i], 1));
72       Prev = i + 1;
73       break;
74
75     default:
76       InTok = true;
77     }
78   }
79   if (InTok && Prev != AsmString.size())
80     Tokens.push_back(StringRef(&AsmString[Prev], AsmString.size() - Prev));
81 }
82
83 void AsmMatcherEmitter::run(raw_ostream &OS) {
84   CodeGenTarget Target;
85   const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
86   Record *AsmParser = Target.getAsmParser();
87   std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
88
89   std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");
90
91   EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
92
93   // Emit the function to match a register name to number.
94
95   OS << "bool " << Target.getName() << ClassName
96      << "::MatchRegisterName(const StringRef &Name, unsigned &RegNo) {\n";
97
98   // FIXME: TableGen should have a fast string matcher generator.
99   for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
100     const CodeGenRegister &Reg = Registers[i];
101     if (Reg.TheDef->getValueAsString("AsmName").empty())
102       continue;
103
104     OS << "  if (Name == \"" 
105        << Reg.TheDef->getValueAsString("AsmName") << "\")\n"
106        << "    return RegNo=" << i + 1 << ", false;\n";
107   }
108   OS << "  return true;\n";
109   OS << "}\n";
110
111   // Emit the function to match instructions.  
112   std::vector<const CodeGenInstruction*> NumberedInstructions;
113   Target.getInstructionsByEnumValue(NumberedInstructions);
114
115   std::list<std::string> MatchFns;
116
117   OS << "\n";
118   const std::map<std::string, CodeGenInstruction> &Instructions =
119     Target.getInstructions();
120   for (std::map<std::string, CodeGenInstruction>::const_iterator 
121          it = Instructions.begin(), ie = Instructions.end(); it != ie; ++it) {
122     const CodeGenInstruction &CGI = it->second;
123
124     // Ignore psuedo ops.
125     //
126     // FIXME: This is a hack.
127     if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
128       if (Form->getValue()->getAsString() == "Pseudo")
129         continue;
130
131     // Ignore instructions with no .s string.
132     //
133     // FIXME: What are these?
134     if (CGI.AsmString.empty())
135       continue;
136
137     // FIXME: Hack; ignore "lock".
138     if (StringRef(CGI.AsmString).startswith("lock"))
139       continue;
140
141     // FIXME: Hack.
142 #if 0
143     if (1 && it->first != "SUB8mr")
144       continue;
145 #endif
146
147     std::string Flattened = FlattenVariants(CGI.AsmString, 0);
148     SmallVector<StringRef, 8> Tokens;
149
150     TokenizeAsmString(Flattened, Tokens);
151
152     DEBUG({
153         outs() << it->first << " -- flattened:\"" 
154                << Flattened << "\", tokens:[";
155         for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
156           outs() << Tokens[i];
157           if (i + 1 != e)
158             outs() << ", ";
159         }
160         outs() << "]\n";
161
162         for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) {
163           const CodeGenInstruction::OperandInfo &OI = CGI.OperandList[i];
164           outs() << "  op[" << i << "] = " << OI.Name
165                  << " " << OI.Rec->getName()
166                  << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
167         }
168       });
169
170     // FIXME: Ignore non-literal tokens.
171     if (std::find(Tokens[0].begin(), Tokens[0].end(), '$') != Tokens[0].end())
172       continue;
173
174     std::string FnName = "Match_" + Target.getName() + "_Inst_" + it->first;
175     MatchFns.push_back(FnName);
176
177     OS << "static bool " << FnName
178        << "(const StringRef &Name,"
179        << " SmallVectorImpl<X86Operand> &Operands,"
180        << " MCInst &Inst) {\n\n";
181
182     OS << "  // Match name.\n";
183     OS << "  if (Name != \"" << Tokens[0] << "\")\n";
184     OS << "    return true;\n\n";
185     
186     OS << "  // Match number of operands.\n";
187     OS << "  if (Operands.size() != " << Tokens.size() - 1 << ")\n";
188     OS << "    return true;\n\n";
189
190     // Compute the total number of MCOperands.
191     //
192     // FIXME: Isn't this somewhere else?
193     unsigned NumMIOperands = 0;
194     for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) {
195       const CodeGenInstruction::OperandInfo &OI = CGI.OperandList[i];
196       NumMIOperands = std::max(NumMIOperands, 
197                                OI.MIOperandNo + OI.MINumOperands);
198     }
199
200     std::set<unsigned> MatchedOperands;
201     // This the list of operands we need to fill in.
202     if (NumMIOperands)
203       OS << "  MCOperand Ops[" << NumMIOperands << "];\n\n";
204
205     unsigned ParsedOpIdx = 0;
206     for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
207       // FIXME: Can only match simple operands.
208       if (Tokens[i][0] != '$') {
209         OS << "  // FIXME: unable to match token: '" << Tokens[i] << "'!\n";
210         OS << "  return true;\n\n";
211         continue;
212       }
213
214       // Map this token to an operand. FIXME: Move elsewhere.
215
216       unsigned Idx;
217       try {
218         Idx = CGI.getOperandNamed(Tokens[i].substr(1));
219       } catch(...) {
220         OS << "  // FIXME: unable to find operand: '" << Tokens[i] << "'!\n";
221         OS << "  return true;\n\n";
222         continue;
223       }
224
225       // FIXME: Each match routine should always end up filling the same number
226       // of operands, we should just check that the number matches what the
227       // match routine expects here instead of passing it. We can do this once
228       // we start generating the class match functions.
229       const CodeGenInstruction::OperandInfo &OI = CGI.OperandList[Idx];
230
231       // Track that we have matched these operands.
232       //
233       // FIXME: Verify that we don't parse something to the same operand twice.
234       for (unsigned j = 0; j != OI.MINumOperands; ++j)
235         MatchedOperands.insert(OI.MIOperandNo + j);
236
237       OS << "  // Match '" << Tokens[i] << "' (parsed operand " << ParsedOpIdx 
238          << ") to machine operands [" << OI.MIOperandNo << ", " 
239          << OI.MIOperandNo + OI.MINumOperands << ").\n";
240       OS << "  if (Match_" << Target.getName() 
241          << "_Op_" << OI.Rec->getName()  << "("
242          << "Operands[" << ParsedOpIdx << "], "
243          << "&Ops[" << OI.MIOperandNo << "], " 
244          << OI.MINumOperands << "))\n";
245       OS << "    return true;\n\n";
246
247       ++ParsedOpIdx;
248     }
249
250     // Generate code to construct the MCInst.
251
252     OS << "  // Construct MCInst.\n";
253     OS << "  Inst.setOpcode(" << Target.getName() << "::" 
254        << it->first << ");\n";
255     for (unsigned i = 0, e = NumMIOperands; i != e; ++i) {
256       // FIXME: Oops! Ignore this for now, the instruction should print ok. If
257       // we need to evaluate the constraints.
258       if (!MatchedOperands.count(i)) {
259         OS << "\n";
260         OS << "  // FIXME: Nothing matched Ops[" << i << "]!\n";
261         OS << "  Ops[" << i << "].MakeReg(0);\n";
262         OS << "\n";
263       }
264
265       OS << "  Inst.addOperand(Ops[" << i << "]);\n";
266     }
267     OS << "\n";
268     OS << "  return false;\n";
269     OS << "}\n\n";
270   }
271
272   // Generate the top level match function.
273
274   OS << "bool " << Target.getName() << ClassName
275      << "::MatchInstruction(const StringRef &Name, "
276      << "SmallVectorImpl<" << Target.getName() << "Operand> &Operands, "
277      << "MCInst &Inst) {\n";
278   for (std::list<std::string>::iterator it = MatchFns.begin(), 
279          ie = MatchFns.end(); it != ie; ++it) {
280     OS << "  if (!" << *it << "(Name, Operands, Inst))\n";
281     OS << "    return false;\n\n";
282   }
283
284   OS << "  return true;\n";
285   OS << "}\n\n";
286 }