6340a153a258c864a4b525840c205c399531ddac
[oota-llvm.git] / utils / TableGen / InstrInfoEmitter.cpp
1 //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This tablegen backend is responsible for emitting a description of the target
11 // instruction set for the code generator.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "InstrInfoEmitter.h"
16 #include "CodeGenTarget.h"
17 #include "Record.h"
18 using namespace llvm;
19
20 // runEnums - Print out enum values for all of the instructions.
21 void InstrInfoEmitter::runEnums(std::ostream &OS) {
22   EmitSourceFileHeader("Target Instruction Enum Values", OS);
23   OS << "namespace llvm {\n\n";
24
25   CodeGenTarget Target;
26
27   // We must emit the PHI opcode first...
28   Record *InstrInfo = Target.getInstructionSet();
29
30   std::string Namespace = Target.inst_begin()->second.Namespace;
31
32   if (!Namespace.empty())
33     OS << "namespace " << Namespace << " {\n";
34   OS << "  enum {\n";
35
36   std::vector<const CodeGenInstruction*> NumberedInstructions;
37   Target.getInstructionsByEnumValue(NumberedInstructions);
38
39   for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
40     OS << "    " << NumberedInstructions[i]->TheDef->getName()
41        << ", \t// " << i << "\n";
42   }
43   OS << "  };\n";
44   if (!Namespace.empty())
45     OS << "}\n";
46   OS << "} // End llvm namespace \n";
47 }
48
49 static std::vector<Record*> GetDefList(ListInit *LI, const std::string &Name) {
50   std::vector<Record*> Result;
51   for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
52     if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)))
53       Result.push_back(DI->getDef());
54     else
55       throw "Illegal value in '" + Name + "' list!";
56   return Result;
57 }
58
59 void InstrInfoEmitter::printDefList(const std::vector<Record*> &Uses,
60                                     unsigned Num, std::ostream &OS) const {
61   OS << "static const unsigned ImplicitList" << Num << "[] = { ";
62   for (unsigned i = 0, e = Uses.size(); i != e; ++i)
63     OS << getQualifiedName(Uses[i]) << ", ";
64   OS << "0 };\n";
65 }
66
67
68 // run - Emit the main instruction description records for the target...
69 void InstrInfoEmitter::run(std::ostream &OS) {
70   EmitSourceFileHeader("Target Instruction Descriptors", OS);
71   OS << "namespace llvm {\n\n";
72
73   CodeGenTarget Target;
74   const std::string &TargetName = Target.getName();
75   Record *InstrInfo = Target.getInstructionSet();
76   Record *PHI = InstrInfo->getValueAsDef("PHIInst");
77
78   // Emit empty implicit uses and defs lists
79   OS << "static const unsigned EmptyImpList[] = { 0 };\n";
80
81   // Keep track of all of the def lists we have emitted already.
82   std::map<std::vector<Record*>, unsigned> EmittedLists;
83   std::map<ListInit*, unsigned> ListNumbers;
84   unsigned ListNumber = 0;
85  
86   // Emit all of the instruction's implicit uses and defs.
87   for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
88          E = Target.inst_end(); II != E; ++II) {
89     Record *Inst = II->second.TheDef;
90     ListInit *LI = Inst->getValueAsListInit("Uses");
91     if (LI->getSize()) {
92       std::vector<Record*> Uses = GetDefList(LI, Inst->getName());
93       unsigned &IL = EmittedLists[Uses];
94       if (!IL) printDefList(Uses, IL = ++ListNumber, OS);
95       ListNumbers[LI] = IL;
96     }
97     LI = Inst->getValueAsListInit("Defs");
98     if (LI->getSize()) {
99       std::vector<Record*> Uses = GetDefList(LI, Inst->getName());
100       unsigned &IL = EmittedLists[Uses];
101       if (!IL) printDefList(Uses, IL = ++ListNumber, OS);
102       ListNumbers[LI] = IL;
103     }
104   }
105
106   OS << "\nstatic const TargetInstrDescriptor " << TargetName
107      << "Insts[] = {\n";
108   emitRecord(Target.getPHIInstruction(), 0, InstrInfo, ListNumbers, OS);
109
110   unsigned i = 0;
111   for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
112          E = Target.inst_end(); II != E; ++II)
113     if (II->second.TheDef != PHI)
114       emitRecord(II->second, ++i, InstrInfo, ListNumbers, OS);
115   OS << "};\n";
116   OS << "} // End llvm namespace \n";
117 }
118
119 void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
120                                   Record *InstrInfo,
121                                   std::map<ListInit*, unsigned> &ListNumbers,
122                                   std::ostream &OS) {
123   OS << "  { \"";
124   if (Inst.Name.empty())
125     OS << Inst.TheDef->getName();
126   else
127     OS << Inst.Name;
128   OS << "\",\t" << -1
129      //Inst.OperandList.size()
130      << ", -1, 0, false, 0, 0, 0, 0";
131
132   // Emit all of the target indepedent flags...
133   if (Inst.isReturn)     OS << "|M_RET_FLAG";
134   if (Inst.isBranch)     OS << "|M_BRANCH_FLAG";
135   if (Inst.isBarrier)    OS << "|M_BARRIER_FLAG";
136   if (Inst.hasDelaySlot) OS << "|M_DELAY_SLOT_FLAG";
137   if (Inst.isCall)       OS << "|M_CALL_FLAG";
138   if (Inst.isLoad)       OS << "|M_LOAD_FLAG";
139   if (Inst.isStore)      OS << "|M_STORE_FLAG";
140   if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG";
141   if (Inst.isConvertibleToThreeAddress) OS << "|M_CONVERTIBLE_TO_3_ADDR";
142   if (Inst.isCommutable) OS << "|M_COMMUTABLE";
143   if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
144   OS << ", 0";
145
146   // Emit all of the target-specific flags...
147   ListInit *LI    = InstrInfo->getValueAsListInit("TSFlagsFields");
148   ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts");
149   if (LI->getSize() != Shift->getSize())
150     throw "Lengths of " + InstrInfo->getName() +
151           ":(TargetInfoFields, TargetInfoPositions) must be equal!";
152
153   for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
154     emitShiftedValue(Inst.TheDef, dynamic_cast<StringInit*>(LI->getElement(i)),
155                      dynamic_cast<IntInit*>(Shift->getElement(i)), OS);
156
157   OS << ", ";
158
159   // Emit the implicit uses and defs lists...
160   LI = Inst.TheDef->getValueAsListInit("Uses");
161   if (!LI->getSize())
162     OS << "EmptyImpList, ";
163   else
164     OS << "ImplicitList" << ListNumbers[LI] << ", ";
165
166   LI = Inst.TheDef->getValueAsListInit("Defs");
167   if (!LI->getSize())
168     OS << "EmptyImpList ";
169   else
170     OS << "ImplicitList" << ListNumbers[LI] << " ";
171
172   OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
173 }
174
175 void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
176                                         IntInit *ShiftInt, std::ostream &OS) {
177   if (Val == 0 || ShiftInt == 0)
178     throw std::string("Illegal value or shift amount in TargetInfo*!");
179   RecordVal *RV = R->getValue(Val->getValue());
180   int Shift = ShiftInt->getValue();
181
182   if (RV == 0 || RV->getValue() == 0)
183     throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!";
184
185   Init *Value = RV->getValue();
186   if (BitInit *BI = dynamic_cast<BitInit*>(Value)) {
187     if (BI->getValue()) OS << "|(1<<" << Shift << ")";
188     return;
189   } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) {
190     // Convert the Bits to an integer to print...
191     Init *I = BI->convertInitializerTo(new IntRecTy());
192     if (I)
193       if (IntInit *II = dynamic_cast<IntInit*>(I)) {
194         if (II->getValue())
195           OS << "|(" << II->getValue() << "<<" << Shift << ")";
196         return;
197       }
198
199   } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) {
200     if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")";
201     return;
202   }
203
204   std::cerr << "Unhandled initializer: " << *Val << "\n";
205   throw "In record '" + R->getName() + "' for TSFlag emission.";
206 }
207