EDEmitter.cpp revision eaf1c98a7c38444d41d1c6dc2074736eec7d452f
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/MC/EDInstInfo.h"
23#include "llvm/Support/ErrorHandling.h"
24#include "llvm/Support/Format.h"
25#include "llvm/Support/raw_ostream.h"
26
27#include <map>
28#include <string>
29#include <vector>
30
31using namespace llvm;
32
33///////////////////////////////////////////////////////////
34// Support classes for emitting nested C data structures //
35///////////////////////////////////////////////////////////
36
37namespace {
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    typedef std::pair<const char*, const char*> member;
91    std::vector< member > Members;
92  public:
93    StructEmitter(const char *N) : Name(N) {
94    }
95    void addMember(const char *t, const char *n) {
96      member m(t, n);
97      Members.push_back(m);
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 = Members.size();
105      for (index = 0; index < numMembers; ++index) {
106        o.indent(i) << Members[index].first << " ";
107        o.indent(i) << Members[index].second << ";" << "\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    bool IsNumber;
124    union {
125      int Number;
126      const char* String;
127    };
128  public:
129    LiteralConstantEmitter(const char *string) :
130      IsNumber(false),
131      String(string) {
132    }
133    LiteralConstantEmitter(int number = 0) :
134      IsNumber(true),
135      Number(number) {
136    }
137    void set(const char *string) {
138      IsNumber = false;
139      Number = 0;
140      String = string;
141    }
142    void set(int number) {
143      IsNumber = true;
144      String = NULL;
145      Number = number;
146    }
147    bool is(const char *string) {
148      return !strcmp(String, string);
149    }
150    void emit(raw_ostream &o, unsigned int &i) {
151      if (IsNumber)
152        o << Number;
153      else
154        o << String;
155    }
156  };
157
158  class CompoundConstantEmitter : public ConstantEmitter {
159  private:
160    unsigned int Padding;
161    std::vector<ConstantEmitter *> Entries;
162  public:
163    CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) {
164    }
165    CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
166      Entries.push_back(e);
167
168      return *this;
169    }
170    ~CompoundConstantEmitter() {
171      while (Entries.size()) {
172        ConstantEmitter *entry = Entries.back();
173        Entries.pop_back();
174        delete entry;
175      }
176    }
177    void emit(raw_ostream &o, unsigned int &i) {
178      o << "{" << "\n";
179      i += 2;
180
181      unsigned int index;
182      unsigned int numEntries = Entries.size();
183
184      unsigned int numToPrint;
185
186      if (Padding) {
187        if (numEntries > Padding) {
188          fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding);
189          llvm_unreachable("More entries than padding");
190        }
191        numToPrint = Padding;
192      } else {
193        numToPrint = numEntries;
194      }
195
196      for (index = 0; index < numToPrint; ++index) {
197        o.indent(i);
198        if (index < numEntries)
199          Entries[index]->emit(o, i);
200        else
201          o << "-1";
202
203        if (index < (numToPrint - 1))
204          o << ",";
205        o << "\n";
206      }
207
208      i -= 2;
209      o.indent(i) << "}";
210    }
211  };
212
213  class FlagsConstantEmitter : public ConstantEmitter {
214  private:
215    std::vector<std::string> Flags;
216  public:
217    FlagsConstantEmitter() {
218    }
219    FlagsConstantEmitter &addEntry(const char *f) {
220      Flags.push_back(std::string(f));
221      return *this;
222    }
223    void emit(raw_ostream &o, unsigned int &i) {
224      unsigned int index;
225      unsigned int numFlags = Flags.size();
226      if (numFlags == 0)
227        o << "0";
228
229      for (index = 0; index < numFlags; ++index) {
230        o << Flags[index].c_str();
231        if (index < (numFlags - 1))
232          o << " | ";
233      }
234    }
235  };
236}
237
238EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
239}
240
241/// populateOperandOrder - Accepts a CodeGenInstruction and generates its
242///   AsmWriterInst for the desired assembly syntax, giving an ordered list of
243///   operands in the order they appear in the printed instruction.  Then, for
244///   each entry in that list, determines the index of the same operand in the
245///   CodeGenInstruction, and emits the resulting mapping into an array, filling
246///   in unused slots with -1.
247///
248/// @arg operandOrder - The array that will be populated with the operand
249///                     mapping.  Each entry will contain -1 (invalid index
250///                     into the operands present in the AsmString) or a number
251///                     representing an index in the operand descriptor array.
252/// @arg inst         - The instruction to use when looking up the operands
253/// @arg syntax       - The syntax to use, according to LLVM's enumeration
254void populateOperandOrder(CompoundConstantEmitter *operandOrder,
255                          const CodeGenInstruction &inst,
256                          unsigned syntax) {
257  unsigned int numArgs = 0;
258
259  AsmWriterInst awInst(inst, syntax, -1, -1);
260
261  std::vector<AsmWriterOperand>::iterator operandIterator;
262
263  for (operandIterator = awInst.Operands.begin();
264       operandIterator != awInst.Operands.end();
265       ++operandIterator) {
266    if (operandIterator->OperandType ==
267        AsmWriterOperand::isMachineInstrOperand) {
268      operandOrder->addEntry(
269        new LiteralConstantEmitter(operandIterator->CGIOpNo));
270      numArgs++;
271    }
272  }
273}
274
275/////////////////////////////////////////////////////
276// Support functions for handling X86 instructions //
277/////////////////////////////////////////////////////
278
279#define SET(flag) { type->set(flag); return 0; }
280
281#define REG(str) if (name == str) SET("kOperandTypeRegister");
282#define MEM(str) if (name == str) SET("kOperandTypeX86Memory");
283#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress");
284#define IMM(str) if (name == str) SET("kOperandTypeImmediate");
285#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative");
286
287/// X86TypeFromOpName - Processes the name of a single X86 operand (which is
288///   actually its type) and translates it into an operand type
289///
290/// @arg flags    - The type object to set
291/// @arg name     - The name of the operand
292static int X86TypeFromOpName(LiteralConstantEmitter *type,
293                             const std::string &name) {
294  REG("GR8");
295  REG("GR8_NOREX");
296  REG("GR16");
297  REG("GR32");
298  REG("GR32_NOREX");
299  REG("GR32_TC");
300  REG("FR32");
301  REG("RFP32");
302  REG("GR64");
303  REG("GR64_TC");
304  REG("FR64");
305  REG("VR64");
306  REG("RFP64");
307  REG("RFP80");
308  REG("VR128");
309  REG("VR256");
310  REG("RST");
311  REG("SEGMENT_REG");
312  REG("DEBUG_REG");
313  REG("CONTROL_REG");
314
315  IMM("i8imm");
316  IMM("i16imm");
317  IMM("i16i8imm");
318  IMM("i32imm");
319  IMM("i32i8imm");
320  IMM("i64imm");
321  IMM("i64i8imm");
322  IMM("i64i32imm");
323  IMM("SSECC");
324
325  // all R, I, R, I, R
326  MEM("i8mem");
327  MEM("i8mem_NOREX");
328  MEM("i16mem");
329  MEM("i32mem");
330  MEM("i32mem_TC");
331  MEM("f32mem");
332  MEM("ssmem");
333  MEM("opaque32mem");
334  MEM("opaque48mem");
335  MEM("i64mem");
336  MEM("i64mem_TC");
337  MEM("f64mem");
338  MEM("sdmem");
339  MEM("f80mem");
340  MEM("opaque80mem");
341  MEM("i128mem");
342  MEM("i256mem");
343  MEM("f128mem");
344  MEM("f256mem");
345  MEM("opaque512mem");
346
347  // all R, I, R, I
348  LEA("lea32mem");
349  LEA("lea64_32mem");
350  LEA("lea64mem");
351
352  // all I
353  PCR("i16imm_pcrel");
354  PCR("i32imm_pcrel");
355  PCR("i64i32imm_pcrel");
356  PCR("brtarget8");
357  PCR("offset8");
358  PCR("offset16");
359  PCR("offset32");
360  PCR("offset64");
361  PCR("brtarget");
362
363  return 1;
364}
365
366#undef REG
367#undef MEM
368#undef LEA
369#undef IMM
370#undef PCR
371
372#undef SET
373
374/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding
375///   the appropriate flags to their descriptors
376///
377/// @operandFlags - A reference the array of operand flag objects
378/// @inst         - The instruction to use as a source of information
379static void X86PopulateOperands(
380  LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
381  const CodeGenInstruction &inst) {
382  if (!inst.TheDef->isSubClassOf("X86Inst"))
383    return;
384
385  unsigned int index;
386  unsigned int numOperands = inst.OperandList.size();
387
388  for (index = 0; index < numOperands; ++index) {
389    const CodeGenInstruction::OperandInfo &operandInfo =
390      inst.OperandList[index];
391    Record &rec = *operandInfo.Rec;
392
393    if (X86TypeFromOpName(operandTypes[index], rec.getName())) {
394      errs() << "Operand type: " << rec.getName().c_str() << "\n";
395      errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
396      errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
397      llvm_unreachable("Unhandled type");
398    }
399  }
400}
401
402/// decorate1 - Decorates a named operand with a new flag
403///
404/// @operandFlags - The array of operand flag objects, which don't have names
405/// @inst         - The CodeGenInstruction, which provides a way to translate
406///                 between names and operand indices
407/// @opName       - The name of the operand
408/// @flag         - The name of the flag to add
409static inline void decorate1(
410  FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
411  const CodeGenInstruction &inst,
412  const char *opName,
413  const char *opFlag) {
414  unsigned opIndex;
415
416  opIndex = inst.getOperandNamed(std::string(opName));
417
418  operandFlags[opIndex]->addEntry(opFlag);
419}
420
421#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag)
422
423#define MOV(source, target) {               \
424  instType.set("kInstructionTypeMove");     \
425  DECORATE1(source, "kOperandFlagSource");  \
426  DECORATE1(target, "kOperandFlagTarget");  \
427}
428
429#define BRANCH(target) {                    \
430  instType.set("kInstructionTypeBranch");   \
431  DECORATE1(target, "kOperandFlagTarget");  \
432}
433
434#define PUSH(source) {                      \
435  instType.set("kInstructionTypePush");     \
436  DECORATE1(source, "kOperandFlagSource");  \
437}
438
439#define POP(target) {                       \
440  instType.set("kInstructionTypePop");      \
441  DECORATE1(target, "kOperandFlagTarget");  \
442}
443
444#define CALL(target) {                      \
445  instType.set("kInstructionTypeCall");     \
446  DECORATE1(target, "kOperandFlagTarget");  \
447}
448
449#define RETURN() {                          \
450  instType.set("kInstructionTypeReturn");   \
451}
452
453/// X86ExtractSemantics - Performs various checks on the name of an X86
454///   instruction to determine what sort of an instruction it is and then adds
455///   the appropriate flags to the instruction and its operands
456///
457/// @arg instType     - A reference to the type for the instruction as a whole
458/// @arg operandFlags - A reference to the array of operand flag object pointers
459/// @arg inst         - A reference to the original instruction
460static void X86ExtractSemantics(
461  LiteralConstantEmitter &instType,
462  FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
463  const CodeGenInstruction &inst) {
464  const std::string &name = inst.TheDef->getName();
465
466  if (name.find("MOV") != name.npos) {
467    if (name.find("MOV_V") != name.npos) {
468      // ignore (this is a pseudoinstruction)
469    } else if (name.find("MASK") != name.npos) {
470      // ignore (this is a masking move)
471    } else if (name.find("r0") != name.npos) {
472      // ignore (this is a pseudoinstruction)
473    } else if (name.find("PS") != name.npos ||
474             name.find("PD") != name.npos) {
475      // ignore (this is a shuffling move)
476    } else if (name.find("MOVS") != name.npos) {
477      // ignore (this is a string move)
478    } else if (name.find("_F") != name.npos) {
479      // TODO handle _F moves to ST(0)
480    } else if (name.find("a") != name.npos) {
481      // TODO handle moves to/from %ax
482    } else if (name.find("CMOV") != name.npos) {
483      MOV("src2", "dst");
484    } else if (name.find("PC") != name.npos) {
485      MOV("label", "reg")
486    } else {
487      MOV("src", "dst");
488    }
489  }
490
491  if (name.find("JMP") != name.npos ||
492      name.find("J") == 0) {
493    if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
494      BRANCH("off");
495    } else {
496      BRANCH("dst");
497    }
498  }
499
500  if (name.find("PUSH") != name.npos) {
501    if (name.find("FS") != name.npos ||
502        name.find("GS") != name.npos) {
503      instType.set("kInstructionTypePush");
504      // TODO add support for fixed operands
505    } else if (name.find("F") != name.npos) {
506      // ignore (this pushes onto the FP stack)
507    } else if (name.find("A") != name.npos) {
508      // ignore (pushes all GP registoers onto the stack)
509    } else if (name[name.length() - 1] == 'm') {
510      PUSH("src");
511    } else if (name.find("i") != name.npos) {
512      PUSH("imm");
513    } else {
514      PUSH("reg");
515    }
516  }
517
518  if (name.find("POP") != name.npos) {
519    if (name.find("POPCNT") != name.npos) {
520      // ignore (not a real pop)
521    } else if (name.find("FS") != name.npos ||
522             name.find("GS") != name.npos) {
523      instType.set("kInstructionTypePop");
524      // TODO add support for fixed operands
525    } else if (name.find("F") != name.npos) {
526      // ignore (this pops from the FP stack)
527    } else if (name.find("A") != name.npos) {
528      // ignore (pushes all GP registoers onto the stack)
529    } else if (name[name.length() - 1] == 'm') {
530      POP("dst");
531    } else {
532      POP("reg");
533    }
534  }
535
536  if (name.find("CALL") != name.npos) {
537    if (name.find("ADJ") != name.npos) {
538      // ignore (not a call)
539    } else if (name.find("SYSCALL") != name.npos) {
540      // ignore (doesn't go anywhere we know about)
541    } else if (name.find("VMCALL") != name.npos) {
542      // ignore (rather different semantics than a regular call)
543    } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
544      CALL("off");
545    } else {
546      CALL("dst");
547    }
548  }
549
550  if (name.find("RET") != name.npos) {
551    RETURN();
552  }
553}
554
555#undef MOV
556#undef BRANCH
557#undef PUSH
558#undef POP
559#undef CALL
560#undef RETURN
561
562/////////////////////////////////////////////////////
563// Support functions for handling ARM instructions //
564/////////////////////////////////////////////////////
565
566#define SET(flag) { type->set(flag); return 0; }
567
568#define REG(str)    if (name == str) SET("kOperandTypeRegister");
569#define IMM(str)    if (name == str) SET("kOperandTypeImmediate");
570
571#define MISC(str, type)   if (name == str) SET(type);
572
573/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is
574///   actually its type) and translates it into an operand type
575///
576/// @arg type     - The type object to set
577/// @arg name     - The name of the operand
578static int ARMFlagFromOpName(LiteralConstantEmitter *type,
579                             const std::string &name) {
580  REG("GPR");
581  REG("rGPR");
582  REG("tcGPR");
583  REG("cc_out");
584  REG("s_cc_out");
585  REG("tGPR");
586  REG("DPR");
587  REG("DPR_VFP2");
588  REG("DPR_8");
589  REG("SPR");
590  REG("QPR");
591  REG("QQPR");
592  REG("QQQQPR");
593
594  IMM("i32imm");
595  IMM("bf_inv_mask_imm");
596  IMM("jtblock_operand");
597  IMM("nohash_imm");
598  IMM("cpinst_operand");
599  IMM("cps_opt");
600  IMM("vfp_f64imm");
601  IMM("vfp_f32imm");
602  IMM("msr_mask");
603  IMM("neg_zero");
604  IMM("imm0_31");
605  IMM("nModImm");
606  IMM("imm0_4095");
607  IMM("jt2block_operand");
608  IMM("t_imm_s4");
609  IMM("pclabel");
610  IMM("sat_shift");
611
612  MISC("brtarget", "kOperandTypeARMBranchTarget");                // ?
613  MISC("so_reg", "kOperandTypeARMSoReg");                         // R, R, I
614  MISC("t2_so_reg", "kOperandTypeThumb2SoReg");                   // R, I
615  MISC("so_imm", "kOperandTypeARMSoImm");                         // I
616  MISC("t2_so_imm", "kOperandTypeThumb2SoImm");                   // I
617  MISC("so_imm2part", "kOperandTypeARMSoImm2Part");               // I
618  MISC("pred", "kOperandTypeARMPredicate");                       // I, R
619  MISC("it_pred", "kOperandTypeARMPredicate");                    // I
620  MISC("addrmode2", "kOperandTypeARMAddrMode2");                  // R, R, I
621  MISC("am2offset", "kOperandTypeARMAddrMode2Offset");            // R, I
622  MISC("addrmode3", "kOperandTypeARMAddrMode3");                  // R, R, I
623  MISC("am3offset", "kOperandTypeARMAddrMode3Offset");            // R, I
624  MISC("addrmode4", "kOperandTypeARMAddrMode4");                  // R, I
625  MISC("addrmode5", "kOperandTypeARMAddrMode5");                  // R, I
626  MISC("addrmode6", "kOperandTypeARMAddrMode6");                  // R, R, I, I
627  MISC("am6offset", "kOperandTypeARMAddrMode6Offset");            // R, I, I
628  MISC("addrmodepc", "kOperandTypeARMAddrModePC");                // R, I
629  MISC("reglist", "kOperandTypeARMRegisterList");                 // I, R, ...
630  MISC("it_mask", "kOperandTypeThumbITMask");                     // I
631  MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8");      // R, I
632  MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
633  MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12");    // R, I
634  MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg");   // R, R, I
635  MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4");  // R, I
636  MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
637                                                                  // R, I
638  MISC("tb_addrmode", "kOperandTypeARMTBAddrMode");               // I
639  MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1");           // R, I, R
640  MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2");           // R, I, R
641  MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4");           // R, I, R
642  MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR");           // R, R
643  MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP");           // R, I
644
645  return 1;
646}
647
648#undef SOREG
649#undef SOIMM
650#undef PRED
651#undef REG
652#undef MEM
653#undef LEA
654#undef IMM
655#undef PCR
656
657#undef SET
658
659/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding
660///   the appropriate flags to their descriptors
661///
662/// @operandFlags - A reference the array of operand flag objects
663/// @inst         - The instruction to use as a source of information
664static void ARMPopulateOperands(
665  LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
666  const CodeGenInstruction &inst) {
667  if (!inst.TheDef->isSubClassOf("InstARM") &&
668      !inst.TheDef->isSubClassOf("InstThumb"))
669    return;
670
671  unsigned int index;
672  unsigned int numOperands = inst.OperandList.size();
673
674  if (numOperands > EDIS_MAX_OPERANDS) {
675    errs() << "numOperands == " << numOperands << " > " <<
676      EDIS_MAX_OPERANDS << '\n';
677    llvm_unreachable("Too many operands");
678  }
679
680  for (index = 0; index < numOperands; ++index) {
681    const CodeGenInstruction::OperandInfo &operandInfo =
682    inst.OperandList[index];
683    Record &rec = *operandInfo.Rec;
684
685    if (ARMFlagFromOpName(operandTypes[index], rec.getName())) {
686      errs() << "Operand type: " << rec.getName() << '\n';
687      errs() << "Operand name: " << operandInfo.Name << '\n';
688      errs() << "Instruction mame: " << inst.TheDef->getName() << '\n';
689      llvm_unreachable("Unhandled type");
690    }
691  }
692}
693
694#define BRANCH(target) {                    \
695  instType.set("kInstructionTypeBranch");   \
696  DECORATE1(target, "kOperandFlagTarget");  \
697}
698
699/// ARMExtractSemantics - Performs various checks on the name of an ARM
700///   instruction to determine what sort of an instruction it is and then adds
701///   the appropriate flags to the instruction and its operands
702///
703/// @arg instType     - A reference to the type for the instruction as a whole
704/// @arg operandTypes - A reference to the array of operand type object pointers
705/// @arg operandFlags - A reference to the array of operand flag object pointers
706/// @arg inst         - A reference to the original instruction
707static void ARMExtractSemantics(
708  LiteralConstantEmitter &instType,
709  LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS],
710  FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
711  const CodeGenInstruction &inst) {
712  const std::string &name = inst.TheDef->getName();
713
714  if (name == "tBcc"   ||
715      name == "tB"     ||
716      name == "t2Bcc"  ||
717      name == "Bcc"    ||
718      name == "tCBZ"   ||
719      name == "tCBNZ") {
720    BRANCH("target");
721  }
722
723  if (name == "tBLr9"      ||
724      name == "BLr9_pred"  ||
725      name == "tBLXi_r9"   ||
726      name == "tBLXr_r9"   ||
727      name == "BLXr9"      ||
728      name == "t2BXJ"      ||
729      name == "BXJ") {
730    BRANCH("func");
731
732    unsigned opIndex;
733    opIndex = inst.getOperandNamed("func");
734    if (operandTypes[opIndex]->is("kOperandTypeImmediate"))
735      operandTypes[opIndex]->set("kOperandTypeARMBranchTarget");
736  }
737}
738
739#undef BRANCH
740
741/// populateInstInfo - Fills an array of InstInfos with information about each
742///   instruction in a target
743///
744/// @arg infoArray  - The array of InstInfo objects to populate
745/// @arg target     - The CodeGenTarget to use as a source of instructions
746static void populateInstInfo(CompoundConstantEmitter &infoArray,
747                             CodeGenTarget &target) {
748  const std::vector<const CodeGenInstruction*> &numberedInstructions =
749    target.getInstructionsByEnumValue();
750
751  unsigned int index;
752  unsigned int numInstructions = numberedInstructions.size();
753
754  for (index = 0; index < numInstructions; ++index) {
755    const CodeGenInstruction& inst = *numberedInstructions[index];
756
757    CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
758    infoArray.addEntry(infoStruct);
759
760    LiteralConstantEmitter *instType = new LiteralConstantEmitter;
761    infoStruct->addEntry(instType);
762
763    LiteralConstantEmitter *numOperandsEmitter =
764      new LiteralConstantEmitter(inst.OperandList.size());
765    infoStruct->addEntry(numOperandsEmitter);
766
767    CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter;
768    infoStruct->addEntry(operandTypeArray);
769
770    LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS];
771
772    CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
773    infoStruct->addEntry(operandFlagArray);
774
775    FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS];
776
777    for (unsigned operandIndex = 0;
778         operandIndex < EDIS_MAX_OPERANDS;
779         ++operandIndex) {
780      operandTypes[operandIndex] = new LiteralConstantEmitter;
781      operandTypeArray->addEntry(operandTypes[operandIndex]);
782
783      operandFlags[operandIndex] = new FlagsConstantEmitter;
784      operandFlagArray->addEntry(operandFlags[operandIndex]);
785    }
786
787    unsigned numSyntaxes = 0;
788
789    if (target.getName() == "X86") {
790      X86PopulateOperands(operandTypes, inst);
791      X86ExtractSemantics(*instType, operandFlags, inst);
792      numSyntaxes = 2;
793    }
794    else if (target.getName() == "ARM") {
795      ARMPopulateOperands(operandTypes, inst);
796      ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
797      numSyntaxes = 1;
798    }
799
800    CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
801
802    infoStruct->addEntry(operandOrderArray);
803
804    for (unsigned syntaxIndex = 0;
805         syntaxIndex < EDIS_MAX_SYNTAXES;
806         ++syntaxIndex) {
807      CompoundConstantEmitter *operandOrder =
808        new CompoundConstantEmitter(EDIS_MAX_OPERANDS);
809
810      operandOrderArray->addEntry(operandOrder);
811
812      if (syntaxIndex < numSyntaxes) {
813        populateOperandOrder(operandOrder, inst, syntaxIndex);
814      }
815    }
816
817    infoStruct = NULL;
818  }
819}
820
821static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
822  EnumEmitter operandTypes("OperandTypes");
823  operandTypes.addEntry("kOperandTypeNone");
824  operandTypes.addEntry("kOperandTypeImmediate");
825  operandTypes.addEntry("kOperandTypeRegister");
826  operandTypes.addEntry("kOperandTypeX86Memory");
827  operandTypes.addEntry("kOperandTypeX86EffectiveAddress");
828  operandTypes.addEntry("kOperandTypeX86PCRelative");
829  operandTypes.addEntry("kOperandTypeARMBranchTarget");
830  operandTypes.addEntry("kOperandTypeARMSoReg");
831  operandTypes.addEntry("kOperandTypeARMSoImm");
832  operandTypes.addEntry("kOperandTypeARMSoImm2Part");
833  operandTypes.addEntry("kOperandTypeARMPredicate");
834  operandTypes.addEntry("kOperandTypeARMAddrMode2");
835  operandTypes.addEntry("kOperandTypeARMAddrMode2Offset");
836  operandTypes.addEntry("kOperandTypeARMAddrMode3");
837  operandTypes.addEntry("kOperandTypeARMAddrMode3Offset");
838  operandTypes.addEntry("kOperandTypeARMAddrMode4");
839  operandTypes.addEntry("kOperandTypeARMAddrMode5");
840  operandTypes.addEntry("kOperandTypeARMAddrMode6");
841  operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
842  operandTypes.addEntry("kOperandTypeARMAddrModePC");
843  operandTypes.addEntry("kOperandTypeARMRegisterList");
844  operandTypes.addEntry("kOperandTypeARMTBAddrMode");
845  operandTypes.addEntry("kOperandTypeThumbITMask");
846  operandTypes.addEntry("kOperandTypeThumbAddrModeS1");
847  operandTypes.addEntry("kOperandTypeThumbAddrModeS2");
848  operandTypes.addEntry("kOperandTypeThumbAddrModeS4");
849  operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
850  operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
851  operandTypes.addEntry("kOperandTypeThumb2SoReg");
852  operandTypes.addEntry("kOperandTypeThumb2SoImm");
853  operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8");
854  operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset");
855  operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12");
856  operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg");
857  operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4");
858  operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset");
859  operandTypes.emit(o, i);
860
861  o << "\n";
862
863  EnumEmitter operandFlags("OperandFlags");
864  operandFlags.addEntry("kOperandFlagSource");
865  operandFlags.addEntry("kOperandFlagTarget");
866  operandFlags.emitAsFlags(o, i);
867
868  o << "\n";
869
870  EnumEmitter instructionTypes("InstructionTypes");
871  instructionTypes.addEntry("kInstructionTypeNone");
872  instructionTypes.addEntry("kInstructionTypeMove");
873  instructionTypes.addEntry("kInstructionTypeBranch");
874  instructionTypes.addEntry("kInstructionTypePush");
875  instructionTypes.addEntry("kInstructionTypePop");
876  instructionTypes.addEntry("kInstructionTypeCall");
877  instructionTypes.addEntry("kInstructionTypeReturn");
878  instructionTypes.emit(o, i);
879
880  o << "\n";
881}
882
883void EDEmitter::run(raw_ostream &o) {
884  unsigned int i = 0;
885
886  CompoundConstantEmitter infoArray;
887  CodeGenTarget target;
888
889  populateInstInfo(infoArray, target);
890
891  emitCommonEnums(o, i);
892
893  o << "namespace {\n";
894
895  o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = ";
896  infoArray.emit(o, i);
897  o << ";" << "\n";
898
899  o << "}\n";
900}
901