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