1 | //===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This tablegen backend is responsible for emitting a description of the target |
10 | // instruction set for the code generator. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "Basic/SequenceToOffsetTable.h" |
15 | #include "Common/CodeGenDAGPatterns.h" |
16 | #include "Common/CodeGenInstruction.h" |
17 | #include "Common/CodeGenSchedule.h" |
18 | #include "Common/CodeGenTarget.h" |
19 | #include "Common/PredicateExpander.h" |
20 | #include "Common/SubtargetFeatureInfo.h" |
21 | #include "Common/Types.h" |
22 | #include "TableGenBackends.h" |
23 | #include "llvm/ADT/ArrayRef.h" |
24 | #include "llvm/ADT/STLExtras.h" |
25 | #include "llvm/ADT/SmallVector.h" |
26 | #include "llvm/ADT/StringExtras.h" |
27 | #include "llvm/Support/Casting.h" |
28 | #include "llvm/Support/raw_ostream.h" |
29 | #include "llvm/TableGen/Error.h" |
30 | #include "llvm/TableGen/Record.h" |
31 | #include "llvm/TableGen/TableGenBackend.h" |
32 | #include <cassert> |
33 | #include <cstdint> |
34 | #include <iterator> |
35 | #include <map> |
36 | #include <string> |
37 | #include <utility> |
38 | #include <vector> |
39 | |
40 | using namespace llvm; |
41 | |
42 | cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info" ); |
43 | static cl::opt<bool> ExpandMIOperandInfo( |
44 | "instr-info-expand-mi-operand-info" , |
45 | cl::desc("Expand operand's MIOperandInfo DAG into suboperands" ), |
46 | cl::cat(InstrInfoEmitterCat), cl::init(Val: true)); |
47 | |
48 | namespace { |
49 | |
50 | class InstrInfoEmitter { |
51 | RecordKeeper &Records; |
52 | CodeGenDAGPatterns CDP; |
53 | const CodeGenSchedModels &SchedModels; |
54 | |
55 | public: |
56 | InstrInfoEmitter(RecordKeeper &R) |
57 | : Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {} |
58 | |
59 | // run - Output the instruction set description. |
60 | void run(raw_ostream &OS); |
61 | |
62 | private: |
63 | void emitEnums(raw_ostream &OS); |
64 | |
65 | typedef std::vector<std::string> OperandInfoTy; |
66 | typedef std::vector<OperandInfoTy> OperandInfoListTy; |
67 | typedef std::map<OperandInfoTy, unsigned> OperandInfoMapTy; |
68 | |
69 | /// The keys of this map are maps which have OpName enum values as their keys |
70 | /// and instruction operand indices as their values. The values of this map |
71 | /// are lists of instruction names. |
72 | typedef std::map<std::map<unsigned, unsigned>, std::vector<std::string>> |
73 | OpNameMapTy; |
74 | typedef std::map<std::string, unsigned>::iterator StrUintMapIter; |
75 | |
76 | /// Generate member functions in the target-specific GenInstrInfo class. |
77 | /// |
78 | /// This method is used to custom expand TIIPredicate definitions. |
79 | /// See file llvm/Target/TargetInstPredicates.td for a description of what is |
80 | /// a TIIPredicate and how to use it. |
81 | void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName, |
82 | bool ExpandDefinition = true); |
83 | |
84 | /// Expand TIIPredicate definitions to functions that accept a const MCInst |
85 | /// reference. |
86 | void emitMCIIHelperMethods(raw_ostream &OS, StringRef TargetName); |
87 | |
88 | /// Write verifyInstructionPredicates methods. |
89 | void emitFeatureVerifier(raw_ostream &OS, const CodeGenTarget &Target); |
90 | void emitRecord(const CodeGenInstruction &Inst, unsigned Num, |
91 | Record *InstrInfo, |
92 | std::map<std::vector<Record *>, unsigned> &EL, |
93 | const OperandInfoMapTy &OperandInfo, raw_ostream &OS); |
94 | void emitOperandTypeMappings( |
95 | raw_ostream &OS, const CodeGenTarget &Target, |
96 | ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
97 | void |
98 | initOperandMapData(ArrayRef<const CodeGenInstruction *> NumberedInstructions, |
99 | StringRef Namespace, |
100 | std::map<std::string, unsigned> &Operands, |
101 | OpNameMapTy &OperandMap); |
102 | void emitOperandNameMappings( |
103 | raw_ostream &OS, const CodeGenTarget &Target, |
104 | ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
105 | |
106 | void emitLogicalOperandSizeMappings( |
107 | raw_ostream &OS, StringRef Namespace, |
108 | ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
109 | void emitLogicalOperandTypeMappings( |
110 | raw_ostream &OS, StringRef Namespace, |
111 | ArrayRef<const CodeGenInstruction *> NumberedInstructions); |
112 | |
113 | // Operand information. |
114 | unsigned CollectOperandInfo(OperandInfoListTy &OperandInfoList, |
115 | OperandInfoMapTy &OperandInfoMap); |
116 | void EmitOperandInfo(raw_ostream &OS, OperandInfoListTy &OperandInfoList); |
117 | OperandInfoTy GetOperandInfo(const CodeGenInstruction &Inst); |
118 | }; |
119 | |
120 | } // end anonymous namespace |
121 | |
122 | //===----------------------------------------------------------------------===// |
123 | // Operand Info Emission. |
124 | //===----------------------------------------------------------------------===// |
125 | |
126 | InstrInfoEmitter::OperandInfoTy |
127 | InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { |
128 | OperandInfoTy Result; |
129 | |
130 | for (auto &Op : Inst.Operands) { |
131 | // Handle aggregate operands and normal operands the same way by expanding |
132 | // either case into a list of operands for this op. |
133 | std::vector<CGIOperandList::OperandInfo> OperandList; |
134 | |
135 | // This might be a multiple operand thing. Targets like X86 have |
136 | // registers in their multi-operand operands. It may also be an anonymous |
137 | // operand, which has a single operand, but no declared class for the |
138 | // operand. |
139 | DagInit *MIOI = Op.MIOperandInfo; |
140 | |
141 | if (!MIOI || MIOI->getNumArgs() == 0) { |
142 | // Single, anonymous, operand. |
143 | OperandList.push_back(x: Op); |
144 | } else { |
145 | for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { |
146 | OperandList.push_back(x: Op); |
147 | |
148 | auto *OpR = cast<DefInit>(Val: MIOI->getArg(Num: j))->getDef(); |
149 | OperandList.back().Rec = OpR; |
150 | } |
151 | } |
152 | |
153 | for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { |
154 | Record *OpR = OperandList[j].Rec; |
155 | std::string Res; |
156 | |
157 | if (OpR->isSubClassOf(Name: "RegisterOperand" )) |
158 | OpR = OpR->getValueAsDef(FieldName: "RegClass" ); |
159 | if (OpR->isSubClassOf(Name: "RegisterClass" )) |
160 | Res += getQualifiedName(R: OpR) + "RegClassID, " ; |
161 | else if (OpR->isSubClassOf(Name: "PointerLikeRegClass" )) |
162 | Res += utostr(X: OpR->getValueAsInt(FieldName: "RegClassKind" )) + ", " ; |
163 | else |
164 | // -1 means the operand does not have a fixed register class. |
165 | Res += "-1, " ; |
166 | |
167 | // Fill in applicable flags. |
168 | Res += "0" ; |
169 | |
170 | // Ptr value whose register class is resolved via callback. |
171 | if (OpR->isSubClassOf(Name: "PointerLikeRegClass" )) |
172 | Res += "|(1<<MCOI::LookupPtrRegClass)" ; |
173 | |
174 | // Predicate operands. Check to see if the original unexpanded operand |
175 | // was of type PredicateOp. |
176 | if (Op.Rec->isSubClassOf(Name: "PredicateOp" )) |
177 | Res += "|(1<<MCOI::Predicate)" ; |
178 | |
179 | // Optional def operands. Check to see if the original unexpanded operand |
180 | // was of type OptionalDefOperand. |
181 | if (Op.Rec->isSubClassOf(Name: "OptionalDefOperand" )) |
182 | Res += "|(1<<MCOI::OptionalDef)" ; |
183 | |
184 | // Branch target operands. Check to see if the original unexpanded |
185 | // operand was of type BranchTargetOperand. |
186 | if (Op.Rec->isSubClassOf(Name: "BranchTargetOperand" )) |
187 | Res += "|(1<<MCOI::BranchTarget)" ; |
188 | |
189 | // Fill in operand type. |
190 | Res += ", " ; |
191 | assert(!Op.OperandType.empty() && "Invalid operand type." ); |
192 | Res += Op.OperandType; |
193 | |
194 | // Fill in constraint info. |
195 | Res += ", " ; |
196 | |
197 | const CGIOperandList::ConstraintInfo &Constraint = Op.Constraints[j]; |
198 | if (Constraint.isNone()) |
199 | Res += "0" ; |
200 | else if (Constraint.isEarlyClobber()) |
201 | Res += "MCOI_EARLY_CLOBBER" ; |
202 | else { |
203 | assert(Constraint.isTied()); |
204 | Res += "MCOI_TIED_TO(" + utostr(X: Constraint.getTiedOperand()) + ")" ; |
205 | } |
206 | |
207 | Result.push_back(x: Res); |
208 | } |
209 | } |
210 | |
211 | return Result; |
212 | } |
213 | |
214 | unsigned |
215 | InstrInfoEmitter::CollectOperandInfo(OperandInfoListTy &OperandInfoList, |
216 | OperandInfoMapTy &OperandInfoMap) { |
217 | const CodeGenTarget &Target = CDP.getTargetInfo(); |
218 | unsigned Offset = 0; |
219 | for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { |
220 | OperandInfoTy OperandInfo = GetOperandInfo(Inst: *Inst); |
221 | if (OperandInfoMap.insert(x: {OperandInfo, Offset}).second) { |
222 | OperandInfoList.push_back(x: OperandInfo); |
223 | Offset += OperandInfo.size(); |
224 | } |
225 | } |
226 | return Offset; |
227 | } |
228 | |
229 | void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, |
230 | OperandInfoListTy &OperandInfoList) { |
231 | unsigned Offset = 0; |
232 | for (auto &OperandInfo : OperandInfoList) { |
233 | OS << " /* " << Offset << " */" ; |
234 | for (auto &Info : OperandInfo) |
235 | OS << " { " << Info << " }," ; |
236 | OS << '\n'; |
237 | Offset += OperandInfo.size(); |
238 | } |
239 | } |
240 | |
241 | /// Initialize data structures for generating operand name mappings. |
242 | /// |
243 | /// \param Operands [out] A map used to generate the OpName enum with operand |
244 | /// names as its keys and operand enum values as its values. |
245 | /// \param OperandMap [out] A map for representing the operand name mappings for |
246 | /// each instructions. This is used to generate the OperandMap table as |
247 | /// well as the getNamedOperandIdx() function. |
248 | void InstrInfoEmitter::initOperandMapData( |
249 | ArrayRef<const CodeGenInstruction *> NumberedInstructions, |
250 | StringRef Namespace, std::map<std::string, unsigned> &Operands, |
251 | OpNameMapTy &OperandMap) { |
252 | unsigned NumOperands = 0; |
253 | for (const CodeGenInstruction *Inst : NumberedInstructions) { |
254 | if (!Inst->TheDef->getValueAsBit(FieldName: "UseNamedOperandTable" )) |
255 | continue; |
256 | std::map<unsigned, unsigned> OpList; |
257 | for (const auto &Info : Inst->Operands) { |
258 | StrUintMapIter I = Operands.find(x: Info.Name); |
259 | |
260 | if (I == Operands.end()) { |
261 | I = Operands.insert(position: Operands.begin(), x: std::pair<std::string, unsigned>( |
262 | Info.Name, NumOperands++)); |
263 | } |
264 | OpList[I->second] = Info.MIOperandNo; |
265 | } |
266 | OperandMap[OpList].push_back(x: Namespace.str() + |
267 | "::" + Inst->TheDef->getName().str()); |
268 | } |
269 | } |
270 | |
271 | /// Generate a table and function for looking up the indices of operands by |
272 | /// name. |
273 | /// |
274 | /// This code generates: |
275 | /// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry |
276 | /// for each operand name. |
277 | /// - A 2-dimensional table called OperandMap for mapping OpName enum values to |
278 | /// operand indices. |
279 | /// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) |
280 | /// for looking up the operand index for an instruction, given a value from |
281 | /// OpName enum |
282 | void InstrInfoEmitter::emitOperandNameMappings( |
283 | raw_ostream &OS, const CodeGenTarget &Target, |
284 | ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
285 | StringRef Namespace = Target.getInstNamespace(); |
286 | std::string OpNameNS = "OpName" ; |
287 | // Map of operand names to their enumeration value. This will be used to |
288 | // generate the OpName enum. |
289 | std::map<std::string, unsigned> Operands; |
290 | OpNameMapTy OperandMap; |
291 | |
292 | initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap); |
293 | |
294 | OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n" ; |
295 | OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n" ; |
296 | OS << "namespace llvm {\n" ; |
297 | OS << "namespace " << Namespace << " {\n" ; |
298 | OS << "namespace " << OpNameNS << " {\n" ; |
299 | OS << "enum {\n" ; |
300 | for (const auto &Op : Operands) |
301 | OS << " " << Op.first << " = " << Op.second << ",\n" ; |
302 | |
303 | OS << " OPERAND_LAST" ; |
304 | OS << "\n};\n" ; |
305 | OS << "} // end namespace OpName\n" ; |
306 | OS << "} // end namespace " << Namespace << "\n" ; |
307 | OS << "} // end namespace llvm\n" ; |
308 | OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n" ; |
309 | |
310 | OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n" ; |
311 | OS << "#undef GET_INSTRINFO_NAMED_OPS\n" ; |
312 | OS << "namespace llvm {\n" ; |
313 | OS << "namespace " << Namespace << " {\n" ; |
314 | OS << "LLVM_READONLY\n" ; |
315 | OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n" ; |
316 | if (!Operands.empty()) { |
317 | OS << " static const int16_t OperandMap [][" << Operands.size() |
318 | << "] = {\n" ; |
319 | for (const auto &Entry : OperandMap) { |
320 | const std::map<unsigned, unsigned> &OpList = Entry.first; |
321 | OS << "{" ; |
322 | |
323 | // Emit a row of the OperandMap table |
324 | for (unsigned i = 0, e = Operands.size(); i != e; ++i) |
325 | OS << (OpList.count(x: i) == 0 ? -1 : (int)OpList.find(x: i)->second) << ", " ; |
326 | |
327 | OS << "},\n" ; |
328 | } |
329 | OS << "};\n" ; |
330 | |
331 | OS << " switch(Opcode) {\n" ; |
332 | unsigned TableIndex = 0; |
333 | for (const auto &Entry : OperandMap) { |
334 | for (const std::string &Name : Entry.second) |
335 | OS << " case " << Name << ":\n" ; |
336 | |
337 | OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n" ; |
338 | } |
339 | OS << " default: return -1;\n" ; |
340 | OS << " }\n" ; |
341 | } else { |
342 | // There are no operands, so no need to emit anything |
343 | OS << " return -1;\n" ; |
344 | } |
345 | OS << "}\n" ; |
346 | OS << "} // end namespace " << Namespace << "\n" ; |
347 | OS << "} // end namespace llvm\n" ; |
348 | OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n" ; |
349 | } |
350 | |
351 | /// Generate an enum for all the operand types for this target, under the |
352 | /// llvm::TargetNamespace::OpTypes namespace. |
353 | /// Operand types are all definitions derived of the Operand Target.td class. |
354 | void InstrInfoEmitter::emitOperandTypeMappings( |
355 | raw_ostream &OS, const CodeGenTarget &Target, |
356 | ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
357 | |
358 | StringRef Namespace = Target.getInstNamespace(); |
359 | std::vector<Record *> Operands = Records.getAllDerivedDefinitions(ClassName: "Operand" ); |
360 | std::vector<Record *> RegisterOperands = |
361 | Records.getAllDerivedDefinitions(ClassName: "RegisterOperand" ); |
362 | std::vector<Record *> RegisterClasses = |
363 | Records.getAllDerivedDefinitions(ClassName: "RegisterClass" ); |
364 | |
365 | OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n" ; |
366 | OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n" ; |
367 | OS << "namespace llvm {\n" ; |
368 | OS << "namespace " << Namespace << " {\n" ; |
369 | OS << "namespace OpTypes {\n" ; |
370 | OS << "enum OperandType {\n" ; |
371 | |
372 | unsigned EnumVal = 0; |
373 | for (const std::vector<Record *> *RecordsToAdd : |
374 | {&Operands, &RegisterOperands, &RegisterClasses}) { |
375 | for (const Record *Op : *RecordsToAdd) { |
376 | if (!Op->isAnonymous()) |
377 | OS << " " << Op->getName() << " = " << EnumVal << ",\n" ; |
378 | ++EnumVal; |
379 | } |
380 | } |
381 | |
382 | OS << " OPERAND_TYPE_LIST_END" |
383 | << "\n};\n" ; |
384 | OS << "} // end namespace OpTypes\n" ; |
385 | OS << "} // end namespace " << Namespace << "\n" ; |
386 | OS << "} // end namespace llvm\n" ; |
387 | OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n" ; |
388 | |
389 | OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n" ; |
390 | OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n" ; |
391 | OS << "namespace llvm {\n" ; |
392 | OS << "namespace " << Namespace << " {\n" ; |
393 | OS << "LLVM_READONLY\n" ; |
394 | OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n" ; |
395 | auto getInstrName = [&](int I) -> StringRef { |
396 | return NumberedInstructions[I]->TheDef->getName(); |
397 | }; |
398 | // TODO: Factor out duplicate operand lists to compress the tables. |
399 | if (!NumberedInstructions.empty()) { |
400 | std::vector<int> OperandOffsets; |
401 | std::vector<Record *> OperandRecords; |
402 | int CurrentOffset = 0; |
403 | for (const CodeGenInstruction *Inst : NumberedInstructions) { |
404 | OperandOffsets.push_back(x: CurrentOffset); |
405 | for (const auto &Op : Inst->Operands) { |
406 | const DagInit *MIOI = Op.MIOperandInfo; |
407 | if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) { |
408 | // Single, anonymous, operand. |
409 | OperandRecords.push_back(x: Op.Rec); |
410 | ++CurrentOffset; |
411 | } else { |
412 | for (Init *Arg : MIOI->getArgs()) { |
413 | OperandRecords.push_back(x: cast<DefInit>(Val: Arg)->getDef()); |
414 | ++CurrentOffset; |
415 | } |
416 | } |
417 | } |
418 | } |
419 | |
420 | // Emit the table of offsets (indexes) into the operand type table. |
421 | // Size the unsigned integer offset to save space. |
422 | assert(OperandRecords.size() <= UINT32_MAX && |
423 | "Too many operands for offset table" ); |
424 | OS << " static const " << getMinimalTypeForRange(Range: OperandRecords.size()); |
425 | OS << " Offsets[] = {\n" ; |
426 | for (int I = 0, E = OperandOffsets.size(); I != E; ++I) { |
427 | OS << " /* " << getInstrName(I) << " */\n" ; |
428 | OS << " " << OperandOffsets[I] << ",\n" ; |
429 | } |
430 | OS << " };\n" ; |
431 | |
432 | // Add an entry for the end so that we don't need to special case it below. |
433 | OperandOffsets.push_back(x: OperandRecords.size()); |
434 | |
435 | // Emit the actual operand types in a flat table. |
436 | // Size the signed integer operand type to save space. |
437 | assert(EnumVal <= INT16_MAX && |
438 | "Too many operand types for operand types table" ); |
439 | OS << "\n using namespace OpTypes;\n" ; |
440 | OS << " static" ; |
441 | OS << ((EnumVal <= INT8_MAX) ? " const int8_t" : " const int16_t" ); |
442 | OS << " OpcodeOperandTypes[] = {\n " ; |
443 | for (int I = 0, E = OperandRecords.size(), CurOffset = 0; I != E; ++I) { |
444 | // We print each Opcode's operands in its own row. |
445 | if (I == OperandOffsets[CurOffset]) { |
446 | OS << "\n /* " << getInstrName(CurOffset) << " */\n " ; |
447 | while (OperandOffsets[++CurOffset] == I) |
448 | OS << "/* " << getInstrName(CurOffset) << " */\n " ; |
449 | } |
450 | Record *OpR = OperandRecords[I]; |
451 | if ((OpR->isSubClassOf(Name: "Operand" ) || |
452 | OpR->isSubClassOf(Name: "RegisterOperand" ) || |
453 | OpR->isSubClassOf(Name: "RegisterClass" )) && |
454 | !OpR->isAnonymous()) |
455 | OS << OpR->getName(); |
456 | else |
457 | OS << -1; |
458 | OS << ", " ; |
459 | } |
460 | OS << "\n };\n" ; |
461 | |
462 | OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n" ; |
463 | } else { |
464 | OS << " llvm_unreachable(\"No instructions defined\");\n" ; |
465 | } |
466 | OS << "}\n" ; |
467 | OS << "} // end namespace " << Namespace << "\n" ; |
468 | OS << "} // end namespace llvm\n" ; |
469 | OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n" ; |
470 | |
471 | OS << "#ifdef GET_INSTRINFO_MEM_OPERAND_SIZE\n" ; |
472 | OS << "#undef GET_INSTRINFO_MEM_OPERAND_SIZE\n" ; |
473 | OS << "namespace llvm {\n" ; |
474 | OS << "namespace " << Namespace << " {\n" ; |
475 | OS << "LLVM_READONLY\n" ; |
476 | OS << "static int getMemOperandSize(int OpType) {\n" ; |
477 | OS << " switch (OpType) {\n" ; |
478 | std::map<int, SmallVector<StringRef, 0>> SizeToOperandName; |
479 | for (const Record *Op : Operands) { |
480 | if (!Op->isSubClassOf(Name: "X86MemOperand" )) |
481 | continue; |
482 | if (int Size = Op->getValueAsInt(FieldName: "Size" )) |
483 | SizeToOperandName[Size].push_back(Elt: Op->getName()); |
484 | } |
485 | OS << " default: return 0;\n" ; |
486 | for (const auto &KV : SizeToOperandName) { |
487 | for (const StringRef &OperandName : KV.second) |
488 | OS << " case OpTypes::" << OperandName << ":\n" ; |
489 | OS << " return " << KV.first << ";\n\n" ; |
490 | } |
491 | OS << " }\n}\n" ; |
492 | OS << "} // end namespace " << Namespace << "\n" ; |
493 | OS << "} // end namespace llvm\n" ; |
494 | OS << "#endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n" ; |
495 | } |
496 | |
497 | void InstrInfoEmitter::emitLogicalOperandSizeMappings( |
498 | raw_ostream &OS, StringRef Namespace, |
499 | ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
500 | std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap; |
501 | |
502 | std::map<unsigned, std::vector<std::string>> InstMap; |
503 | |
504 | size_t LogicalOpListSize = 0U; |
505 | std::vector<unsigned> LogicalOpList; |
506 | for (const auto *Inst : NumberedInstructions) { |
507 | if (!Inst->TheDef->getValueAsBit(FieldName: "UseLogicalOperandMappings" )) |
508 | continue; |
509 | |
510 | LogicalOpList.clear(); |
511 | llvm::transform(Range: Inst->Operands, d_first: std::back_inserter(x&: LogicalOpList), |
512 | F: [](const CGIOperandList::OperandInfo &Op) -> unsigned { |
513 | auto *MIOI = Op.MIOperandInfo; |
514 | if (!MIOI || MIOI->getNumArgs() == 0) |
515 | return 1; |
516 | return MIOI->getNumArgs(); |
517 | }); |
518 | LogicalOpListSize = std::max(a: LogicalOpList.size(), b: LogicalOpListSize); |
519 | |
520 | auto I = |
521 | LogicalOpSizeMap.insert(x: {LogicalOpList, LogicalOpSizeMap.size()}).first; |
522 | InstMap[I->second].push_back( |
523 | x: (Namespace + "::" + Inst->TheDef->getName()).str()); |
524 | } |
525 | |
526 | OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n" ; |
527 | OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n" ; |
528 | OS << "namespace llvm {\n" ; |
529 | OS << "namespace " << Namespace << " {\n" ; |
530 | OS << "LLVM_READONLY static unsigned\n" ; |
531 | OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n" ; |
532 | if (!InstMap.empty()) { |
533 | std::vector<const std::vector<unsigned> *> LogicalOpSizeList( |
534 | LogicalOpSizeMap.size()); |
535 | for (auto &P : LogicalOpSizeMap) { |
536 | LogicalOpSizeList[P.second] = &P.first; |
537 | } |
538 | OS << " static const unsigned SizeMap[][" << LogicalOpListSize |
539 | << "] = {\n" ; |
540 | for (auto &R : LogicalOpSizeList) { |
541 | const auto &Row = *R; |
542 | OS << " {" ; |
543 | int i; |
544 | for (i = 0; i < static_cast<int>(Row.size()); ++i) { |
545 | OS << Row[i] << ", " ; |
546 | } |
547 | for (; i < static_cast<int>(LogicalOpListSize); ++i) { |
548 | OS << "0, " ; |
549 | } |
550 | OS << "}, " ; |
551 | OS << "\n" ; |
552 | } |
553 | OS << " };\n" ; |
554 | |
555 | OS << " switch (Opcode) {\n" ; |
556 | OS << " default: return LogicalOpIdx;\n" ; |
557 | for (auto &P : InstMap) { |
558 | auto OpMapIdx = P.first; |
559 | const auto &Insts = P.second; |
560 | for (const auto &Inst : Insts) { |
561 | OS << " case " << Inst << ":\n" ; |
562 | } |
563 | OS << " return SizeMap[" << OpMapIdx << "][LogicalOpIdx];\n" ; |
564 | } |
565 | OS << " }\n" ; |
566 | } else { |
567 | OS << " return LogicalOpIdx;\n" ; |
568 | } |
569 | OS << "}\n" ; |
570 | |
571 | OS << "LLVM_READONLY static inline unsigned\n" ; |
572 | OS << "getLogicalOperandIdx(uint16_t Opcode, uint16_t LogicalOpIdx) {\n" ; |
573 | OS << " auto S = 0U;\n" ; |
574 | OS << " for (auto i = 0U; i < LogicalOpIdx; ++i)\n" ; |
575 | OS << " S += getLogicalOperandSize(Opcode, i);\n" ; |
576 | OS << " return S;\n" ; |
577 | OS << "}\n" ; |
578 | |
579 | OS << "} // end namespace " << Namespace << "\n" ; |
580 | OS << "} // end namespace llvm\n" ; |
581 | OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n" ; |
582 | } |
583 | |
584 | void InstrInfoEmitter::emitLogicalOperandTypeMappings( |
585 | raw_ostream &OS, StringRef Namespace, |
586 | ArrayRef<const CodeGenInstruction *> NumberedInstructions) { |
587 | std::map<std::vector<std::string>, unsigned> LogicalOpTypeMap; |
588 | |
589 | std::map<unsigned, std::vector<std::string>> InstMap; |
590 | |
591 | size_t OpTypeListSize = 0U; |
592 | std::vector<std::string> LogicalOpTypeList; |
593 | for (const auto *Inst : NumberedInstructions) { |
594 | if (!Inst->TheDef->getValueAsBit(FieldName: "UseLogicalOperandMappings" )) |
595 | continue; |
596 | |
597 | LogicalOpTypeList.clear(); |
598 | for (const auto &Op : Inst->Operands) { |
599 | auto *OpR = Op.Rec; |
600 | if ((OpR->isSubClassOf(Name: "Operand" ) || |
601 | OpR->isSubClassOf(Name: "RegisterOperand" ) || |
602 | OpR->isSubClassOf(Name: "RegisterClass" )) && |
603 | !OpR->isAnonymous()) { |
604 | LogicalOpTypeList.push_back( |
605 | x: (Namespace + "::OpTypes::" + Op.Rec->getName()).str()); |
606 | } else { |
607 | LogicalOpTypeList.push_back(x: "-1" ); |
608 | } |
609 | } |
610 | OpTypeListSize = std::max(a: LogicalOpTypeList.size(), b: OpTypeListSize); |
611 | |
612 | auto I = |
613 | LogicalOpTypeMap.insert(x: {LogicalOpTypeList, LogicalOpTypeMap.size()}) |
614 | .first; |
615 | InstMap[I->second].push_back( |
616 | x: (Namespace + "::" + Inst->TheDef->getName()).str()); |
617 | } |
618 | |
619 | OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n" ; |
620 | OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n" ; |
621 | OS << "namespace llvm {\n" ; |
622 | OS << "namespace " << Namespace << " {\n" ; |
623 | OS << "LLVM_READONLY static int\n" ; |
624 | OS << "getLogicalOperandType(uint16_t Opcode, uint16_t LogicalOpIdx) {\n" ; |
625 | if (!InstMap.empty()) { |
626 | std::vector<const std::vector<std::string> *> LogicalOpTypeList( |
627 | LogicalOpTypeMap.size()); |
628 | for (auto &P : LogicalOpTypeMap) { |
629 | LogicalOpTypeList[P.second] = &P.first; |
630 | } |
631 | OS << " static const int TypeMap[][" << OpTypeListSize << "] = {\n" ; |
632 | for (int r = 0, rs = LogicalOpTypeList.size(); r < rs; ++r) { |
633 | const auto &Row = *LogicalOpTypeList[r]; |
634 | OS << " {" ; |
635 | int i, s = Row.size(); |
636 | for (i = 0; i < s; ++i) { |
637 | if (i > 0) |
638 | OS << ", " ; |
639 | OS << Row[i]; |
640 | } |
641 | for (; i < static_cast<int>(OpTypeListSize); ++i) { |
642 | if (i > 0) |
643 | OS << ", " ; |
644 | OS << "-1" ; |
645 | } |
646 | OS << "}" ; |
647 | if (r != rs - 1) |
648 | OS << "," ; |
649 | OS << "\n" ; |
650 | } |
651 | OS << " };\n" ; |
652 | |
653 | OS << " switch (Opcode) {\n" ; |
654 | OS << " default: return -1;\n" ; |
655 | for (auto &P : InstMap) { |
656 | auto OpMapIdx = P.first; |
657 | const auto &Insts = P.second; |
658 | for (const auto &Inst : Insts) { |
659 | OS << " case " << Inst << ":\n" ; |
660 | } |
661 | OS << " return TypeMap[" << OpMapIdx << "][LogicalOpIdx];\n" ; |
662 | } |
663 | OS << " }\n" ; |
664 | } else { |
665 | OS << " return -1;\n" ; |
666 | } |
667 | OS << "}\n" ; |
668 | OS << "} // end namespace " << Namespace << "\n" ; |
669 | OS << "} // end namespace llvm\n" ; |
670 | OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_TYPE_MAP\n\n" ; |
671 | } |
672 | |
673 | void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS, |
674 | StringRef TargetName) { |
675 | RecVec TIIPredicates = Records.getAllDerivedDefinitions(ClassName: "TIIPredicate" ); |
676 | |
677 | OS << "#ifdef GET_INSTRINFO_MC_HELPER_DECLS\n" ; |
678 | OS << "#undef GET_INSTRINFO_MC_HELPER_DECLS\n\n" ; |
679 | |
680 | OS << "namespace llvm {\n" ; |
681 | OS << "class MCInst;\n" ; |
682 | OS << "class FeatureBitset;\n\n" ; |
683 | |
684 | OS << "namespace " << TargetName << "_MC {\n\n" ; |
685 | |
686 | for (const Record *Rec : TIIPredicates) { |
687 | OS << "bool " << Rec->getValueAsString(FieldName: "FunctionName" ) |
688 | << "(const MCInst &MI);\n" ; |
689 | } |
690 | |
691 | OS << "void verifyInstructionPredicates(unsigned Opcode, const FeatureBitset " |
692 | "&Features);\n" ; |
693 | |
694 | OS << "\n} // end namespace " << TargetName << "_MC\n" ; |
695 | OS << "} // end namespace llvm\n\n" ; |
696 | |
697 | OS << "#endif // GET_INSTRINFO_MC_HELPER_DECLS\n\n" ; |
698 | |
699 | OS << "#ifdef GET_INSTRINFO_MC_HELPERS\n" ; |
700 | OS << "#undef GET_INSTRINFO_MC_HELPERS\n\n" ; |
701 | |
702 | OS << "namespace llvm {\n" ; |
703 | OS << "namespace " << TargetName << "_MC {\n\n" ; |
704 | |
705 | PredicateExpander PE(TargetName); |
706 | PE.setExpandForMC(true); |
707 | |
708 | for (const Record *Rec : TIIPredicates) { |
709 | OS << "bool " << Rec->getValueAsString(FieldName: "FunctionName" ); |
710 | OS << "(const MCInst &MI) {\n" ; |
711 | |
712 | OS.indent(NumSpaces: PE.getIndentLevel() * 2); |
713 | PE.expandStatement(OS, Rec: Rec->getValueAsDef(FieldName: "Body" )); |
714 | OS << "\n}\n\n" ; |
715 | } |
716 | |
717 | OS << "} // end namespace " << TargetName << "_MC\n" ; |
718 | OS << "} // end namespace llvm\n\n" ; |
719 | |
720 | OS << "#endif // GET_GENISTRINFO_MC_HELPERS\n\n" ; |
721 | } |
722 | |
723 | static std::string |
724 | getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) { |
725 | std::string Name = "CEFBS" ; |
726 | for (const auto &Feature : FeatureBitset) |
727 | Name += ("_" + Feature->getName()).str(); |
728 | return Name; |
729 | } |
730 | |
731 | void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS, |
732 | const CodeGenTarget &Target) { |
733 | const auto &All = SubtargetFeatureInfo::getAll(Records); |
734 | std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; |
735 | SubtargetFeatures.insert(first: All.begin(), last: All.end()); |
736 | |
737 | OS << "#if (defined(ENABLE_INSTR_PREDICATE_VERIFIER) && !defined(NDEBUG)) " |
738 | << "||\\\n" |
739 | << " defined(GET_AVAILABLE_OPCODE_CHECKER)\n" |
740 | << "#define GET_COMPUTE_FEATURES\n" |
741 | << "#endif\n" ; |
742 | OS << "#ifdef GET_COMPUTE_FEATURES\n" |
743 | << "#undef GET_COMPUTE_FEATURES\n" |
744 | << "namespace llvm {\n" |
745 | << "namespace " << Target.getName() << "_MC {\n\n" ; |
746 | |
747 | // Emit the subtarget feature enumeration. |
748 | SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, |
749 | OS); |
750 | // Emit the available features compute function. |
751 | OS << "inline " ; |
752 | SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( |
753 | TargetName: Target.getName(), ClassName: "" , FuncName: "computeAvailableFeatures" , SubtargetFeatures, OS); |
754 | |
755 | std::vector<std::vector<Record *>> FeatureBitsets; |
756 | for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { |
757 | FeatureBitsets.emplace_back(); |
758 | for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs(FieldName: "Predicates" )) { |
759 | const auto &I = SubtargetFeatures.find(x: Predicate); |
760 | if (I != SubtargetFeatures.end()) |
761 | FeatureBitsets.back().push_back(x: I->second.TheDef); |
762 | } |
763 | } |
764 | |
765 | llvm::sort(C&: FeatureBitsets, Comp: [&](const std::vector<Record *> &A, |
766 | const std::vector<Record *> &B) { |
767 | if (A.size() < B.size()) |
768 | return true; |
769 | if (A.size() > B.size()) |
770 | return false; |
771 | for (auto Pair : zip(t: A, u: B)) { |
772 | if (std::get<0>(t&: Pair)->getName() < std::get<1>(t&: Pair)->getName()) |
773 | return true; |
774 | if (std::get<0>(t&: Pair)->getName() > std::get<1>(t&: Pair)->getName()) |
775 | return false; |
776 | } |
777 | return false; |
778 | }); |
779 | FeatureBitsets.erase(first: llvm::unique(R&: FeatureBitsets), last: FeatureBitsets.end()); |
780 | OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n" |
781 | << " enum : " << getMinimalTypeForRange(Range: FeatureBitsets.size()) << " {\n" |
782 | << " CEFBS_None,\n" ; |
783 | for (const auto &FeatureBitset : FeatureBitsets) { |
784 | if (FeatureBitset.empty()) |
785 | continue; |
786 | OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n" ; |
787 | } |
788 | OS << " };\n\n" |
789 | << " static constexpr FeatureBitset FeatureBitsets[] = {\n" |
790 | << " {}, // CEFBS_None\n" ; |
791 | for (const auto &FeatureBitset : FeatureBitsets) { |
792 | if (FeatureBitset.empty()) |
793 | continue; |
794 | OS << " {" ; |
795 | for (const auto &Feature : FeatureBitset) { |
796 | const auto &I = SubtargetFeatures.find(x: Feature); |
797 | assert(I != SubtargetFeatures.end() && "Didn't import predicate?" ); |
798 | OS << I->second.getEnumBitName() << ", " ; |
799 | } |
800 | OS << "},\n" ; |
801 | } |
802 | OS << " };\n" |
803 | << " static constexpr " << getMinimalTypeForRange(Range: FeatureBitsets.size()) |
804 | << " RequiredFeaturesRefs[] = {\n" ; |
805 | unsigned InstIdx = 0; |
806 | for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { |
807 | OS << " CEFBS" ; |
808 | unsigned NumPredicates = 0; |
809 | for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs(FieldName: "Predicates" )) { |
810 | const auto &I = SubtargetFeatures.find(x: Predicate); |
811 | if (I != SubtargetFeatures.end()) { |
812 | OS << '_' << I->second.TheDef->getName(); |
813 | NumPredicates++; |
814 | } |
815 | } |
816 | if (!NumPredicates) |
817 | OS << "_None" ; |
818 | OS << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n" ; |
819 | InstIdx++; |
820 | } |
821 | OS << " };\n\n" |
822 | << " assert(Opcode < " << InstIdx << ");\n" |
823 | << " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n" |
824 | << "}\n\n" ; |
825 | |
826 | OS << "} // end namespace " << Target.getName() << "_MC\n" |
827 | << "} // end namespace llvm\n" |
828 | << "#endif // GET_COMPUTE_FEATURES\n\n" ; |
829 | |
830 | OS << "#ifdef GET_AVAILABLE_OPCODE_CHECKER\n" |
831 | << "#undef GET_AVAILABLE_OPCODE_CHECKER\n" |
832 | << "namespace llvm {\n" |
833 | << "namespace " << Target.getName() << "_MC {\n" ; |
834 | OS << "bool isOpcodeAvailable(" |
835 | << "unsigned Opcode, const FeatureBitset &Features) {\n" |
836 | << " FeatureBitset AvailableFeatures = " |
837 | << "computeAvailableFeatures(Features);\n" |
838 | << " FeatureBitset RequiredFeatures = " |
839 | << "computeRequiredFeatures(Opcode);\n" |
840 | << " FeatureBitset MissingFeatures =\n" |
841 | << " (AvailableFeatures & RequiredFeatures) ^\n" |
842 | << " RequiredFeatures;\n" |
843 | << " return !MissingFeatures.any();\n" |
844 | << "}\n" ; |
845 | OS << "} // end namespace " << Target.getName() << "_MC\n" |
846 | << "} // end namespace llvm\n" |
847 | << "#endif // GET_AVAILABLE_OPCODE_CHECKER\n\n" ; |
848 | |
849 | OS << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" |
850 | << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" |
851 | << "#include <sstream>\n\n" ; |
852 | |
853 | OS << "namespace llvm {\n" ; |
854 | OS << "namespace " << Target.getName() << "_MC {\n\n" ; |
855 | |
856 | // Emit the name table for error messages. |
857 | OS << "#ifndef NDEBUG\n" ; |
858 | SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS); |
859 | OS << "#endif // NDEBUG\n\n" ; |
860 | |
861 | // Emit the predicate verifier. |
862 | OS << "void verifyInstructionPredicates(\n" |
863 | << " unsigned Opcode, const FeatureBitset &Features) {\n" |
864 | << "#ifndef NDEBUG\n" ; |
865 | OS << " FeatureBitset AvailableFeatures = " |
866 | "computeAvailableFeatures(Features);\n" ; |
867 | OS << " FeatureBitset RequiredFeatures = " |
868 | << "computeRequiredFeatures(Opcode);\n" ; |
869 | OS << " FeatureBitset MissingFeatures =\n" |
870 | << " (AvailableFeatures & RequiredFeatures) ^\n" |
871 | << " RequiredFeatures;\n" |
872 | << " if (MissingFeatures.any()) {\n" |
873 | << " std::ostringstream Msg;\n" |
874 | << " Msg << \"Attempting to emit \" << &" << Target.getName() |
875 | << "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n" |
876 | << " << \" instruction but the \";\n" |
877 | << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n" |
878 | << " if (MissingFeatures.test(i))\n" |
879 | << " Msg << SubtargetFeatureNames[i] << \" \";\n" |
880 | << " Msg << \"predicate(s) are not met\";\n" |
881 | << " report_fatal_error(Msg.str().c_str());\n" |
882 | << " }\n" |
883 | << "#endif // NDEBUG\n" ; |
884 | OS << "}\n" ; |
885 | OS << "} // end namespace " << Target.getName() << "_MC\n" ; |
886 | OS << "} // end namespace llvm\n" ; |
887 | OS << "#endif // ENABLE_INSTR_PREDICATE_VERIFIER\n\n" ; |
888 | } |
889 | |
890 | void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS, |
891 | StringRef TargetName, |
892 | bool ExpandDefinition) { |
893 | RecVec TIIPredicates = Records.getAllDerivedDefinitions(ClassName: "TIIPredicate" ); |
894 | if (TIIPredicates.empty()) |
895 | return; |
896 | |
897 | PredicateExpander PE(TargetName); |
898 | PE.setExpandForMC(false); |
899 | |
900 | for (const Record *Rec : TIIPredicates) { |
901 | OS << (ExpandDefinition ? "" : "static " ) << "bool " ; |
902 | if (ExpandDefinition) |
903 | OS << TargetName << "InstrInfo::" ; |
904 | OS << Rec->getValueAsString(FieldName: "FunctionName" ); |
905 | OS << "(const MachineInstr &MI)" ; |
906 | if (!ExpandDefinition) { |
907 | OS << ";\n" ; |
908 | continue; |
909 | } |
910 | |
911 | OS << " {\n" ; |
912 | OS.indent(NumSpaces: PE.getIndentLevel() * 2); |
913 | PE.expandStatement(OS, Rec: Rec->getValueAsDef(FieldName: "Body" )); |
914 | OS << "\n}\n\n" ; |
915 | } |
916 | } |
917 | |
918 | //===----------------------------------------------------------------------===// |
919 | // Main Output. |
920 | //===----------------------------------------------------------------------===// |
921 | |
922 | // run - Emit the main instruction description records for the target... |
923 | void InstrInfoEmitter::run(raw_ostream &OS) { |
924 | emitSourceFileHeader(Desc: "Target Instruction Enum Values and Descriptors" , OS); |
925 | emitEnums(OS); |
926 | |
927 | CodeGenTarget &Target = CDP.getTargetInfo(); |
928 | const std::string &TargetName = std::string(Target.getName()); |
929 | Record *InstrInfo = Target.getInstructionSet(); |
930 | |
931 | // Collect all of the operand info records. |
932 | Records.startTimer(Name: "Collect operand info" ); |
933 | OperandInfoListTy OperandInfoList; |
934 | OperandInfoMapTy OperandInfoMap; |
935 | unsigned OperandInfoSize = |
936 | CollectOperandInfo(OperandInfoList, OperandInfoMap); |
937 | |
938 | // Collect all of the instruction's implicit uses and defs. |
939 | Records.startTimer(Name: "Collect uses/defs" ); |
940 | std::map<std::vector<Record *>, unsigned> EmittedLists; |
941 | std::vector<std::vector<Record *>> ImplicitLists; |
942 | unsigned ImplicitListSize = 0; |
943 | for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { |
944 | std::vector<Record *> ImplicitOps = II->ImplicitUses; |
945 | llvm::append_range(C&: ImplicitOps, R: II->ImplicitDefs); |
946 | if (EmittedLists.insert(x: {ImplicitOps, ImplicitListSize}).second) { |
947 | ImplicitLists.push_back(x: ImplicitOps); |
948 | ImplicitListSize += ImplicitOps.size(); |
949 | } |
950 | } |
951 | |
952 | ArrayRef<const CodeGenInstruction *> NumberedInstructions = |
953 | Target.getInstructionsByEnumValue(); |
954 | OS << "#if defined(GET_INSTRINFO_MC_DESC) || " |
955 | "defined(GET_INSTRINFO_CTOR_DTOR)\n" ; |
956 | OS << "namespace llvm {\n\n" ; |
957 | |
958 | OS << "struct " << TargetName << "InstrTable {\n" ; |
959 | OS << " MCInstrDesc Insts[" << NumberedInstructions.size() << "];\n" ; |
960 | OS << " static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), " |
961 | "\"Unwanted padding between Insts and OperandInfo\");\n" ; |
962 | OS << " MCOperandInfo OperandInfo[" << OperandInfoSize << "];\n" ; |
963 | OS << " static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), " |
964 | "\"Unwanted padding between OperandInfo and ImplicitOps\");\n" ; |
965 | OS << " MCPhysReg ImplicitOps[" << std::max(a: ImplicitListSize, b: 1U) << "];\n" ; |
966 | OS << "};\n\n" ; |
967 | |
968 | OS << "} // end namespace llvm\n" ; |
969 | OS << "#endif // defined(GET_INSTRINFO_MC_DESC) || " |
970 | "defined(GET_INSTRINFO_CTOR_DTOR)\n\n" ; |
971 | |
972 | OS << "#ifdef GET_INSTRINFO_MC_DESC\n" ; |
973 | OS << "#undef GET_INSTRINFO_MC_DESC\n" ; |
974 | OS << "namespace llvm {\n\n" ; |
975 | |
976 | // Emit all of the MCInstrDesc records in reverse ENUM ordering. |
977 | Records.startTimer(Name: "Emit InstrDesc records" ); |
978 | OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n" ; |
979 | OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof " |
980 | << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n" ; |
981 | |
982 | OS << "extern const " << TargetName << "InstrTable " << TargetName |
983 | << "Descs = {\n {\n" ; |
984 | SequenceToOffsetTable<std::string> InstrNames; |
985 | unsigned Num = NumberedInstructions.size(); |
986 | for (const CodeGenInstruction *Inst : reverse(C&: NumberedInstructions)) { |
987 | // Keep a list of the instruction names. |
988 | InstrNames.add(Seq: std::string(Inst->TheDef->getName())); |
989 | // Emit the record into the table. |
990 | emitRecord(Inst: *Inst, Num: --Num, InstrInfo, EL&: EmittedLists, OperandInfo: OperandInfoMap, OS); |
991 | } |
992 | |
993 | OS << " }, {\n" ; |
994 | |
995 | // Emit all of the operand info records. |
996 | Records.startTimer(Name: "Emit operand info" ); |
997 | EmitOperandInfo(OS, OperandInfoList); |
998 | |
999 | OS << " }, {\n" ; |
1000 | |
1001 | // Emit all of the instruction's implicit uses and defs. |
1002 | Records.startTimer(Name: "Emit uses/defs" ); |
1003 | for (auto &List : ImplicitLists) { |
1004 | OS << " /* " << EmittedLists[List] << " */" ; |
1005 | for (auto &Reg : List) |
1006 | OS << ' ' << getQualifiedName(R: Reg) << ','; |
1007 | OS << '\n'; |
1008 | } |
1009 | |
1010 | OS << " }\n};\n\n" ; |
1011 | |
1012 | // Emit the array of instruction names. |
1013 | Records.startTimer(Name: "Emit instruction names" ); |
1014 | InstrNames.layout(); |
1015 | InstrNames.emitStringLiteralDef(OS, Decl: Twine("extern const char " ) + TargetName + |
1016 | "InstrNameData[]" ); |
1017 | |
1018 | OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {" ; |
1019 | Num = 0; |
1020 | for (const CodeGenInstruction *Inst : NumberedInstructions) { |
1021 | // Newline every eight entries. |
1022 | if (Num % 8 == 0) |
1023 | OS << "\n " ; |
1024 | OS << InstrNames.get(Seq: std::string(Inst->TheDef->getName())) << "U, " ; |
1025 | ++Num; |
1026 | } |
1027 | OS << "\n};\n\n" ; |
1028 | |
1029 | bool HasDeprecationFeatures = |
1030 | llvm::any_of(Range&: NumberedInstructions, P: [](const CodeGenInstruction *Inst) { |
1031 | return !Inst->HasComplexDeprecationPredicate && |
1032 | !Inst->DeprecatedReason.empty(); |
1033 | }); |
1034 | if (HasDeprecationFeatures) { |
1035 | OS << "extern const uint8_t " << TargetName |
1036 | << "InstrDeprecationFeatures[] = {" ; |
1037 | Num = 0; |
1038 | for (const CodeGenInstruction *Inst : NumberedInstructions) { |
1039 | if (Num % 8 == 0) |
1040 | OS << "\n " ; |
1041 | if (!Inst->HasComplexDeprecationPredicate && |
1042 | !Inst->DeprecatedReason.empty()) |
1043 | OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason |
1044 | << ", " ; |
1045 | else |
1046 | OS << "uint8_t(-1), " ; |
1047 | ++Num; |
1048 | } |
1049 | OS << "\n};\n\n" ; |
1050 | } |
1051 | |
1052 | bool HasComplexDeprecationInfos = |
1053 | llvm::any_of(Range&: NumberedInstructions, P: [](const CodeGenInstruction *Inst) { |
1054 | return Inst->HasComplexDeprecationPredicate; |
1055 | }); |
1056 | if (HasComplexDeprecationInfos) { |
1057 | OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName |
1058 | << "InstrComplexDeprecationInfos[] = {" ; |
1059 | Num = 0; |
1060 | for (const CodeGenInstruction *Inst : NumberedInstructions) { |
1061 | if (Num % 8 == 0) |
1062 | OS << "\n " ; |
1063 | if (Inst->HasComplexDeprecationPredicate) |
1064 | // Emit a function pointer to the complex predicate method. |
1065 | OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, " ; |
1066 | else |
1067 | OS << "nullptr, " ; |
1068 | ++Num; |
1069 | } |
1070 | OS << "\n};\n\n" ; |
1071 | } |
1072 | |
1073 | // MCInstrInfo initialization routine. |
1074 | Records.startTimer(Name: "Emit initialization routine" ); |
1075 | OS << "static inline void Init" << TargetName |
1076 | << "MCInstrInfo(MCInstrInfo *II) {\n" ; |
1077 | OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName |
1078 | << "InstrNameIndices, " << TargetName << "InstrNameData, " ; |
1079 | if (HasDeprecationFeatures) |
1080 | OS << TargetName << "InstrDeprecationFeatures, " ; |
1081 | else |
1082 | OS << "nullptr, " ; |
1083 | if (HasComplexDeprecationInfos) |
1084 | OS << TargetName << "InstrComplexDeprecationInfos, " ; |
1085 | else |
1086 | OS << "nullptr, " ; |
1087 | OS << NumberedInstructions.size() << ");\n}\n\n" ; |
1088 | |
1089 | OS << "} // end namespace llvm\n" ; |
1090 | |
1091 | OS << "#endif // GET_INSTRINFO_MC_DESC\n\n" ; |
1092 | |
1093 | // Create a TargetInstrInfo subclass to hide the MC layer initialization. |
1094 | OS << "#ifdef GET_INSTRINFO_HEADER\n" ; |
1095 | OS << "#undef GET_INSTRINFO_HEADER\n" ; |
1096 | |
1097 | std::string ClassName = TargetName + "GenInstrInfo" ; |
1098 | OS << "namespace llvm {\n" ; |
1099 | OS << "struct " << ClassName << " : public TargetInstrInfo {\n" |
1100 | << " explicit " << ClassName |
1101 | << "(unsigned CFSetupOpcode = ~0u, unsigned CFDestroyOpcode = ~0u, " |
1102 | "unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n" |
1103 | << " ~" << ClassName << "() override = default;\n" ; |
1104 | |
1105 | OS << "\n};\n} // end namespace llvm\n" ; |
1106 | |
1107 | OS << "#endif // GET_INSTRINFO_HEADER\n\n" ; |
1108 | |
1109 | OS << "#ifdef GET_INSTRINFO_HELPER_DECLS\n" ; |
1110 | OS << "#undef GET_INSTRINFO_HELPER_DECLS\n\n" ; |
1111 | emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false); |
1112 | OS << "\n" ; |
1113 | OS << "#endif // GET_INSTRINFO_HELPER_DECLS\n\n" ; |
1114 | |
1115 | OS << "#ifdef GET_INSTRINFO_HELPERS\n" ; |
1116 | OS << "#undef GET_INSTRINFO_HELPERS\n\n" ; |
1117 | emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true); |
1118 | OS << "#endif // GET_INSTRINFO_HELPERS\n\n" ; |
1119 | |
1120 | OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n" ; |
1121 | OS << "#undef GET_INSTRINFO_CTOR_DTOR\n" ; |
1122 | |
1123 | OS << "namespace llvm {\n" ; |
1124 | OS << "extern const " << TargetName << "InstrTable " << TargetName |
1125 | << "Descs;\n" ; |
1126 | OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n" ; |
1127 | OS << "extern const char " << TargetName << "InstrNameData[];\n" ; |
1128 | if (HasDeprecationFeatures) |
1129 | OS << "extern const uint8_t " << TargetName |
1130 | << "InstrDeprecationFeatures[];\n" ; |
1131 | if (HasComplexDeprecationInfos) |
1132 | OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName |
1133 | << "InstrComplexDeprecationInfos[];\n" ; |
1134 | OS << ClassName << "::" << ClassName |
1135 | << "(unsigned CFSetupOpcode, unsigned CFDestroyOpcode, unsigned " |
1136 | "CatchRetOpcode, unsigned ReturnOpcode)\n" |
1137 | << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, " |
1138 | "ReturnOpcode) {\n" |
1139 | << " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName |
1140 | << "InstrNameIndices, " << TargetName << "InstrNameData, " ; |
1141 | if (HasDeprecationFeatures) |
1142 | OS << TargetName << "InstrDeprecationFeatures, " ; |
1143 | else |
1144 | OS << "nullptr, " ; |
1145 | if (HasComplexDeprecationInfos) |
1146 | OS << TargetName << "InstrComplexDeprecationInfos, " ; |
1147 | else |
1148 | OS << "nullptr, " ; |
1149 | OS << NumberedInstructions.size() << ");\n}\n" ; |
1150 | OS << "} // end namespace llvm\n" ; |
1151 | |
1152 | OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n" ; |
1153 | |
1154 | Records.startTimer(Name: "Emit operand name mappings" ); |
1155 | emitOperandNameMappings(OS, Target, NumberedInstructions); |
1156 | |
1157 | Records.startTimer(Name: "Emit operand type mappings" ); |
1158 | emitOperandTypeMappings(OS, Target, NumberedInstructions); |
1159 | |
1160 | Records.startTimer(Name: "Emit logical operand size mappings" ); |
1161 | emitLogicalOperandSizeMappings(OS, Namespace: TargetName, NumberedInstructions); |
1162 | |
1163 | Records.startTimer(Name: "Emit logical operand type mappings" ); |
1164 | emitLogicalOperandTypeMappings(OS, Namespace: TargetName, NumberedInstructions); |
1165 | |
1166 | Records.startTimer(Name: "Emit helper methods" ); |
1167 | emitMCIIHelperMethods(OS, TargetName); |
1168 | |
1169 | Records.startTimer(Name: "Emit verifier methods" ); |
1170 | emitFeatureVerifier(OS, Target); |
1171 | } |
1172 | |
1173 | void InstrInfoEmitter::emitRecord( |
1174 | const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, |
1175 | std::map<std::vector<Record *>, unsigned> &EmittedLists, |
1176 | const OperandInfoMapTy &OperandInfoMap, raw_ostream &OS) { |
1177 | int MinOperands = 0; |
1178 | if (!Inst.Operands.empty()) |
1179 | // Each logical operand can be multiple MI operands. |
1180 | MinOperands = |
1181 | Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; |
1182 | // Even the logical output operand may be multiple MI operands. |
1183 | int DefOperands = 0; |
1184 | if (Inst.Operands.NumDefs) { |
1185 | auto &Opnd = Inst.Operands[Inst.Operands.NumDefs - 1]; |
1186 | DefOperands = Opnd.MIOperandNo + Opnd.MINumOperands; |
1187 | } |
1188 | |
1189 | OS << " { " ; |
1190 | OS << Num << ",\t" << MinOperands << ",\t" << DefOperands << ",\t" |
1191 | << Inst.TheDef->getValueAsInt(FieldName: "Size" ) << ",\t" |
1192 | << SchedModels.getSchedClassIdx(Inst) << ",\t" ; |
1193 | |
1194 | CodeGenTarget &Target = CDP.getTargetInfo(); |
1195 | |
1196 | // Emit the implicit use/def list... |
1197 | OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t" ; |
1198 | std::vector<Record *> ImplicitOps = Inst.ImplicitUses; |
1199 | llvm::append_range(C&: ImplicitOps, R: Inst.ImplicitDefs); |
1200 | OS << Target.getName() << "ImpOpBase + " << EmittedLists[ImplicitOps] |
1201 | << ",\t" ; |
1202 | |
1203 | // Emit the operand info offset. |
1204 | OperandInfoTy OperandInfo = GetOperandInfo(Inst); |
1205 | OS << OperandInfoMap.find(x: OperandInfo)->second << ",\t0" ; |
1206 | |
1207 | // Emit all of the target independent flags... |
1208 | if (Inst.isPreISelOpcode) |
1209 | OS << "|(1ULL<<MCID::PreISelOpcode)" ; |
1210 | if (Inst.isPseudo) |
1211 | OS << "|(1ULL<<MCID::Pseudo)" ; |
1212 | if (Inst.isMeta) |
1213 | OS << "|(1ULL<<MCID::Meta)" ; |
1214 | if (Inst.isReturn) |
1215 | OS << "|(1ULL<<MCID::Return)" ; |
1216 | if (Inst.isEHScopeReturn) |
1217 | OS << "|(1ULL<<MCID::EHScopeReturn)" ; |
1218 | if (Inst.isBranch) |
1219 | OS << "|(1ULL<<MCID::Branch)" ; |
1220 | if (Inst.isIndirectBranch) |
1221 | OS << "|(1ULL<<MCID::IndirectBranch)" ; |
1222 | if (Inst.isCompare) |
1223 | OS << "|(1ULL<<MCID::Compare)" ; |
1224 | if (Inst.isMoveImm) |
1225 | OS << "|(1ULL<<MCID::MoveImm)" ; |
1226 | if (Inst.isMoveReg) |
1227 | OS << "|(1ULL<<MCID::MoveReg)" ; |
1228 | if (Inst.isBitcast) |
1229 | OS << "|(1ULL<<MCID::Bitcast)" ; |
1230 | if (Inst.isAdd) |
1231 | OS << "|(1ULL<<MCID::Add)" ; |
1232 | if (Inst.isTrap) |
1233 | OS << "|(1ULL<<MCID::Trap)" ; |
1234 | if (Inst.isSelect) |
1235 | OS << "|(1ULL<<MCID::Select)" ; |
1236 | if (Inst.isBarrier) |
1237 | OS << "|(1ULL<<MCID::Barrier)" ; |
1238 | if (Inst.hasDelaySlot) |
1239 | OS << "|(1ULL<<MCID::DelaySlot)" ; |
1240 | if (Inst.isCall) |
1241 | OS << "|(1ULL<<MCID::Call)" ; |
1242 | if (Inst.canFoldAsLoad) |
1243 | OS << "|(1ULL<<MCID::FoldableAsLoad)" ; |
1244 | if (Inst.mayLoad) |
1245 | OS << "|(1ULL<<MCID::MayLoad)" ; |
1246 | if (Inst.mayStore) |
1247 | OS << "|(1ULL<<MCID::MayStore)" ; |
1248 | if (Inst.mayRaiseFPException) |
1249 | OS << "|(1ULL<<MCID::MayRaiseFPException)" ; |
1250 | if (Inst.isPredicable) |
1251 | OS << "|(1ULL<<MCID::Predicable)" ; |
1252 | if (Inst.isConvertibleToThreeAddress) |
1253 | OS << "|(1ULL<<MCID::ConvertibleTo3Addr)" ; |
1254 | if (Inst.isCommutable) |
1255 | OS << "|(1ULL<<MCID::Commutable)" ; |
1256 | if (Inst.isTerminator) |
1257 | OS << "|(1ULL<<MCID::Terminator)" ; |
1258 | if (Inst.isReMaterializable) |
1259 | OS << "|(1ULL<<MCID::Rematerializable)" ; |
1260 | if (Inst.isNotDuplicable) |
1261 | OS << "|(1ULL<<MCID::NotDuplicable)" ; |
1262 | if (Inst.Operands.hasOptionalDef) |
1263 | OS << "|(1ULL<<MCID::HasOptionalDef)" ; |
1264 | if (Inst.usesCustomInserter) |
1265 | OS << "|(1ULL<<MCID::UsesCustomInserter)" ; |
1266 | if (Inst.hasPostISelHook) |
1267 | OS << "|(1ULL<<MCID::HasPostISelHook)" ; |
1268 | if (Inst.Operands.isVariadic) |
1269 | OS << "|(1ULL<<MCID::Variadic)" ; |
1270 | if (Inst.hasSideEffects) |
1271 | OS << "|(1ULL<<MCID::UnmodeledSideEffects)" ; |
1272 | if (Inst.isAsCheapAsAMove) |
1273 | OS << "|(1ULL<<MCID::CheapAsAMove)" ; |
1274 | if (!Target.getAllowRegisterRenaming() || Inst.hasExtraSrcRegAllocReq) |
1275 | OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)" ; |
1276 | if (!Target.getAllowRegisterRenaming() || Inst.hasExtraDefRegAllocReq) |
1277 | OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)" ; |
1278 | if (Inst.isRegSequence) |
1279 | OS << "|(1ULL<<MCID::RegSequence)" ; |
1280 | if (Inst.isExtractSubreg) |
1281 | OS << "|(1ULL<<MCID::ExtractSubreg)" ; |
1282 | if (Inst.isInsertSubreg) |
1283 | OS << "|(1ULL<<MCID::InsertSubreg)" ; |
1284 | if (Inst.isConvergent) |
1285 | OS << "|(1ULL<<MCID::Convergent)" ; |
1286 | if (Inst.variadicOpsAreDefs) |
1287 | OS << "|(1ULL<<MCID::VariadicOpsAreDefs)" ; |
1288 | if (Inst.isAuthenticated) |
1289 | OS << "|(1ULL<<MCID::Authenticated)" ; |
1290 | |
1291 | // Emit all of the target-specific flags... |
1292 | BitsInit *TSF = Inst.TheDef->getValueAsBitsInit(FieldName: "TSFlags" ); |
1293 | if (!TSF) |
1294 | PrintFatalError(ErrorLoc: Inst.TheDef->getLoc(), Msg: "no TSFlags?" ); |
1295 | uint64_t Value = 0; |
1296 | for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { |
1297 | if (const auto *Bit = dyn_cast<BitInit>(Val: TSF->getBit(Bit: i))) |
1298 | Value |= uint64_t(Bit->getValue()) << i; |
1299 | else |
1300 | PrintFatalError(ErrorLoc: Inst.TheDef->getLoc(), |
1301 | Msg: "Invalid TSFlags bit in " + Inst.TheDef->getName()); |
1302 | } |
1303 | OS << ", 0x" ; |
1304 | OS.write_hex(N: Value); |
1305 | OS << "ULL" ; |
1306 | |
1307 | OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n" ; |
1308 | } |
1309 | |
1310 | // emitEnums - Print out enum values for all of the instructions. |
1311 | void InstrInfoEmitter::emitEnums(raw_ostream &OS) { |
1312 | OS << "#ifdef GET_INSTRINFO_ENUM\n" ; |
1313 | OS << "#undef GET_INSTRINFO_ENUM\n" ; |
1314 | |
1315 | OS << "namespace llvm {\n\n" ; |
1316 | |
1317 | const CodeGenTarget &Target = CDP.getTargetInfo(); |
1318 | |
1319 | // We must emit the PHI opcode first... |
1320 | StringRef Namespace = Target.getInstNamespace(); |
1321 | |
1322 | if (Namespace.empty()) |
1323 | PrintFatalError(Msg: "No instructions defined!" ); |
1324 | |
1325 | OS << "namespace " << Namespace << " {\n" ; |
1326 | OS << " enum {\n" ; |
1327 | unsigned Num = 0; |
1328 | for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) |
1329 | OS << " " << Inst->TheDef->getName() |
1330 | << "\t= " << (Num = Target.getInstrIntValue(R: Inst->TheDef)) << ",\n" ; |
1331 | OS << " INSTRUCTION_LIST_END = " << Num + 1 << "\n" ; |
1332 | OS << " };\n\n" ; |
1333 | OS << "} // end namespace " << Namespace << "\n" ; |
1334 | OS << "} // end namespace llvm\n" ; |
1335 | OS << "#endif // GET_INSTRINFO_ENUM\n\n" ; |
1336 | |
1337 | OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n" ; |
1338 | OS << "#undef GET_INSTRINFO_SCHED_ENUM\n" ; |
1339 | OS << "namespace llvm {\n\n" ; |
1340 | OS << "namespace " << Namespace << " {\n" ; |
1341 | OS << "namespace Sched {\n" ; |
1342 | OS << " enum {\n" ; |
1343 | Num = 0; |
1344 | for (const auto &Class : SchedModels.explicit_classes()) |
1345 | OS << " " << Class.Name << "\t= " << Num++ << ",\n" ; |
1346 | OS << " SCHED_LIST_END = " << Num << "\n" ; |
1347 | OS << " };\n" ; |
1348 | OS << "} // end namespace Sched\n" ; |
1349 | OS << "} // end namespace " << Namespace << "\n" ; |
1350 | OS << "} // end namespace llvm\n" ; |
1351 | |
1352 | OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n" ; |
1353 | } |
1354 | |
1355 | static void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) { |
1356 | RK.startTimer(Name: "Analyze DAG patterns" ); |
1357 | InstrInfoEmitter(RK).run(OS); |
1358 | RK.startTimer(Name: "Emit map table" ); |
1359 | EmitMapTable(RK, OS); |
1360 | } |
1361 | |
1362 | static TableGen::Emitter::Opt X("gen-instr-info" , EmitInstrInfo, |
1363 | "Generate instruction descriptions" ); |
1364 | |