blob: f2adc00c07d03d944f81111bf30ff0ea73232b4a [file] [log] [blame]
Daniel Dunbar3f6e3ff2009-07-11 19:39:44 +00001//===- 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//
Daniel Dunbarfe6759e2009-08-07 08:26:05 +000013// The input to the target specific matcher is a list of literal tokens and
14// operands. The target specific parser should generally eliminate any syntax
15// which is not relevant for matching; for example, comma tokens should have
16// already been consumed and eliminated by the parser. Most instructions will
17// end up with a single literal token (the instruction name) and some number of
18// operands.
19//
20// Some example inputs, for X86:
21// 'addl' (immediate ...) (register ...)
22// 'add' (immediate ...) (memory ...)
23// 'call' '*' %epc
24//
25// The assembly matcher is responsible for converting this input into a precise
26// machine instruction (i.e., an instruction with a well defined encoding). This
27// mapping has several properties which complicate matching:
28//
29// - It may be ambiguous; many architectures can legally encode particular
30// variants of an instruction in different ways (for example, using a smaller
31// encoding for small immediates). Such ambiguities should never be
32// arbitrarily resolved by the assembler, the assembler is always responsible
33// for choosing the "best" available instruction.
34//
35// - It may depend on the subtarget or the assembler context. Instructions
36// which are invalid for the current mode, but otherwise unambiguous (e.g.,
37// an SSE instruction in a file being assembled for i486) should be accepted
38// and rejected by the assembler front end. However, if the proper encoding
39// for an instruction is dependent on the assembler context then the matcher
40// is responsible for selecting the correct machine instruction for the
41// current mode.
42//
43// The core matching algorithm attempts to exploit the regularity in most
44// instruction sets to quickly determine the set of possibly matching
45// instructions, and the simplify the generated code. Additionally, this helps
46// to ensure that the ambiguities are intentionally resolved by the user.
47//
48// The matching is divided into two distinct phases:
49//
50// 1. Classification: Each operand is mapped to the unique set which (a)
51// contains it, and (b) is the largest such subset for which a single
52// instruction could match all members.
53//
54// For register classes, we can generate these subgroups automatically. For
55// arbitrary operands, we expect the user to define the classes and their
56// relations to one another (for example, 8-bit signed immediates as a
57// subset of 32-bit immediates).
58//
59// By partitioning the operands in this way, we guarantee that for any
60// tuple of classes, any single instruction must match either all or none
61// of the sets of operands which could classify to that tuple.
62//
63// In addition, the subset relation amongst classes induces a partial order
64// on such tuples, which we use to resolve ambiguities.
65//
66// FIXME: What do we do if a crazy case shows up where this is the wrong
67// resolution?
68//
69// 2. The input can now be treated as a tuple of classes (static tokens are
70// simple singleton sets). Each such tuple should generally map to a single
71// instruction (we currently ignore cases where this isn't true, whee!!!),
72// which we can emit a simple matcher for.
73//
Daniel Dunbar3f6e3ff2009-07-11 19:39:44 +000074//===----------------------------------------------------------------------===//
75
76#include "AsmMatcherEmitter.h"
77#include "CodeGenTarget.h"
78#include "Record.h"
Daniel Dunbarfe6759e2009-08-07 08:26:05 +000079#include "llvm/ADT/OwningPtr.h"
Daniel Dunbara54716c2009-07-31 02:32:59 +000080#include "llvm/ADT/SmallVector.h"
Daniel Dunbarfe6759e2009-08-07 08:26:05 +000081#include "llvm/ADT/StringExtras.h"
82#include "llvm/Support/CommandLine.h"
Daniel Dunbara54716c2009-07-31 02:32:59 +000083#include "llvm/Support/Debug.h"
84#include <set>
85#include <list>
Daniel Dunbar3f6e3ff2009-07-11 19:39:44 +000086using namespace llvm;
87
Daniel Dunbarfe6759e2009-08-07 08:26:05 +000088namespace {
89 cl::opt<std::string>
90 MatchOneInstr("match-one-instr", cl::desc("Match only the named instruction"),
91 cl::init(""));
92}
93
Daniel Dunbara54716c2009-07-31 02:32:59 +000094/// FlattenVariants - Flatten an .td file assembly string by selecting the
95/// variant at index \arg N.
96static std::string FlattenVariants(const std::string &AsmString,
97 unsigned N) {
98 StringRef Cur = AsmString;
99 std::string Res = "";
100
101 for (;;) {
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000102 // Find the start of the next variant string.
103 size_t VariantsStart = 0;
104 for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
105 if (Cur[VariantsStart] == '{' &&
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000106 (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
107 Cur[VariantsStart-1] != '\\')))
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000108 break;
Daniel Dunbara54716c2009-07-31 02:32:59 +0000109
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000110 // Add the prefix to the result.
111 Res += Cur.slice(0, VariantsStart);
112 if (VariantsStart == Cur.size())
Daniel Dunbara54716c2009-07-31 02:32:59 +0000113 break;
114
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000115 ++VariantsStart; // Skip the '{'.
116
117 // Scan to the end of the variants string.
118 size_t VariantsEnd = VariantsStart;
119 unsigned NestedBraces = 1;
120 for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000121 if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000122 if (--NestedBraces == 0)
123 break;
124 } else if (Cur[VariantsEnd] == '{')
125 ++NestedBraces;
126 }
Daniel Dunbara54716c2009-07-31 02:32:59 +0000127
128 // Select the Nth variant (or empty).
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000129 StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
Daniel Dunbara54716c2009-07-31 02:32:59 +0000130 for (unsigned i = 0; i != N; ++i)
131 Selection = Selection.split('|').second;
132 Res += Selection.split('|').first;
133
Daniel Dunbar815c7ab2009-08-04 20:36:45 +0000134 assert(VariantsEnd != Cur.size() &&
135 "Unterminated variants in assembly string!");
136 Cur = Cur.substr(VariantsEnd + 1);
Daniel Dunbara54716c2009-07-31 02:32:59 +0000137 }
138
139 return Res;
140}
141
142/// TokenizeAsmString - Tokenize a simplified assembly string.
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000143static void TokenizeAsmString(const StringRef &AsmString,
Daniel Dunbara54716c2009-07-31 02:32:59 +0000144 SmallVectorImpl<StringRef> &Tokens) {
145 unsigned Prev = 0;
146 bool InTok = true;
147 for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
148 switch (AsmString[i]) {
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000149 case '[':
150 case ']':
Daniel Dunbara54716c2009-07-31 02:32:59 +0000151 case '*':
152 case '!':
153 case ' ':
154 case '\t':
155 case ',':
156 if (InTok) {
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000157 Tokens.push_back(AsmString.slice(Prev, i));
Daniel Dunbara54716c2009-07-31 02:32:59 +0000158 InTok = false;
159 }
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000160 if (!isspace(AsmString[i]) && AsmString[i] != ',')
161 Tokens.push_back(AsmString.substr(i, 1));
Daniel Dunbara54716c2009-07-31 02:32:59 +0000162 Prev = i + 1;
163 break;
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000164
165 case '\\':
166 if (InTok) {
167 Tokens.push_back(AsmString.slice(Prev, i));
168 InTok = false;
169 }
170 ++i;
171 assert(i != AsmString.size() && "Invalid quoted character");
172 Tokens.push_back(AsmString.substr(i, 1));
173 Prev = i + 1;
174 break;
175
176 case '$': {
177 // If this isn't "${", treat like a normal token.
178 if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
179 if (InTok) {
180 Tokens.push_back(AsmString.slice(Prev, i));
181 InTok = false;
182 }
183 Prev = i;
184 break;
185 }
186
187 if (InTok) {
188 Tokens.push_back(AsmString.slice(Prev, i));
189 InTok = false;
190 }
191
192 StringRef::iterator End =
193 std::find(AsmString.begin() + i, AsmString.end(), '}');
194 assert(End != AsmString.end() && "Missing brace in operand reference!");
195 size_t EndPos = End - AsmString.begin();
196 Tokens.push_back(AsmString.slice(i, EndPos+1));
197 Prev = EndPos + 1;
198 i = EndPos;
199 break;
200 }
Daniel Dunbara54716c2009-07-31 02:32:59 +0000201
202 default:
203 InTok = true;
204 }
205 }
206 if (InTok && Prev != AsmString.size())
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000207 Tokens.push_back(AsmString.substr(Prev));
208}
209
210static bool IsAssemblerInstruction(const StringRef &Name,
211 const CodeGenInstruction &CGI,
212 const SmallVectorImpl<StringRef> &Tokens) {
213 // Ignore psuedo ops.
214 //
215 // FIXME: This is a hack.
216 if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
217 if (Form->getValue()->getAsString() == "Pseudo")
218 return false;
219
220 // Ignore "PHI" node.
221 //
222 // FIXME: This is also a hack.
223 if (Name == "PHI")
224 return false;
225
226 // Ignore instructions with no .s string.
227 //
228 // FIXME: What are these?
229 if (CGI.AsmString.empty())
230 return false;
231
232 // FIXME: Hack; ignore any instructions with a newline in them.
233 if (std::find(CGI.AsmString.begin(),
234 CGI.AsmString.end(), '\n') != CGI.AsmString.end())
235 return false;
236
237 // Ignore instructions with attributes, these are always fake instructions for
238 // simplifying codegen.
239 //
240 // FIXME: Is this true?
241 //
242 // Also, we ignore instructions which reference the operand multiple times;
243 // this implies a constraint we would not currently honor. These are
244 // currently always fake instructions for simplifying codegen.
245 //
246 // FIXME: Encode this assumption in the .td, so we can error out here.
247 std::set<std::string> OperandNames;
248 for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
249 if (Tokens[i][0] == '$' &&
250 std::find(Tokens[i].begin(),
251 Tokens[i].end(), ':') != Tokens[i].end()) {
252 DEBUG({
253 errs() << "warning: '" << Name << "': "
254 << "ignoring instruction; operand with attribute '"
255 << Tokens[i] << "', \n";
256 });
257 return false;
258 }
259
260 if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
261 DEBUG({
262 errs() << "warning: '" << Name << "': "
263 << "ignoring instruction; tied operand '"
264 << Tokens[i] << "', \n";
265 });
266 return false;
267 }
268 }
269
270 return true;
271}
272
273namespace {
274
275struct OperandListLess {
276 bool operator()(const
277 std::pair<const CodeGenInstruction::OperandInfo*, unsigned> &
278 A,
279 const
280 std::pair<const CodeGenInstruction::OperandInfo*, unsigned> &
281 B) {
282 return A.first->MIOperandNo < B.first->MIOperandNo;
283 }
284
285};
286
287struct InstructionInfo {
288 struct Operand {
289 enum {
290 Token,
291 Class
292 } Kind;
293
294 struct ClassData {
295 /// Operand - The tablegen operand this class corresponds to.
296 const CodeGenInstruction::OperandInfo *Operand;
297
298 /// ClassName - The name of this operand's class.
299 std::string ClassName;
300
301 /// PredicateMethod - The name of the operand method to test whether the
302 /// operand matches this class.
303 std::string PredicateMethod;
304
305 /// RenderMethod - The name of the operand method to add this operand to
306 /// an MCInst.
307 std::string RenderMethod;
308 } AsClass;
309 };
310
311 /// InstrName - The target name for this instruction.
312 std::string InstrName;
313
314 /// Instr - The instruction this matches.
315 const CodeGenInstruction *Instr;
316
317 /// AsmString - The assembly string for this instruction (with variants
318 /// removed).
319 std::string AsmString;
320
321 /// Tokens - The tokenized assembly pattern that this instruction matches.
322 SmallVector<StringRef, 4> Tokens;
323
324 /// Operands - The operands that this instruction matches.
325 SmallVector<Operand, 4> Operands;
326
327 /// ConversionFn - The name of the conversion function to convert parsed
328 /// operands into an MCInst for this function.
329 std::string ConversionFn;
330
331 /// OrderedClassOperands - The indices of the class operands, ordered by their
332 /// MIOperandNo order (which is the order they should be passed to the
333 /// conversion function).
334 SmallVector<unsigned, 4> OrderedClassOperands;
335
336public:
337 void dump();
338};
339
340}
341
342void InstructionInfo::dump() {
343 errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
344 << ", tokens:[";
345 for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
346 errs() << Tokens[i];
347 if (i + 1 != e)
348 errs() << ", ";
349 }
350 errs() << "]\n";
351
352 for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
353 Operand &Op = Operands[i];
354 errs() << " op[" << i << "] = ";
355 if (Op.Kind == Operand::Token) {
356 errs() << '\"' << Tokens[i] << "\"\n";
357 continue;
358 }
359
360 assert(Op.Kind == Operand::Class && "Invalid kind!");
361 const CodeGenInstruction::OperandInfo &OI = *Op.AsClass.Operand;
362 errs() << OI.Name << " " << OI.Rec->getName()
363 << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
364 }
365}
366
367static void BuildInstructionInfos(CodeGenTarget &Target,
368 std::vector<InstructionInfo*> &Infos) {
369 const std::map<std::string, CodeGenInstruction> &Instructions =
370 Target.getInstructions();
371
372 for (std::map<std::string, CodeGenInstruction>::const_iterator
373 it = Instructions.begin(), ie = Instructions.end(); it != ie; ++it) {
374 const CodeGenInstruction &CGI = it->second;
375
376 if (!MatchOneInstr.empty() && it->first != MatchOneInstr)
377 continue;
378
379 OwningPtr<InstructionInfo> II(new InstructionInfo);
380
381 II->InstrName = it->first;
382 II->Instr = &it->second;
383 II->AsmString = FlattenVariants(CGI.AsmString, 0);
384
385 TokenizeAsmString(II->AsmString, II->Tokens);
386
387 // Ignore instructions which shouldn't be matched.
388 if (!IsAssemblerInstruction(it->first, CGI, II->Tokens))
389 continue;
390
391 for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
392 StringRef Token = II->Tokens[i];
393
394 // Check for simple tokens.
395 if (Token[0] != '$') {
396 InstructionInfo::Operand Op;
397 Op.Kind = InstructionInfo::Operand::Token;
398 II->Operands.push_back(Op);
399 continue;
400 }
401
402 // Otherwise this is an operand reference.
403 InstructionInfo::Operand Op;
404 Op.Kind = InstructionInfo::Operand::Class;
405
406 StringRef OperandName;
407 if (Token[1] == '{')
408 OperandName = Token.substr(2, Token.size() - 3);
409 else
410 OperandName = Token.substr(1);
411
412 // Map this token to an operand. FIXME: Move elsewhere.
413 unsigned Idx;
414 try {
415 Idx = CGI.getOperandNamed(OperandName);
416 } catch(...) {
417 errs() << "error: unable to find operand: '" << OperandName << "'!\n";
418 break;
419 }
420
421 const CodeGenInstruction::OperandInfo &OI = CGI.OperandList[Idx];
422 Op.AsClass.Operand = &OI;
423
424 if (OI.Rec->isSubClassOf("RegisterClass")) {
425 Op.AsClass.ClassName = "Reg";
426 Op.AsClass.PredicateMethod = "isReg";
427 Op.AsClass.RenderMethod = "addRegOperands";
428 } else if (OI.Rec->isSubClassOf("Operand")) {
429 // FIXME: This should not be hard coded.
430 const RecordVal *RV = OI.Rec->getValue("Type");
431
432 // FIXME: Yet another total hack.
433 if (RV->getValue()->getAsString() == "iPTR" ||
434 OI.Rec->getName() == "lea32mem" ||
435 OI.Rec->getName() == "lea64_32mem") {
436 Op.AsClass.ClassName = "Mem";
437 Op.AsClass.PredicateMethod = "isMem";
438 Op.AsClass.RenderMethod = "addMemOperands";
439 } else {
440 Op.AsClass.ClassName = "Imm";
441 Op.AsClass.PredicateMethod = "isImm";
442 Op.AsClass.RenderMethod = "addImmOperands";
443 }
444 } else {
445 OI.Rec->dump();
446 assert(0 && "Unexpected instruction operand record!");
447 }
448
449 II->Operands.push_back(Op);
450 }
451
452 // If we broke out, ignore the instruction.
453 if (II->Operands.size() != II->Tokens.size())
454 continue;
455
456 Infos.push_back(II.take());
457 }
458}
459
460static void ConstructConversionFunctions(CodeGenTarget &Target,
461 std::vector<InstructionInfo*> &Infos,
462 raw_ostream &OS) {
463 // Function we have already generated.
464 std::set<std::string> GeneratedFns;
465
466 for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
467 ie = Infos.end(); it != ie; ++it) {
468 InstructionInfo &II = **it;
469
470 // Order the (class) operands by the order to convert them into an MCInst.
471 SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
472 for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
473 InstructionInfo::Operand &Op = II.Operands[i];
474 if (Op.Kind == InstructionInfo::Operand::Class)
475 MIOperandList.push_back(std::make_pair(Op.AsClass.Operand->MIOperandNo,
476 i));
477 }
478 std::sort(MIOperandList.begin(), MIOperandList.end());
479
480 // Compute the total number of operands.
481 unsigned NumMIOperands = 0;
482 for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
483 const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i];
484 NumMIOperands = std::max(NumMIOperands,
485 OI.MIOperandNo + OI.MINumOperands);
486 }
487
488 // Build the conversion function signature.
489 std::string Signature = "Convert";
490 unsigned CurIndex = 0;
491 for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
492 InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
493 assert(CurIndex <= Op.AsClass.Operand->MIOperandNo &&
494 "Duplicate match for instruction operand!");
495
496 // Save the conversion index, for use by the matcher.
497 II.OrderedClassOperands.push_back(MIOperandList[i].second);
498
499 // Skip operands which weren't matched by anything, this occurs when the
500 // .td file encodes "implicit" operands as explicit ones.
501 //
502 // FIXME: This should be removed from the MCInst structure.
503 for (; CurIndex != Op.AsClass.Operand->MIOperandNo; ++CurIndex)
504 Signature += "Imp";
505
506 Signature += Op.AsClass.ClassName;
507 Signature += utostr(Op.AsClass.Operand->MINumOperands);
508 CurIndex += Op.AsClass.Operand->MINumOperands;
509 }
510
511 // Add any trailing implicit operands.
512 for (; CurIndex != NumMIOperands; ++CurIndex)
513 Signature += "Imp";
514
515 // Save the conversion function, for use by the matcher.
516 II.ConversionFn = Signature;
517
518 // Check if we have already generated this function.
519 if (!GeneratedFns.insert(Signature).second)
520 continue;
521
522 // If not, emit it now.
523 //
524 // FIXME: There should be no need to pass the number of operands to fill;
525 // this should always be implicit in the class.
526 OS << "static bool " << Signature << "(MCInst &Inst, unsigned Opcode";
527 for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i)
528 OS << ", " << Target.getName() << "Operand Op" << i;
529 OS << ") {\n";
530 OS << " Inst.setOpcode(Opcode);\n";
531 CurIndex = 0;
532 for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
533 InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
534
535 // Add the implicit operands.
536 for (; CurIndex != Op.AsClass.Operand->MIOperandNo; ++CurIndex)
537 OS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
538
539 OS << " Op" << i << "." << Op.AsClass.RenderMethod
540 << "(Inst, " << Op.AsClass.Operand->MINumOperands << ");\n";
541 CurIndex += Op.AsClass.Operand->MINumOperands;
542 }
543
544 // And add trailing implicit operands.
545 for (; CurIndex != NumMIOperands; ++CurIndex)
546 OS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
547
548 OS << " return false;\n";
549 OS << "}\n\n";
550 }
Daniel Dunbara54716c2009-07-31 02:32:59 +0000551}
552
Daniel Dunbar2f9876b2009-07-17 18:51:11 +0000553void AsmMatcherEmitter::run(raw_ostream &OS) {
Daniel Dunbar3f6e3ff2009-07-11 19:39:44 +0000554 CodeGenTarget Target;
Daniel Dunbar2f9876b2009-07-17 18:51:11 +0000555 const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
Daniel Dunbar85f1b392009-07-29 00:02:19 +0000556 Record *AsmParser = Target.getAsmParser();
557 std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
Daniel Dunbar2f9876b2009-07-17 18:51:11 +0000558
559 std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");
560
561 EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
Daniel Dunbar2f9876b2009-07-17 18:51:11 +0000562
563 // Emit the function to match a register name to number.
564
Daniel Dunbar85f1b392009-07-29 00:02:19 +0000565 OS << "bool " << Target.getName() << ClassName
566 << "::MatchRegisterName(const StringRef &Name, unsigned &RegNo) {\n";
Daniel Dunbar2f9876b2009-07-17 18:51:11 +0000567
568 // FIXME: TableGen should have a fast string matcher generator.
569 for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
570 const CodeGenRegister &Reg = Registers[i];
571 if (Reg.TheDef->getValueAsString("AsmName").empty())
572 continue;
573
574 OS << " if (Name == \""
575 << Reg.TheDef->getValueAsString("AsmName") << "\")\n"
576 << " return RegNo=" << i + 1 << ", false;\n";
577 }
578 OS << " return true;\n";
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000579 OS << "}\n\n";
Daniel Dunbara54716c2009-07-31 02:32:59 +0000580
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000581 std::vector<InstructionInfo*> Infos;
582 BuildInstructionInfos(Target, Infos);
Daniel Dunbara54716c2009-07-31 02:32:59 +0000583
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000584#undef DEBUG_TYPE
585#define DEBUG_TYPE "instruction_info"
586 DEBUG({
587 for (std::vector<InstructionInfo*>::iterator it = Infos.begin(),
588 ie = Infos.end(); it != ie; ++it)
589 (*it)->dump();
590 });
591#undef DEBUG_TYPE
592#define DEBUG_TYPE ""
Daniel Dunbara54716c2009-07-31 02:32:59 +0000593
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000594 // FIXME: At this point we should be able to totally order Infos, if not then
595 // we have an ambiguity which the .td file should be forced to resolve.
Daniel Dunbara54716c2009-07-31 02:32:59 +0000596
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000597 // Generate the terminal actions to convert operands into an MCInst. We still
598 // pass the operands in to these functions individually (as opposed to the
599 // array) so that we do not need to worry about the operand order.
600 ConstructConversionFunctions(Target, Infos, OS);
Daniel Dunbara54716c2009-07-31 02:32:59 +0000601
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000602 // Build a very stupid version of the match function which just checks each
603 // instruction in order.
Daniel Dunbara54716c2009-07-31 02:32:59 +0000604
605 OS << "bool " << Target.getName() << ClassName
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000606 << "::MatchInstruction("
Daniel Dunbara54716c2009-07-31 02:32:59 +0000607 << "SmallVectorImpl<" << Target.getName() << "Operand> &Operands, "
608 << "MCInst &Inst) {\n";
Daniel Dunbarfe6759e2009-08-07 08:26:05 +0000609
610 for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
611 ie = Infos.end(); it != ie; ++it) {
612 InstructionInfo &II = **it;
613
614 // The parser is expected to arrange things so that each "token" matches
615 // exactly one target specific operand.
616 OS << " if (Operands.size() == " << II.Operands.size();
617 for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
618 InstructionInfo::Operand &Op = II.Operands[i];
619
620 OS << " &&\n";
621 OS << " ";
622
623 if (Op.Kind == InstructionInfo::Operand::Token)
624 OS << "Operands[" << i << "].isToken(\"" << II.Tokens[i] << "\")";
625 else
626 OS << "Operands[" << i << "]."
627 << Op.AsClass.PredicateMethod << "()";
628 }
629 OS << ")\n";
630 OS << " return " << II.ConversionFn << "(Inst, "
631 << Target.getName() << "::" << II.InstrName;
632 for (unsigned i = 0, e = II.OrderedClassOperands.size(); i != e; ++i)
633 OS << ", Operands[" << II.OrderedClassOperands[i] << "]";
634 OS << ");\n\n";
Daniel Dunbara54716c2009-07-31 02:32:59 +0000635 }
636
637 OS << " return true;\n";
638 OS << "}\n\n";
Daniel Dunbar3f6e3ff2009-07-11 19:39:44 +0000639}