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