6bbe4d9c529759db552ee233d6cc63c62085a5c3
[oota-llvm.git] / utils / TableGen / EDEmitter.cpp
1 //===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===//
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 is responsible for emitting a description of each
11 // instruction in a format that the enhanced disassembler can use to tokenize
12 // and parse instructions.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "EDEmitter.h"
17
18 #include "AsmWriterInst.h"
19 #include "CodeGenTarget.h"
20 #include "Record.h"
21
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/Format.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 #include <vector>
27 #include <string>
28
29 #define MAX_OPERANDS 5
30 #define MAX_SYNTAXES 2
31
32 using namespace llvm;
33
34 ///////////////////////////////////////////////////////////
35 // Support classes for emitting nested C data structures //
36 ///////////////////////////////////////////////////////////
37
38 namespace {
39   
40   class EnumEmitter {
41   private:
42     std::string Name;
43     std::vector<std::string> Entries;
44   public:
45     EnumEmitter(const char *N) : Name(N) { 
46     }
47     int addEntry(const char *e) { 
48       Entries.push_back(std::string(e));
49       return Entries.size() - 1; 
50     }
51     void emit(raw_ostream &o, unsigned int &i) {
52       o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
53       i += 2;
54       
55       unsigned int index = 0;
56       unsigned int numEntries = Entries.size();
57       for(index = 0; index < numEntries; ++index) {
58         o.indent(i) << Entries[index];
59         if(index < (numEntries - 1))
60           o << ",";
61         o << "\n";
62       }
63       
64       i -= 2;
65       o.indent(i) << "};" << "\n";
66     }
67     
68     void emitAsFlags(raw_ostream &o, unsigned int &i) {
69       o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
70       i += 2;
71       
72       unsigned int index = 0;
73       unsigned int numEntries = Entries.size();
74       unsigned int flag = 1;
75       for (index = 0; index < numEntries; ++index) {
76         o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
77         if (index < (numEntries - 1))
78           o << ",";
79         o << "\n";
80         flag <<= 1;
81       }
82       
83       i -= 2;
84       o.indent(i) << "};" << "\n";
85     }
86   };
87
88   class StructEmitter {
89   private:
90     std::string Name;
91     std::vector<std::string> MemberTypes;
92     std::vector<std::string> MemberNames;
93   public:
94     StructEmitter(const char *N) : Name(N) {
95     }
96     void addMember(const char *t, const char *n) {
97       MemberTypes.push_back(std::string(t));
98       MemberNames.push_back(std::string(n));
99     }
100     void emit(raw_ostream &o, unsigned int &i) {
101       o.indent(i) << "struct " << Name.c_str() << " {" << "\n";
102       i += 2;
103       
104       unsigned int index = 0;
105       unsigned int numMembers = MemberTypes.size();
106       for (index = 0; index < numMembers; ++index) {
107         o.indent(i) << MemberTypes[index] << " " << MemberNames[index] << ";";
108         o << "\n";
109       }
110       
111       i -= 2;
112       o.indent(i) << "};" << "\n";
113     }
114   };
115   
116   class ConstantEmitter {
117   public:
118     virtual ~ConstantEmitter() { }
119     virtual void emit(raw_ostream &o, unsigned int &i) = 0;
120   };
121   
122   class LiteralConstantEmitter : public ConstantEmitter {
123   private:
124     std::string Literal;
125   public:
126     LiteralConstantEmitter(const char *literal) : Literal(literal) {
127     }
128     LiteralConstantEmitter(int literal) {
129       char buf[256];
130       snprintf(buf, 256, "%d", literal);
131       Literal = buf;
132     }
133     void emit(raw_ostream &o, unsigned int &i) {
134       o << Literal;
135     }
136   };
137   
138   class CompoundConstantEmitter : public ConstantEmitter {
139   private:
140     std::vector<ConstantEmitter*> Entries;
141   public:
142     CompoundConstantEmitter() {
143     }
144     ~CompoundConstantEmitter() {
145       unsigned int index;
146       unsigned int numEntries = Entries.size();
147       for (index = 0; index < numEntries; ++index) {
148         delete Entries[index];
149       }
150     }
151     CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
152       Entries.push_back(e);
153       return *this;
154     }
155     void emit(raw_ostream &o, unsigned int &i) {
156       o << "{" << "\n";
157       i += 2;
158   
159       unsigned int index;
160       unsigned int numEntries = Entries.size();
161       for (index = 0; index < numEntries; ++index) {
162         o.indent(i);
163         Entries[index]->emit(o, i);
164         if (index < (numEntries - 1))
165           o << ",";
166         o << "\n";
167       }
168       
169       i -= 2;
170       o.indent(i) << "}";
171     }
172   };
173   
174   class FlagsConstantEmitter : public ConstantEmitter {
175   private:
176     std::vector<std::string> Flags;
177   public:
178     FlagsConstantEmitter() {
179     }
180     FlagsConstantEmitter &addEntry(const char *f) {
181       Flags.push_back(std::string(f));
182       return *this;
183     }
184     void emit(raw_ostream &o, unsigned int &i) {
185       unsigned int index;
186       unsigned int numFlags = Flags.size();
187       if (numFlags == 0)
188         o << "0";
189       
190       for (index = 0; index < numFlags; ++index) {
191         o << Flags[index].c_str();
192         if (index < (numFlags - 1))
193           o << " | ";
194       }
195     }
196   };
197 }
198
199 EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
200 }
201
202 //////////////////////////////////////////////
203 // Support functions for parsing AsmStrings //
204 //////////////////////////////////////////////
205
206 /// parseError - A better error reporter for use in AsmString parsers
207 ///
208 /// @arg asmString  - The original assembly string, for use in the error report
209 /// @arg index      - The character where the error occurred
210 /// @arg err        - The text of the error itself
211 static void parseError(const std::string& asmString, 
212                        unsigned int index, 
213                        const char* err) {
214   errs() << "In: " << asmString.c_str() << "\n";
215   errs() << "Error at " << format("%d", index) << ": " << err << "\n";
216   llvm_unreachable("Parse error");
217 }
218
219 /// resolveBraces - Interprets the brace syntax in an AsmString in favor of just
220 ///   one syntax, and returns the result.  "{A}" is resolved to "A" for syntax 0
221 ///   and "" for all others; "{A|B}" is resolved to "A" for syntax 0, "B" for 
222 ///   syntax 1, and "" for all others; and so on.
223 ///
224 /// @arg asmString    - The original string, as loaded from the .td file
225 /// @arg syntaxIndex  - The index to use
226 static std::string resolveBraces(const std::string &asmString, 
227                                  unsigned int syntaxIndex) {
228   std::string ret;
229   
230   unsigned int index;
231   unsigned int numChars = asmString.length();
232   
233   // Brace parsing countable-state transducer
234   //
235   // STATES       - -1, 0, 1, ..., error
236   // SYMBOLS      - '{', '|', '}', ?, EOF
237   // START STATE  - -1
238   //
239   // state  input   ->  state output
240   // -1     '{'     ->  0
241   // -1     '|'     ->  error
242   // -1     '}'     ->  error
243   // -1     ?       ->  -1    ?
244   // -1     EOF     ->  -1
245   // n      '{'     ->  error
246   // n      '|'     ->  n+1
247   // n      '}'     ->  -1
248   // n      ?       ->  n     ? if n == syntaxIndex
249   //                            if not
250   // n      EOF     ->  error
251   
252   int state = -1;
253   
254   for (index = 0; index < numChars; ++index) {
255     char input = asmString[index];
256         
257     switch (state) {
258     default:
259       switch (input) {
260       default:
261         if (state == (int)syntaxIndex)
262           ret.push_back(input);
263         break;
264       case '{':
265         parseError(asmString, index, "Nested { in AsmString");
266         break;
267       case '|':
268         state++;
269         break;
270       case '}':
271         state = -1;
272         break;
273       }
274       break;
275     case -1:
276       switch (input) {
277       default:
278         ret.push_back(input);
279         break;
280       case '{':
281         state = 0;
282         break;
283       case '|':
284         parseError(asmString, index, "| outside braces in AsmString");
285         break;
286       case '}':
287         parseError(asmString, index, "Unmatched } in AsmString");
288         break;
289       }
290       break;
291     }
292   }
293   
294   if (state != -1)
295     parseError(asmString, index, "Unmatched { in AsmString");
296   
297   return ret;
298 }
299
300 /// getOperandIndex - looks up a named operand in an instruction and determines
301 ///   its index in the operand descriptor array, returning the index or -1 if it
302 ///   is not present.
303 ///
304 /// @arg asmString  - The assembly string for the instruction, for errors only
305 /// @arg operand    - The operand's name
306 /// @arg inst       - The instruction to use when looking up the operand
307 static int8_t getOperandIndex(const std::string &asmString,
308                               const std::string &operand,
309                               const CodeGenInstruction &inst) {
310   int8_t operandIndex;
311   
312   if(operand.length() == 0) {
313     errs() << "In: " << asmString << "\n";
314     errs() << "Operand: " << operand << "\n";
315     llvm_unreachable("Empty operand");
316   }
317   
318   try {
319     operandIndex = inst.getOperandNamed(operand);
320   }
321   catch (...) {
322     return -1;
323   }
324   
325   return operandIndex;
326 }
327
328 /// isAlphanumeric - returns true if a character is a valid alphanumeric
329 ///   character, and false otherwise
330 ///
331 /// input - The character to query
332 static inline bool isAlphanumeric(char input) {
333   if((input >= 'a' && input <= 'z') ||
334      (input >= 'A' && input <= 'Z') ||
335      (input >= '0' && input <= '9') ||
336      (input == '_'))
337     return true;
338   else
339     return false;
340 }
341
342 /// populateOperandOrder - reads a resolved AsmString (see resolveBraces) and
343 ///   records the index into the operand descriptor array for each operand in
344 ///   that string, in the order of appearance.
345 ///
346 /// @arg operandOrder - The array that will be populated with the operand
347 ///                     mapping.  Each entry will contain -1 (invalid index
348 ///                     into the operands present in the AsmString) or a number
349 ///                     representing an index in the operand descriptor array.
350 /// @arg asmString    - The operand's name
351 /// @arg inst         - The instruction to use when looking up the operand
352 void populateOperandOrder(CompoundConstantEmitter *operandOrder,
353                           const std::string &asmString,
354                           const CodeGenInstruction &inst) {
355   std::string aux;
356   
357   unsigned int index;
358   unsigned int numChars = asmString.length();
359   unsigned int numArgs = 0;
360   
361   // Argument processing finite-state transducer
362   //
363   // STATES       - 0, 1, error
364   // SYMBOLS      - A(lphanumeric), '$', ?, EOF
365   // START STATE  - 0
366   //
367   // state  input   ->  state aux
368   // 0      A       ->  0
369   // 0      '$'     ->  1
370   // 0      ?       ->  0
371   // 0      EOF     ->  0
372   // 1      A       ->  1     A
373   // 1      '$'     ->  error
374   // 1      ?       ->  0     clear
375   // 1      EOF     ->  0     clear
376   
377   unsigned int state = 0;
378   
379   for (index = 0; index < numChars; ++index) {
380     char input = asmString[index];
381     
382     switch (state) {
383       default:
384         parseError(asmString, index, "Parser in unreachable state");
385       case 0:
386         if (input == '$') {
387           state = 1;
388         }
389         break;
390       case 1:
391         if (isAlphanumeric(input)) {
392           aux.push_back(input);
393         }
394         else if (input == '$') {
395           parseError(asmString, index, "$ found in argument name");
396         }
397         else {
398           int8_t operandIndex = getOperandIndex(asmString, aux, inst);
399           char buf[3];
400           snprintf(buf, sizeof(buf), "%d", operandIndex);
401           operandOrder->addEntry(new LiteralConstantEmitter(buf));
402           aux.clear();
403           state = 0;
404           numArgs++;
405         }
406         break;
407     }
408   }
409   
410   if (state == 1) {
411     int8_t operandIndex = getOperandIndex(asmString, aux, inst);
412     char buf[2];
413     snprintf(buf, 2, "%d", operandIndex);
414     operandOrder->addEntry(new LiteralConstantEmitter(buf));
415     aux.clear();
416     numArgs++;
417   }
418   
419   for(; numArgs < MAX_OPERANDS; numArgs++) {
420     operandOrder->addEntry(new LiteralConstantEmitter("-1"));
421   }
422 }
423
424 /////////////////////////////////////////////////////
425 // Support functions for handling X86 instructions //
426 /////////////////////////////////////////////////////
427
428 #define ADDFLAG(flag) flags->addEntry(flag)
429
430 #define REG(str) if (name == str) { ADDFLAG("kOperandFlagRegister"); return 0; }
431 #define MEM(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); return 0; }
432 #define LEA(str) if (name == str) { ADDFLAG("kOperandFlagEffectiveAddress"); \
433                                     return 0; }
434 #define IMM(str) if (name == str) { ADDFLAG("kOperandFlagImmediate"); \
435                                     return 0; }
436 #define PCR(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); \
437                                     ADDFLAG("kOperandFlagPCRelative"); \
438                                     return 0; }
439
440 /// X86FlagFromOpName - Processes the name of a single X86 operand (which is
441 ///   actually its type) and translates it into an operand flag
442 ///
443 /// @arg flags    - The flags object to add the flag to
444 /// @arg name     - The name of the operand
445 static int X86FlagFromOpName(FlagsConstantEmitter *flags,
446                              const std::string &name) {
447   REG("GR8");
448   REG("GR8_NOREX");
449   REG("GR16");
450   REG("GR32");
451   REG("GR32_NOREX");
452   REG("FR32");
453   REG("RFP32");
454   REG("GR64");
455   REG("FR64");
456   REG("VR64");
457   REG("RFP64");
458   REG("RFP80");
459   REG("VR128");
460   REG("RST");
461   REG("SEGMENT_REG");
462   REG("DEBUG_REG");
463   REG("CONTROL_REG_32");
464   REG("CONTROL_REG_64");
465   
466   MEM("i8mem");
467   MEM("i8mem_NOREX");
468   MEM("i16mem");
469   MEM("i32mem");
470   MEM("f32mem");
471   MEM("ssmem");
472   MEM("opaque32mem");
473   MEM("opaque48mem");
474   MEM("i64mem");
475   MEM("f64mem");
476   MEM("sdmem");
477   MEM("f80mem");
478   MEM("opaque80mem");
479   MEM("i128mem");
480   MEM("f128mem");
481   MEM("opaque512mem");
482   
483   LEA("lea32mem");
484   LEA("lea64_32mem");
485   LEA("lea64mem");
486   
487   IMM("i8imm");
488   IMM("i16imm");
489   IMM("i16i8imm");
490   IMM("i32imm");
491   IMM("i32imm_pcrel");
492   IMM("i32i8imm");
493   IMM("i64imm");
494   IMM("i64i8imm");
495   IMM("i64i32imm");
496   IMM("i64i32imm_pcrel");
497   IMM("SSECC");
498   
499   PCR("brtarget8");
500   PCR("offset8");
501   PCR("offset16");
502   PCR("offset32");
503   PCR("offset64");
504   PCR("brtarget");
505   
506   return 1;
507 }
508
509 #undef REG
510 #undef MEM
511 #undef LEA
512 #undef IMM
513 #undef PCR
514 #undef ADDFLAG
515
516 /// X86PopulateOperands - Handles all the operands in an X86 instruction, adding
517 ///   the appropriate flags to their descriptors
518 ///
519 /// @operandFlags - A reference the array of operand flag objects
520 /// @inst         - The instruction to use as a source of information
521 static void X86PopulateOperands(
522   FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
523   const CodeGenInstruction &inst) {
524   if (!inst.TheDef->isSubClassOf("X86Inst"))
525     return;
526   
527   unsigned int index;
528   unsigned int numOperands = inst.OperandList.size();
529   
530   for (index = 0; index < numOperands; ++index) {
531     const CodeGenInstruction::OperandInfo &operandInfo = 
532       inst.OperandList[index];
533     Record &rec = *operandInfo.Rec;
534     
535     if (X86FlagFromOpName(operandFlags[index], rec.getName())) {
536       errs() << "Operand type: " << rec.getName().c_str() << "\n";
537       errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
538       errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
539       llvm_unreachable("Unhandled type");
540     }
541   }
542 }
543
544 /// decorate1 - Decorates a named operand with a new flag
545 ///
546 /// @operandFlags - The array of operand flag objects, which don't have names
547 /// @inst         - The CodeGenInstruction, which provides a way to translate
548 ///                 between names and operand indices
549 /// @opName       - The name of the operand
550 /// @flag         - The name of the flag to add
551 static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
552                              const CodeGenInstruction &inst,
553                              const char *opName,
554                              const char *opFlag) {
555   unsigned opIndex;
556   
557   try {
558     opIndex = inst.getOperandNamed(std::string(opName));
559   }
560   catch (...) {
561     errs() << "Instruction: " << inst.TheDef->getName().c_str() << "\n";
562     errs() << "Operand name: " << opName << "\n";
563     llvm_unreachable("Couldn't find operand");
564   }
565   
566   operandFlags[opIndex]->addEntry(opFlag);
567 }
568
569 #define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag)
570
571 #define MOV(source, target) {                       \
572   instFlags.addEntry("kInstructionFlagMove");       \
573   DECORATE1(source, "kOperandFlagSource");          \
574   DECORATE1(target, "kOperandFlagTarget");          \
575 }
576
577 #define BRANCH(target) {                            \
578   instFlags.addEntry("kInstructionFlagBranch");     \
579   DECORATE1(target, "kOperandFlagTarget");          \
580 }
581
582 #define PUSH(source) {                              \
583   instFlags.addEntry("kInstructionFlagPush");       \
584   DECORATE1(source, "kOperandFlagSource");          \
585 }
586
587 #define POP(target) {                               \
588   instFlags.addEntry("kInstructionFlagPop");        \
589   DECORATE1(target, "kOperandFlagTarget");          \
590 }
591
592 #define CALL(target) {                              \
593   instFlags.addEntry("kInstructionFlagCall");       \
594   DECORATE1(target, "kOperandFlagTarget");          \
595 }
596
597 #define RETURN() {                                  \
598   instFlags.addEntry("kInstructionFlagReturn");     \
599 }
600
601 /// X86ExtractSemantics - Performs various checks on the name of an X86
602 ///   instruction to determine what sort of an instruction it is and then adds 
603 ///   the appropriate flags to the instruction and its operands
604 ///
605 /// @arg instFlags    - A reference to the flags for the instruction as a whole
606 /// @arg operandFlags - A reference to the array of operand flag object pointers
607 /// @arg inst         - A reference to the original instruction
608 static void X86ExtractSemantics(FlagsConstantEmitter &instFlags,
609                                 FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
610                                 const CodeGenInstruction &inst) {
611   const std::string &name = inst.TheDef->getName();
612     
613   if (name.find("MOV") != name.npos) {
614     if (name.find("MOV_V") != name.npos) {
615       // ignore (this is a pseudoinstruction)
616     }
617     else if (name.find("MASK") != name.npos) {
618       // ignore (this is a masking move)
619     }
620     else if (name.find("r0") != name.npos) {
621       // ignore (this is a pseudoinstruction)
622     }
623     else if (name.find("PS") != name.npos ||
624              name.find("PD") != name.npos) {
625       // ignore (this is a shuffling move)
626     }
627     else if (name.find("MOVS") != name.npos) {
628       // ignore (this is a string move)
629     }
630     else if (name.find("_F") != name.npos) {
631       // TODO handle _F moves to ST(0)
632     }
633     else if (name.find("a") != name.npos) {
634       // TODO handle moves to/from %ax
635     }
636     else if (name.find("CMOV") != name.npos) {
637       MOV("src2", "dst");
638     }
639     else if (name.find("PC") != name.npos) {
640       MOV("label", "reg")
641     }
642     else {
643       MOV("src", "dst");
644     }
645   }
646   
647   if (name.find("JMP") != name.npos ||
648       name.find("J") == 0) {
649     if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
650       BRANCH("off");
651     }
652     else {
653       BRANCH("dst");
654     }
655   }
656   
657   if (name.find("PUSH") != name.npos) {
658     if (name.find("FS") != name.npos ||
659         name.find("GS") != name.npos) {
660       instFlags.addEntry("kInstructionFlagPush");
661       // TODO add support for fixed operands
662     }
663     else if (name.find("F") != name.npos) {
664       // ignore (this pushes onto the FP stack)
665     }
666     else if (name[name.length() - 1] == 'm') {
667       PUSH("src");
668     }
669     else if (name.find("i") != name.npos) {
670       PUSH("imm");
671     }
672     else {
673       PUSH("reg");
674     }
675   }
676   
677   if (name.find("POP") != name.npos) {
678     if (name.find("POPCNT") != name.npos) {
679       // ignore (not a real pop)
680     }
681     else if (name.find("FS") != name.npos ||
682              name.find("GS") != name.npos) {
683       instFlags.addEntry("kInstructionFlagPop");
684       // TODO add support for fixed operands
685     }
686     else if (name.find("F") != name.npos) {
687       // ignore (this pops from the FP stack)
688     }
689     else if (name[name.length() - 1] == 'm') {
690       POP("dst");
691     }
692     else {
693       POP("reg");
694     }
695   }
696   
697   if (name.find("CALL") != name.npos) {
698     if (name.find("ADJ") != name.npos) {
699       // ignore (not a call)
700     }
701     else if (name.find("SYSCALL") != name.npos) {
702       // ignore (doesn't go anywhere we know about)
703     }
704     else if (name.find("VMCALL") != name.npos) {
705       // ignore (rather different semantics than a regular call)
706     }
707     else if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
708       CALL("off");
709     }
710     else {
711       CALL("dst");
712     }
713   }
714   
715   if (name.find("RET") != name.npos) {
716     RETURN();
717   }
718 }
719
720 #undef MOV
721 #undef BRANCH
722 #undef PUSH
723 #undef POP
724 #undef CALL
725 #undef RETURN
726
727 #undef COND_DECORATE_2
728 #undef COND_DECORATE_1
729 #undef DECORATE1
730
731 /// populateInstInfo - Fills an array of InstInfos with information about each 
732 ///   instruction in a target
733 ///
734 /// @arg infoArray  - The array of InstInfo objects to populate
735 /// @arg target     - The CodeGenTarget to use as a source of instructions
736 static void populateInstInfo(CompoundConstantEmitter &infoArray,
737                              CodeGenTarget &target) {
738   std::vector<const CodeGenInstruction*> numberedInstructions;
739   target.getInstructionsByEnumValue(numberedInstructions);
740   
741   unsigned int index;
742   unsigned int numInstructions = numberedInstructions.size();
743   
744   for (index = 0; index < numInstructions; ++index) {
745     const CodeGenInstruction& inst = *numberedInstructions[index];
746     
747     CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
748     infoArray.addEntry(infoStruct);
749     
750     FlagsConstantEmitter *instFlags = new FlagsConstantEmitter;
751     infoStruct->addEntry(instFlags);
752     
753     LiteralConstantEmitter *numOperandsEmitter = 
754       new LiteralConstantEmitter(inst.OperandList.size());
755     infoStruct->addEntry(numOperandsEmitter);
756                          
757     CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
758     infoStruct->addEntry(operandFlagArray);
759         
760     FlagsConstantEmitter *operandFlags[MAX_OPERANDS];
761     
762     for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) {
763       operandFlags[operandIndex] = new FlagsConstantEmitter;
764       operandFlagArray->addEntry(operandFlags[operandIndex]);
765     }
766  
767     unsigned numSyntaxes = 0;
768     
769     if (target.getName() == "X86") {
770       X86PopulateOperands(operandFlags, inst);
771       X86ExtractSemantics(*instFlags, operandFlags, inst);
772       numSyntaxes = 2;
773     }
774     
775     CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
776     infoStruct->addEntry(operandOrderArray);
777     
778     for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) {
779       CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter;
780       operandOrderArray->addEntry(operandOrder);
781       
782       if (syntaxIndex < numSyntaxes) {
783         std::string asmString = inst.AsmString;
784         asmString = resolveBraces(asmString, syntaxIndex);
785         populateOperandOrder(operandOrder, asmString, inst);
786       }
787       else {
788         for (unsigned operandIndex = 0; 
789              operandIndex < MAX_OPERANDS; 
790              ++operandIndex) {
791           operandOrder->addEntry(new LiteralConstantEmitter("-1"));
792         }
793       }
794     }
795   }
796 }
797
798 void EDEmitter::run(raw_ostream &o) {
799   unsigned int i = 0;
800   
801   CompoundConstantEmitter infoArray;
802   CodeGenTarget target;
803   
804   populateInstInfo(infoArray, target);
805   
806   o << "InstInfo instInfo" << target.getName().c_str() << "[] = ";
807   infoArray.emit(o, i);
808   o << ";" << "\n";
809 }
810
811 void EDEmitter::runHeader(raw_ostream &o) {
812   EmitSourceFileHeader("Enhanced Disassembly Info Header", o);
813   
814   o << "#ifndef EDInfo_" << "\n";
815   o << "#define EDInfo_" << "\n";
816   o << "\n";
817   o << "#include <inttypes.h>" << "\n";
818   o << "\n";
819   o << "#define MAX_OPERANDS " << format("%d", MAX_OPERANDS) << "\n";
820   o << "#define MAX_SYNTAXES " << format("%d", MAX_SYNTAXES) << "\n";
821   o << "\n";
822   
823   unsigned int i = 0;
824   
825   EnumEmitter operandFlags("OperandFlags");
826   operandFlags.addEntry("kOperandFlagImmediate");
827   operandFlags.addEntry("kOperandFlagRegister");
828   operandFlags.addEntry("kOperandFlagMemory");
829   operandFlags.addEntry("kOperandFlagEffectiveAddress");
830   operandFlags.addEntry("kOperandFlagPCRelative");
831   operandFlags.addEntry("kOperandFlagSource");
832   operandFlags.addEntry("kOperandFlagTarget");
833   operandFlags.emitAsFlags(o, i);
834   
835   o << "\n";
836   
837   EnumEmitter instructionFlags("InstructionFlags");
838   instructionFlags.addEntry("kInstructionFlagMove");
839   instructionFlags.addEntry("kInstructionFlagBranch");
840   instructionFlags.addEntry("kInstructionFlagPush");
841   instructionFlags.addEntry("kInstructionFlagPop");
842   instructionFlags.addEntry("kInstructionFlagCall");
843   instructionFlags.addEntry("kInstructionFlagReturn");
844   instructionFlags.emitAsFlags(o, i);
845   
846   o << "\n";
847   
848   StructEmitter instInfo("InstInfo");
849   instInfo.addMember("uint32_t", "instructionFlags");
850   instInfo.addMember("uint8_t", "numOperands");
851   instInfo.addMember("uint8_t", "operandFlags[MAX_OPERANDS]");
852   instInfo.addMember("const char", "operandOrders[MAX_SYNTAXES][MAX_OPERANDS]");
853   instInfo.emit(o, i);
854   
855   o << "\n";
856   o << "#endif" << "\n";
857 }