Factor code out into a new getAllDerivedDefinitions method, which is generally useful
[oota-llvm.git] / utils / TableGen / CodeEmitterGen.cpp
1 //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
2 //
3 // FIXME: Document.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "CodeEmitterGen.h"
8 #include "Record.h"
9 #include "Support/Statistic.h"
10
11 bool CodeEmitterGen::run(std::ostream &o) {
12   std::vector<Record*> Insts;
13
14   const std::map<std::string, Record*> &Defs = Records.getDefs();
15
16   Records.getAllDerivedDefinitions("Instruction", Insts);
17
18   std::string Namespace = "V9::";
19   std::string ClassName = "SparcV9CodeEmitter::";
20
21   //const std::string &Namespace = Inst->getValue("Namespace")->getName();
22   o << "unsigned " << ClassName
23     << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
24     << "  unsigned Value = 0;\n"
25     << "  DEBUG(std::cerr << MI);\n"
26     << "  switch (MI.getOpcode()) {\n";
27   for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
28        I != E; ++I)
29   {
30     Record *R = *I;
31     o << "    case " << Namespace << R->getName() << ": {\n"
32       << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";
33
34     const RecordVal *InstVal = R->getValue("Inst");
35     if (!InstVal) {
36       std::cerr << "No 'Inst' record found in target description file!\n";
37       return true;
38     }
39
40     Init *InitVal = InstVal->getValue();
41     assert(dynamic_cast<BitsInit*>(InitVal) &&
42            "Can only handle undefined bits<> types!");
43     BitsInit *BI = (BitsInit*)InitVal;
44
45     unsigned Value = 0;
46     const std::vector<RecordVal> &Vals = R->getValues();
47
48     DEBUG(o << "      // prefilling: ");
49     // Start by filling in fixed values...
50     for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
51       if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
52         Value |= B->getValue() << (e-i-1);
53         DEBUG(o << B->getValue());
54       } else {
55         DEBUG(o << "0");
56       }
57     }
58     DEBUG(o << "\n");
59
60     DEBUG(o << "      // " << *InstVal << "\n");
61     o << "      Value = " << Value << "U;\n\n";
62     
63     // Loop over all of the fields in the instruction adding in any
64     // contributions to this value (due to bit references).
65     //
66     unsigned op = 0;
67     std::map<const std::string,unsigned> OpOrder;
68     std::map<const std::string,bool> OpContinuous;
69     for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
70       if (Vals[i].getName() != "Inst" && 
71           !Vals[i].getValue()->isComplete() &&
72           /* ignore annul and predict bits since no one sets them yet */
73           Vals[i].getName() != "annul" && 
74           Vals[i].getName() != "predict")
75       {
76         o << "      // op" << op << ": " << Vals[i].getName() << "\n"
77           << "      int64_t op" << op 
78           <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
79         //<< "      MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
80         OpOrder[Vals[i].getName()] = op++;
81
82         // Is the operand continuous? If so, we can just mask and OR it in
83         // instead of doing it bit-by-bit, saving a lot in runtime cost.        
84         const BitsInit *InstInit = BI;
85         int beginBitInVar = -1, endBitInVar = -1,
86           beginBitInInst = -1, endBitInInst = -1;
87         bool continuous = true;
88
89         for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
90           if (VarBitInit *VBI =
91               dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
92             TypedInit *TI = VBI->getVariable();
93             if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
94               // only process the current variable
95               if (VI->getName() != Vals[i].getName())
96                 continue;
97
98               if (beginBitInVar == -1)
99                 beginBitInVar = VBI->getBitNum();
100
101               if (endBitInVar == -1)
102                 endBitInVar = VBI->getBitNum();
103               else {
104                 if (endBitInVar == (int)VBI->getBitNum() + 1)
105                   endBitInVar = VBI->getBitNum();
106                 else {
107                   continuous = false;
108                   break;
109                 }
110               }
111
112               if (beginBitInInst == -1)
113                 beginBitInInst = bit;
114               if (endBitInInst == -1)
115                 endBitInInst = bit;
116               else {
117                 if (endBitInInst == bit + 1)
118                   endBitInInst = bit;
119                 else {
120                   continuous = false;
121                   break;
122                 }
123               }
124
125               // maintain same distance between bits in field and bits in
126               // instruction. if the relative distances stay the same
127               // throughout,
128               if ((beginBitInVar - (int)VBI->getBitNum()) !=
129                   (beginBitInInst - bit))
130               {
131                 continuous = false;
132                 break;
133               }
134             }
135           }
136         }
137
138         DEBUG(o << "      // Var: begin = " << beginBitInVar 
139                 << ", end = " << endBitInVar
140                 << "; Inst: begin = " << beginBitInInst
141                 << ", end = " << endBitInInst << "\n");
142
143         if (continuous) {
144           DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
145                   << "\n");
146           
147           // Mask off the right bits
148           // Low mask (ie. shift, if necessary)
149           if (endBitInVar != 0) {
150             o << "      op" << OpOrder[Vals[i].getName()]
151               << " >>= " << endBitInVar << ";\n";
152             beginBitInVar -= endBitInVar;
153             endBitInVar = 0;
154           }
155
156           // High mask
157           o << "      op" << OpOrder[Vals[i].getName()]
158             << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";
159
160           // Shift the value to the correct place (according to place in instr)
161           if (endBitInInst != 0)
162             o << "      op" << OpOrder[Vals[i].getName()]
163               << " <<= " << endBitInInst << ";\n";
164
165           // Just OR in the result
166           o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
167         }
168
169         // otherwise, will be taken care of in the loop below using this value:
170         OpContinuous[Vals[i].getName()] = continuous;
171       }
172     }
173
174     for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
175       if (Vals[f].getPrefix()) {
176         BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
177
178         // Scan through the field looking for bit initializers of the current
179         // variable...
180         for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
181           if (BitInit *BI=dynamic_cast<BitInit*>(FieldInitializer->getBit(i)))
182           {
183             DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
184           } else if (UnsetInit *UI =
185                      dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) {
186             DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
187           } else if (VarBitInit *VBI =
188                      dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
189             TypedInit *TI = VBI->getVariable();
190             if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
191               // If the bits of the field are laid out consecutively in the
192               // instruction, then instead of separately ORing in bits, just
193               // mask and shift the entire field for efficiency.
194               if (OpContinuous[VI->getName()]) {
195                 // already taken care of in the loop above, thus there is no
196                 // need to individually OR in the bits
197
198                 // for debugging, output the regular version anyway, commented
199                 DEBUG(o << "      // Value |= getValueBit(op"
200                         << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
201                         << ")" << " << " << i << ";\n");
202               } else {
203                 o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
204                   << ", " << VBI->getBitNum()
205                   << ")" << " << " << i << ";\n";
206               }
207             } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
208               // FIXME: implement this!
209               o << "FIELD INIT not implemented yet!\n";
210             } else {
211               o << "Error: UNIMPLEMENTED\n";
212             }
213           }
214         }
215       } else {
216         // ignore annul and predict bits since no one sets them yet
217         if (Vals[f].getName() == "annul" || Vals[f].getName() == "predict") {
218           o << "      // found " << Vals[f].getName() << "\n";
219         }
220       }
221     }
222
223     o << "      break;\n"
224       << "    }\n";
225   }
226
227   o << "  default:\n"
228     << "    DEBUG(std::cerr << \"Not supported instr: \" << MI << \"\\n\");\n"
229     << "    abort();\n"
230     << "  }\n"
231     << "  return Value;\n"
232     << "}\n";
233   return false;
234 }