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