]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// |
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 the target | |
11 | // instruction set for the code generator. | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
15 | ||
16 | #include "CodeGenDAGPatterns.h" | |
17 | #include "CodeGenSchedule.h" | |
18 | #include "CodeGenTarget.h" | |
19 | #include "SequenceToOffsetTable.h" | |
970d7e83 | 20 | #include "TableGenBackends.h" |
223e47cc | 21 | #include "llvm/ADT/StringExtras.h" |
970d7e83 | 22 | #include "llvm/TableGen/Error.h" |
223e47cc LB |
23 | #include "llvm/TableGen/Record.h" |
24 | #include "llvm/TableGen/TableGenBackend.h" | |
25 | #include <algorithm> | |
26 | #include <cstdio> | |
27 | #include <map> | |
28 | #include <vector> | |
29 | using namespace llvm; | |
30 | ||
31 | namespace { | |
32 | class InstrInfoEmitter { | |
33 | RecordKeeper &Records; | |
34 | CodeGenDAGPatterns CDP; | |
35 | const CodeGenSchedModels &SchedModels; | |
36 | ||
37 | public: | |
38 | InstrInfoEmitter(RecordKeeper &R): | |
39 | Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {} | |
40 | ||
41 | // run - Output the instruction set description. | |
42 | void run(raw_ostream &OS); | |
43 | ||
44 | private: | |
45 | void emitEnums(raw_ostream &OS); | |
46 | ||
47 | typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; | |
1a4d82fc JJ |
48 | |
49 | /// The keys of this map are maps which have OpName enum values as their keys | |
50 | /// and instruction operand indices as their values. The values of this map | |
51 | /// are lists of instruction names. | |
52 | typedef std::map<std::map<unsigned, unsigned>, | |
53 | std::vector<std::string> > OpNameMapTy; | |
54 | typedef std::map<std::string, unsigned>::iterator StrUintMapIter; | |
223e47cc LB |
55 | void emitRecord(const CodeGenInstruction &Inst, unsigned Num, |
56 | Record *InstrInfo, | |
57 | std::map<std::vector<Record*>, unsigned> &EL, | |
58 | const OperandInfoMapTy &OpInfo, | |
59 | raw_ostream &OS); | |
1a4d82fc JJ |
60 | void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target); |
61 | void initOperandMapData( | |
62 | const std::vector<const CodeGenInstruction *> &NumberedInstructions, | |
63 | const std::string &Namespace, | |
64 | std::map<std::string, unsigned> &Operands, | |
65 | OpNameMapTy &OperandMap); | |
66 | void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target, | |
67 | const std::vector<const CodeGenInstruction*> &NumberedInstructions); | |
223e47cc LB |
68 | |
69 | // Operand information. | |
70 | void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); | |
71 | std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); | |
72 | }; | |
73 | } // End anonymous namespace | |
74 | ||
75 | static void PrintDefList(const std::vector<Record*> &Uses, | |
76 | unsigned Num, raw_ostream &OS) { | |
77 | OS << "static const uint16_t ImplicitList" << Num << "[] = { "; | |
78 | for (unsigned i = 0, e = Uses.size(); i != e; ++i) | |
79 | OS << getQualifiedName(Uses[i]) << ", "; | |
80 | OS << "0 };\n"; | |
81 | } | |
82 | ||
83 | //===----------------------------------------------------------------------===// | |
84 | // Operand Info Emission. | |
85 | //===----------------------------------------------------------------------===// | |
86 | ||
87 | std::vector<std::string> | |
88 | InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { | |
89 | std::vector<std::string> Result; | |
90 | ||
1a4d82fc | 91 | for (auto &Op : Inst.Operands) { |
223e47cc LB |
92 | // Handle aggregate operands and normal operands the same way by expanding |
93 | // either case into a list of operands for this op. | |
94 | std::vector<CGIOperandList::OperandInfo> OperandList; | |
95 | ||
96 | // This might be a multiple operand thing. Targets like X86 have | |
97 | // registers in their multi-operand operands. It may also be an anonymous | |
98 | // operand, which has a single operand, but no declared class for the | |
99 | // operand. | |
1a4d82fc | 100 | DagInit *MIOI = Op.MIOperandInfo; |
223e47cc LB |
101 | |
102 | if (!MIOI || MIOI->getNumArgs() == 0) { | |
103 | // Single, anonymous, operand. | |
1a4d82fc | 104 | OperandList.push_back(Op); |
223e47cc | 105 | } else { |
1a4d82fc JJ |
106 | for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { |
107 | OperandList.push_back(Op); | |
223e47cc | 108 | |
970d7e83 | 109 | Record *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); |
223e47cc LB |
110 | OperandList.back().Rec = OpR; |
111 | } | |
112 | } | |
113 | ||
114 | for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { | |
115 | Record *OpR = OperandList[j].Rec; | |
116 | std::string Res; | |
117 | ||
118 | if (OpR->isSubClassOf("RegisterOperand")) | |
119 | OpR = OpR->getValueAsDef("RegClass"); | |
120 | if (OpR->isSubClassOf("RegisterClass")) | |
121 | Res += getQualifiedName(OpR) + "RegClassID, "; | |
122 | else if (OpR->isSubClassOf("PointerLikeRegClass")) | |
123 | Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", "; | |
124 | else | |
125 | // -1 means the operand does not have a fixed register class. | |
126 | Res += "-1, "; | |
127 | ||
128 | // Fill in applicable flags. | |
129 | Res += "0"; | |
130 | ||
131 | // Ptr value whose register class is resolved via callback. | |
132 | if (OpR->isSubClassOf("PointerLikeRegClass")) | |
133 | Res += "|(1<<MCOI::LookupPtrRegClass)"; | |
134 | ||
135 | // Predicate operands. Check to see if the original unexpanded operand | |
1a4d82fc JJ |
136 | // was of type PredicateOp. |
137 | if (Op.Rec->isSubClassOf("PredicateOp")) | |
223e47cc LB |
138 | Res += "|(1<<MCOI::Predicate)"; |
139 | ||
140 | // Optional def operands. Check to see if the original unexpanded operand | |
141 | // was of type OptionalDefOperand. | |
1a4d82fc | 142 | if (Op.Rec->isSubClassOf("OptionalDefOperand")) |
223e47cc LB |
143 | Res += "|(1<<MCOI::OptionalDef)"; |
144 | ||
145 | // Fill in operand type. | |
85aaf69f | 146 | Res += ", "; |
1a4d82fc JJ |
147 | assert(!Op.OperandType.empty() && "Invalid operand type."); |
148 | Res += Op.OperandType; | |
223e47cc LB |
149 | |
150 | // Fill in constraint info. | |
151 | Res += ", "; | |
152 | ||
153 | const CGIOperandList::ConstraintInfo &Constraint = | |
1a4d82fc | 154 | Op.Constraints[j]; |
223e47cc LB |
155 | if (Constraint.isNone()) |
156 | Res += "0"; | |
157 | else if (Constraint.isEarlyClobber()) | |
158 | Res += "(1 << MCOI::EARLY_CLOBBER)"; | |
159 | else { | |
160 | assert(Constraint.isTied()); | |
161 | Res += "((" + utostr(Constraint.getTiedOperand()) + | |
162 | " << 16) | (1 << MCOI::TIED_TO))"; | |
163 | } | |
164 | ||
165 | Result.push_back(Res); | |
166 | } | |
167 | } | |
168 | ||
169 | return Result; | |
170 | } | |
171 | ||
172 | void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, | |
173 | OperandInfoMapTy &OperandInfoIDs) { | |
174 | // ID #0 is for no operand info. | |
175 | unsigned OperandListNum = 0; | |
176 | OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum; | |
177 | ||
178 | OS << "\n"; | |
179 | const CodeGenTarget &Target = CDP.getTargetInfo(); | |
1a4d82fc JJ |
180 | for (const CodeGenInstruction *Inst : Target.instructions()) { |
181 | std::vector<std::string> OperandInfo = GetOperandInfo(*Inst); | |
223e47cc LB |
182 | unsigned &N = OperandInfoIDs[OperandInfo]; |
183 | if (N != 0) continue; | |
184 | ||
185 | N = ++OperandListNum; | |
186 | OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; | |
1a4d82fc JJ |
187 | for (const std::string &Info : OperandInfo) |
188 | OS << "{ " << Info << " }, "; | |
189 | OS << "};\n"; | |
190 | } | |
191 | } | |
192 | ||
193 | ||
194 | /// Initialize data structures for generating operand name mappings. | |
195 | /// | |
196 | /// \param Operands [out] A map used to generate the OpName enum with operand | |
197 | /// names as its keys and operand enum values as its values. | |
198 | /// \param OperandMap [out] A map for representing the operand name mappings for | |
199 | /// each instructions. This is used to generate the OperandMap table as | |
200 | /// well as the getNamedOperandIdx() function. | |
201 | void InstrInfoEmitter::initOperandMapData( | |
202 | const std::vector<const CodeGenInstruction *> &NumberedInstructions, | |
203 | const std::string &Namespace, | |
204 | std::map<std::string, unsigned> &Operands, | |
205 | OpNameMapTy &OperandMap) { | |
206 | ||
207 | unsigned NumOperands = 0; | |
208 | for (const CodeGenInstruction *Inst : NumberedInstructions) { | |
209 | if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) | |
210 | continue; | |
211 | std::map<unsigned, unsigned> OpList; | |
212 | for (const auto &Info : Inst->Operands) { | |
213 | StrUintMapIter I = Operands.find(Info.Name); | |
214 | ||
215 | if (I == Operands.end()) { | |
216 | I = Operands.insert(Operands.begin(), | |
217 | std::pair<std::string, unsigned>(Info.Name, NumOperands++)); | |
218 | } | |
219 | OpList[I->second] = Info.MIOperandNo; | |
220 | } | |
221 | OperandMap[OpList].push_back(Namespace + "::" + Inst->TheDef->getName()); | |
222 | } | |
223 | } | |
224 | ||
225 | /// Generate a table and function for looking up the indices of operands by | |
226 | /// name. | |
227 | /// | |
228 | /// This code generates: | |
229 | /// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry | |
230 | /// for each operand name. | |
231 | /// - A 2-dimensional table called OperandMap for mapping OpName enum values to | |
232 | /// operand indices. | |
233 | /// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) | |
234 | /// for looking up the operand index for an instruction, given a value from | |
235 | /// OpName enum | |
236 | void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, | |
237 | const CodeGenTarget &Target, | |
238 | const std::vector<const CodeGenInstruction*> &NumberedInstructions) { | |
239 | ||
240 | const std::string &Namespace = Target.getInstNamespace(); | |
241 | std::string OpNameNS = "OpName"; | |
242 | // Map of operand names to their enumeration value. This will be used to | |
243 | // generate the OpName enum. | |
244 | std::map<std::string, unsigned> Operands; | |
245 | OpNameMapTy OperandMap; | |
246 | ||
247 | initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap); | |
248 | ||
249 | OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n"; | |
250 | OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n"; | |
251 | OS << "namespace llvm {"; | |
252 | OS << "namespace " << Namespace << " {\n"; | |
253 | OS << "namespace " << OpNameNS << " { \n"; | |
254 | OS << "enum {\n"; | |
255 | for (const auto &Op : Operands) | |
256 | OS << " " << Op.first << " = " << Op.second << ",\n"; | |
257 | ||
258 | OS << "OPERAND_LAST"; | |
259 | OS << "\n};\n"; | |
260 | OS << "} // End namespace OpName\n"; | |
261 | OS << "} // End namespace " << Namespace << "\n"; | |
262 | OS << "} // End namespace llvm\n"; | |
263 | OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n"; | |
264 | ||
265 | OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; | |
266 | OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; | |
267 | OS << "namespace llvm {"; | |
268 | OS << "namespace " << Namespace << " {\n"; | |
269 | OS << "LLVM_READONLY\n"; | |
270 | OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n"; | |
271 | if (!Operands.empty()) { | |
272 | OS << " static const int16_t OperandMap [][" << Operands.size() | |
273 | << "] = {\n"; | |
274 | for (const auto &Entry : OperandMap) { | |
275 | const std::map<unsigned, unsigned> &OpList = Entry.first; | |
276 | OS << "{"; | |
277 | ||
278 | // Emit a row of the OperandMap table | |
279 | for (unsigned i = 0, e = Operands.size(); i != e; ++i) | |
280 | OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", "; | |
281 | ||
282 | OS << "},\n"; | |
283 | } | |
223e47cc | 284 | OS << "};\n"; |
1a4d82fc JJ |
285 | |
286 | OS << " switch(Opcode) {\n"; | |
287 | unsigned TableIndex = 0; | |
288 | for (const auto &Entry : OperandMap) { | |
289 | for (const std::string &Name : Entry.second) | |
290 | OS << " case " << Name << ":\n"; | |
291 | ||
292 | OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n"; | |
293 | } | |
294 | OS << " default: return -1;\n"; | |
295 | OS << " }\n"; | |
296 | } else { | |
297 | // There are no operands, so no need to emit anything | |
298 | OS << " return -1;\n"; | |
223e47cc | 299 | } |
1a4d82fc JJ |
300 | OS << "}\n"; |
301 | OS << "} // End namespace " << Namespace << "\n"; | |
302 | OS << "} // End namespace llvm\n"; | |
303 | OS << "#endif //GET_INSTRINFO_NAMED_OPS\n"; | |
304 | ||
305 | } | |
306 | ||
307 | /// Generate an enum for all the operand types for this target, under the | |
308 | /// llvm::TargetNamespace::OpTypes namespace. | |
309 | /// Operand types are all definitions derived of the Operand Target.td class. | |
310 | void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, | |
311 | const CodeGenTarget &Target) { | |
312 | ||
313 | const std::string &Namespace = Target.getInstNamespace(); | |
314 | std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand"); | |
315 | ||
316 | OS << "\n#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; | |
317 | OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; | |
318 | OS << "namespace llvm {"; | |
319 | OS << "namespace " << Namespace << " {\n"; | |
320 | OS << "namespace OpTypes { \n"; | |
321 | OS << "enum OperandType {\n"; | |
322 | ||
323 | unsigned EnumVal = 0; | |
324 | for (const Record *Op : Operands) { | |
325 | if (!Op->isAnonymous()) | |
326 | OS << " " << Op->getName() << " = " << EnumVal << ",\n"; | |
327 | ++EnumVal; | |
328 | } | |
329 | ||
330 | OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; | |
331 | OS << "} // End namespace OpTypes\n"; | |
332 | OS << "} // End namespace " << Namespace << "\n"; | |
333 | OS << "} // End namespace llvm\n"; | |
334 | OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; | |
223e47cc LB |
335 | } |
336 | ||
337 | //===----------------------------------------------------------------------===// | |
338 | // Main Output. | |
339 | //===----------------------------------------------------------------------===// | |
340 | ||
341 | // run - Emit the main instruction description records for the target... | |
342 | void InstrInfoEmitter::run(raw_ostream &OS) { | |
343 | emitSourceFileHeader("Target Instruction Enum Values", OS); | |
344 | emitEnums(OS); | |
345 | ||
346 | emitSourceFileHeader("Target Instruction Descriptors", OS); | |
347 | ||
348 | OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n"; | |
349 | OS << "#undef GET_INSTRINFO_MC_DESC\n"; | |
350 | ||
351 | OS << "namespace llvm {\n\n"; | |
352 | ||
353 | CodeGenTarget &Target = CDP.getTargetInfo(); | |
354 | const std::string &TargetName = Target.getName(); | |
355 | Record *InstrInfo = Target.getInstructionSet(); | |
356 | ||
357 | // Keep track of all of the def lists we have emitted already. | |
358 | std::map<std::vector<Record*>, unsigned> EmittedLists; | |
359 | unsigned ListNumber = 0; | |
360 | ||
361 | // Emit all of the instruction's implicit uses and defs. | |
1a4d82fc JJ |
362 | for (const CodeGenInstruction *II : Target.instructions()) { |
363 | Record *Inst = II->TheDef; | |
223e47cc LB |
364 | std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); |
365 | if (!Uses.empty()) { | |
366 | unsigned &IL = EmittedLists[Uses]; | |
367 | if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS); | |
368 | } | |
369 | std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); | |
370 | if (!Defs.empty()) { | |
371 | unsigned &IL = EmittedLists[Defs]; | |
372 | if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); | |
373 | } | |
374 | } | |
375 | ||
376 | OperandInfoMapTy OperandInfoIDs; | |
377 | ||
378 | // Emit all of the operand info records. | |
379 | EmitOperandInfo(OS, OperandInfoIDs); | |
380 | ||
381 | // Emit all of the MCInstrDesc records in their ENUM ordering. | |
382 | // | |
383 | OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; | |
384 | const std::vector<const CodeGenInstruction*> &NumberedInstructions = | |
385 | Target.getInstructionsByEnumValue(); | |
386 | ||
223e47cc | 387 | SequenceToOffsetTable<std::string> InstrNames; |
1a4d82fc JJ |
388 | unsigned Num = 0; |
389 | for (const CodeGenInstruction *Inst : NumberedInstructions) { | |
390 | // Keep a list of the instruction names. | |
391 | InstrNames.add(Inst->TheDef->getName()); | |
392 | // Emit the record into the table. | |
393 | emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS); | |
223e47cc | 394 | } |
1a4d82fc | 395 | OS << "};\n\n"; |
223e47cc | 396 | |
1a4d82fc | 397 | // Emit the array of instruction names. |
223e47cc LB |
398 | InstrNames.layout(); |
399 | OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; | |
400 | InstrNames.emit(OS, printChar); | |
401 | OS << "};\n\n"; | |
402 | ||
403 | OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; | |
1a4d82fc JJ |
404 | Num = 0; |
405 | for (const CodeGenInstruction *Inst : NumberedInstructions) { | |
406 | // Newline every eight entries. | |
407 | if (Num % 8 == 0) | |
223e47cc | 408 | OS << "\n "; |
1a4d82fc JJ |
409 | OS << InstrNames.get(Inst->TheDef->getName()) << "U, "; |
410 | ++Num; | |
223e47cc LB |
411 | } |
412 | ||
413 | OS << "\n};\n\n"; | |
414 | ||
415 | // MCInstrInfo initialization routine. | |
416 | OS << "static inline void Init" << TargetName | |
417 | << "MCInstrInfo(MCInstrInfo *II) {\n"; | |
418 | OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " | |
419 | << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " | |
420 | << NumberedInstructions.size() << ");\n}\n\n"; | |
421 | ||
422 | OS << "} // End llvm namespace \n"; | |
423 | ||
424 | OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; | |
425 | ||
426 | // Create a TargetInstrInfo subclass to hide the MC layer initialization. | |
427 | OS << "\n#ifdef GET_INSTRINFO_HEADER\n"; | |
428 | OS << "#undef GET_INSTRINFO_HEADER\n"; | |
429 | ||
430 | std::string ClassName = TargetName + "GenInstrInfo"; | |
431 | OS << "namespace llvm {\n"; | |
970d7e83 | 432 | OS << "struct " << ClassName << " : public TargetInstrInfo {\n" |
223e47cc | 433 | << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" |
1a4d82fc | 434 | << " virtual ~" << ClassName << "();\n" |
223e47cc LB |
435 | << "};\n"; |
436 | OS << "} // End llvm namespace \n"; | |
437 | ||
438 | OS << "#endif // GET_INSTRINFO_HEADER\n\n"; | |
439 | ||
1a4d82fc JJ |
440 | OS << "\n#ifdef GET_INSTRINFO_CTOR_DTOR\n"; |
441 | OS << "#undef GET_INSTRINFO_CTOR_DTOR\n"; | |
223e47cc LB |
442 | |
443 | OS << "namespace llvm {\n"; | |
444 | OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; | |
445 | OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; | |
446 | OS << "extern const char " << TargetName << "InstrNameData[];\n"; | |
447 | OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" | |
970d7e83 | 448 | << " : TargetInstrInfo(SO, DO) {\n" |
223e47cc LB |
449 | << " InitMCInstrInfo(" << TargetName << "Insts, " |
450 | << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " | |
1a4d82fc JJ |
451 | << NumberedInstructions.size() << ");\n}\n" |
452 | << ClassName << "::~" << ClassName << "() {}\n"; | |
223e47cc LB |
453 | OS << "} // End llvm namespace \n"; |
454 | ||
1a4d82fc JJ |
455 | OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n"; |
456 | ||
457 | emitOperandNameMappings(OS, Target, NumberedInstructions); | |
458 | ||
459 | emitOperandTypesEnum(OS, Target); | |
223e47cc LB |
460 | } |
461 | ||
462 | void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, | |
463 | Record *InstrInfo, | |
464 | std::map<std::vector<Record*>, unsigned> &EmittedLists, | |
465 | const OperandInfoMapTy &OpInfo, | |
466 | raw_ostream &OS) { | |
467 | int MinOperands = 0; | |
970d7e83 | 468 | if (!Inst.Operands.empty()) |
223e47cc LB |
469 | // Each logical operand can be multiple MI operands. |
470 | MinOperands = Inst.Operands.back().MIOperandNo + | |
471 | Inst.Operands.back().MINumOperands; | |
472 | ||
473 | OS << " { "; | |
474 | OS << Num << ",\t" << MinOperands << ",\t" | |
475 | << Inst.Operands.NumDefs << ",\t" | |
476 | << SchedModels.getSchedClassIdx(Inst) << ",\t" | |
477 | << Inst.TheDef->getValueAsInt("Size") << ",\t0"; | |
478 | ||
479 | // Emit all of the target indepedent flags... | |
480 | if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)"; | |
481 | if (Inst.isReturn) OS << "|(1<<MCID::Return)"; | |
482 | if (Inst.isBranch) OS << "|(1<<MCID::Branch)"; | |
483 | if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)"; | |
484 | if (Inst.isCompare) OS << "|(1<<MCID::Compare)"; | |
485 | if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)"; | |
486 | if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)"; | |
487 | if (Inst.isSelect) OS << "|(1<<MCID::Select)"; | |
488 | if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)"; | |
489 | if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)"; | |
490 | if (Inst.isCall) OS << "|(1<<MCID::Call)"; | |
491 | if (Inst.canFoldAsLoad) OS << "|(1<<MCID::FoldableAsLoad)"; | |
492 | if (Inst.mayLoad) OS << "|(1<<MCID::MayLoad)"; | |
493 | if (Inst.mayStore) OS << "|(1<<MCID::MayStore)"; | |
494 | if (Inst.isPredicable) OS << "|(1<<MCID::Predicable)"; | |
495 | if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)"; | |
496 | if (Inst.isCommutable) OS << "|(1<<MCID::Commutable)"; | |
497 | if (Inst.isTerminator) OS << "|(1<<MCID::Terminator)"; | |
498 | if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)"; | |
499 | if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)"; | |
500 | if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)"; | |
501 | if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)"; | |
502 | if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)"; | |
503 | if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)"; | |
504 | if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)"; | |
505 | if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; | |
506 | if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; | |
507 | if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; | |
1a4d82fc JJ |
508 | if (Inst.isRegSequence) OS << "|(1<<MCID::RegSequence)"; |
509 | if (Inst.isExtractSubreg) OS << "|(1<<MCID::ExtractSubreg)"; | |
510 | if (Inst.isInsertSubreg) OS << "|(1<<MCID::InsertSubreg)"; | |
223e47cc LB |
511 | |
512 | // Emit all of the target-specific flags... | |
513 | BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); | |
970d7e83 LB |
514 | if (!TSF) |
515 | PrintFatalError("no TSFlags?"); | |
223e47cc LB |
516 | uint64_t Value = 0; |
517 | for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { | |
970d7e83 | 518 | if (BitInit *Bit = dyn_cast<BitInit>(TSF->getBit(i))) |
223e47cc LB |
519 | Value |= uint64_t(Bit->getValue()) << i; |
520 | else | |
970d7e83 | 521 | PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName()); |
223e47cc LB |
522 | } |
523 | OS << ", 0x"; | |
524 | OS.write_hex(Value); | |
525 | OS << "ULL, "; | |
526 | ||
527 | // Emit the implicit uses and defs lists... | |
528 | std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); | |
529 | if (UseList.empty()) | |
1a4d82fc | 530 | OS << "nullptr, "; |
223e47cc LB |
531 | else |
532 | OS << "ImplicitList" << EmittedLists[UseList] << ", "; | |
533 | ||
534 | std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); | |
535 | if (DefList.empty()) | |
1a4d82fc | 536 | OS << "nullptr, "; |
223e47cc LB |
537 | else |
538 | OS << "ImplicitList" << EmittedLists[DefList] << ", "; | |
539 | ||
540 | // Emit the operand info. | |
541 | std::vector<std::string> OperandInfo = GetOperandInfo(Inst); | |
542 | if (OperandInfo.empty()) | |
1a4d82fc | 543 | OS << "nullptr"; |
223e47cc LB |
544 | else |
545 | OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; | |
546 | ||
1a4d82fc JJ |
547 | CodeGenTarget &Target = CDP.getTargetInfo(); |
548 | if (Inst.HasComplexDeprecationPredicate) | |
549 | // Emit a function pointer to the complex predicate method. | |
550 | OS << ",0" | |
551 | << ",&get" << Inst.DeprecatedReason << "DeprecationInfo"; | |
552 | else if (!Inst.DeprecatedReason.empty()) | |
553 | // Emit the Subtarget feature. | |
554 | OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason | |
555 | << ",nullptr"; | |
556 | else | |
557 | // Instruction isn't deprecated. | |
558 | OS << ",0,nullptr"; | |
559 | ||
223e47cc LB |
560 | OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; |
561 | } | |
562 | ||
563 | // emitEnums - Print out enum values for all of the instructions. | |
564 | void InstrInfoEmitter::emitEnums(raw_ostream &OS) { | |
565 | ||
566 | OS << "\n#ifdef GET_INSTRINFO_ENUM\n"; | |
567 | OS << "#undef GET_INSTRINFO_ENUM\n"; | |
568 | ||
569 | OS << "namespace llvm {\n\n"; | |
570 | ||
571 | CodeGenTarget Target(Records); | |
572 | ||
573 | // We must emit the PHI opcode first... | |
574 | std::string Namespace = Target.getInstNamespace(); | |
575 | ||
576 | if (Namespace.empty()) { | |
577 | fprintf(stderr, "No instructions defined!\n"); | |
578 | exit(1); | |
579 | } | |
580 | ||
581 | const std::vector<const CodeGenInstruction*> &NumberedInstructions = | |
582 | Target.getInstructionsByEnumValue(); | |
583 | ||
584 | OS << "namespace " << Namespace << " {\n"; | |
585 | OS << " enum {\n"; | |
1a4d82fc JJ |
586 | unsigned Num = 0; |
587 | for (const CodeGenInstruction *Inst : NumberedInstructions) | |
588 | OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; | |
223e47cc | 589 | OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; |
85aaf69f | 590 | OS << " };\n\n"; |
1a4d82fc JJ |
591 | OS << "namespace Sched {\n"; |
592 | OS << " enum {\n"; | |
593 | Num = 0; | |
594 | for (const auto &Class : SchedModels.explicit_classes()) | |
595 | OS << " " << Class.Name << "\t= " << Num++ << ",\n"; | |
596 | OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; | |
85aaf69f SL |
597 | OS << " };\n"; |
598 | OS << "} // End Sched namespace\n"; | |
599 | OS << "} // End " << Namespace << " namespace\n"; | |
223e47cc LB |
600 | OS << "} // End llvm namespace \n"; |
601 | ||
602 | OS << "#endif // GET_INSTRINFO_ENUM\n\n"; | |
603 | } | |
604 | ||
605 | namespace llvm { | |
606 | ||
607 | void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { | |
608 | InstrInfoEmitter(RK).run(OS); | |
970d7e83 | 609 | EmitMapTable(RK, OS); |
223e47cc LB |
610 | } |
611 | ||
612 | } // End llvm namespace |