1//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
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 emits an assembly printer for the current target.
10// Note that this is currently fairly skeletal, but will grow over time.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Basic/SequenceToOffsetTable.h"
15#include "Common/AsmWriterInst.h"
16#include "Common/CodeGenInstAlias.h"
17#include "Common/CodeGenInstruction.h"
18#include "Common/CodeGenRegisters.h"
19#include "Common/CodeGenTarget.h"
20#include "Common/Types.h"
21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/MapVector.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringExtras.h"
28#include "llvm/ADT/StringRef.h"
29#include "llvm/ADT/Twine.h"
30#include "llvm/Support/Casting.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/Format.h"
33#include "llvm/Support/FormatVariadic.h"
34#include "llvm/Support/MathExtras.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/TableGen/Error.h"
37#include "llvm/TableGen/Record.h"
38#include "llvm/TableGen/TableGenBackend.h"
39#include <algorithm>
40#include <cassert>
41#include <cstddef>
42#include <cstdint>
43#include <deque>
44#include <iterator>
45#include <map>
46#include <set>
47#include <string>
48#include <tuple>
49#include <utility>
50#include <vector>
51
52using namespace llvm;
53
54#define DEBUG_TYPE "asm-writer-emitter"
55
56namespace {
57
58/// A group of instructions that share identical printing logic except for at
59/// most one differing operand.
60struct InstructionGroup {
61 AsmWriterInst FirstInst;
62 std::vector<AsmWriterInst> SimilarInsts;
63 unsigned DifferingOperand = ~0;
64
65 InstructionGroup(AsmWriterInst FirstInst) : FirstInst(std::move(FirstInst)) {}
66};
67
68class AsmWriterEmitter {
69 const RecordKeeper &Records;
70 CodeGenTarget Target;
71 ArrayRef<const CodeGenInstruction *> NumberedInstructions;
72 std::vector<AsmWriterInst> Instructions;
73
74public:
75 AsmWriterEmitter(const RecordKeeper &R);
76
77 void run(raw_ostream &o);
78
79private:
80 void EmitGetMnemonic(
81 raw_ostream &o,
82 std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
83 unsigned &BitsLeft, unsigned &AsmStrBits);
84 void EmitPrintInstruction(
85 raw_ostream &o,
86 std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
87 unsigned &BitsLeft, unsigned &AsmStrBits);
88 void EmitGetRegisterName(raw_ostream &o);
89 void EmitPrintAliasInstruction(raw_ostream &O);
90
91 void FindUniqueOperandCommands(std::vector<std::string> &UOC,
92 std::vector<std::vector<unsigned>> &InstIdxs,
93 std::vector<unsigned> &InstOpsUsed,
94 bool PassSubtarget) const;
95};
96
97} // end anonymous namespace
98
99static void
100PrintCases(std::vector<std::pair<std::string, AsmWriterOperand>> &OpsToPrint,
101 raw_ostream &O, bool PassSubtarget) {
102 O << " case " << OpsToPrint.back().first << ":";
103 AsmWriterOperand TheOp = OpsToPrint.back().second;
104 OpsToPrint.pop_back();
105
106 // Check to see if any other operands are identical in this list, and if so,
107 // emit a case label for them.
108 for (unsigned i = OpsToPrint.size(); i != 0; --i)
109 if (OpsToPrint[i - 1].second == TheOp) {
110 O << "\n case " << OpsToPrint[i - 1].first << ":";
111 OpsToPrint.erase(position: OpsToPrint.begin() + i - 1);
112 }
113
114 // Finally, emit the code.
115 O << "\n " << TheOp.getCode(PassSubtarget);
116 O << "\n break;\n";
117}
118
119/// Group instructions by similarity. When ExactMatch is true, only group
120/// instructions with identical operand sequences (for the bytecode path).
121static std::vector<InstructionGroup>
122groupInstructions(std::vector<AsmWriterInst> &Insts, bool ExactMatch = false) {
123 std::vector<InstructionGroup> Groups;
124 while (!Insts.empty()) {
125 InstructionGroup &G = Groups.emplace_back(args: std::move(Insts.back()));
126 Insts.pop_back();
127
128 for (unsigned I = Insts.size(); I != 0; --I) {
129 unsigned DiffOp = Insts[I - 1].MatchesAllButOneOp(Other: G.FirstInst);
130 if (DiffOp == ~0U || (!ExactMatch && DiffOp != ~1U)) {
131 if (G.DifferingOperand == ~0U) // First match!
132 G.DifferingOperand = DiffOp;
133
134 // If this differs in the same operand as the rest of the instructions
135 // in this class, move it to the SimilarInsts list.
136 if (G.DifferingOperand == DiffOp || DiffOp == ~0U) {
137 G.SimilarInsts.push_back(x: Insts[I - 1]);
138 Insts.erase(position: Insts.begin() + I - 1);
139 }
140 }
141 }
142 }
143 return Groups;
144}
145
146/// Emit operand printing code for an instruction group.
147static void emitInstructionOperands(const InstructionGroup &G, raw_ostream &O,
148 bool PassSubtarget) {
149 for (unsigned I = 0, E = G.FirstInst.Operands.size(); I != E; ++I) {
150 if (I != G.DifferingOperand) {
151 // If the operand is the same for all instructions, just print it.
152 O << " " << G.FirstInst.Operands[I].getCode(PassSubtarget);
153 } else {
154 // If this is the operand that varies between all of the instructions,
155 // emit a switch for just this operand now.
156 O << " switch (MI->getOpcode()) {\n";
157 O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
158 std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
159 OpsToPrint.emplace_back(args: G.FirstInst.CGI->Namespace.str() +
160 "::" + G.FirstInst.CGI->getName().str(),
161 args: G.FirstInst.Operands[I]);
162
163 for (const AsmWriterInst &AWI : G.SimilarInsts) {
164 OpsToPrint.emplace_back(args: AWI.CGI->Namespace.str() +
165 "::" + AWI.CGI->getName().str(),
166 args: AWI.Operands[I]);
167 }
168 std::reverse(first: OpsToPrint.begin(), last: OpsToPrint.end());
169 while (!OpsToPrint.empty())
170 PrintCases(OpsToPrint, O, PassSubtarget);
171 O << " }";
172 }
173 O << "\n";
174 }
175}
176
177/// Emit the case labels and operand printing code for an instruction group.
178static void emitInstructions(const InstructionGroup &G, raw_ostream &O,
179 bool PassSubtarget) {
180 O << " case " << G.FirstInst.CGI->Namespace
181 << "::" << G.FirstInst.CGI->getName() << ":\n";
182 for (const AsmWriterInst &AWI : G.SimilarInsts)
183 O << " case " << AWI.CGI->Namespace << "::" << AWI.CGI->getName() << ":\n";
184 emitInstructionOperands(G, O, PassSubtarget);
185 O << " break;\n";
186}
187
188/// Emit the bytecode tables and interpreter loop for overflow instructions.
189/// Instructions with identical operand sequences share the same offset (via
190/// groupInstructions with ExactMatch=true). Tables are emitted as static const
191/// arrays inside printInstruction() so that local variables remain in scope.
192static void
193EmitOverflowBytecodeSection(raw_ostream &O, StringRef TargetName,
194 const std::vector<InstructionGroup> &Groups,
195 ArrayRef<const CodeGenInstruction *> NumberedInsts,
196 bool PassSubtarget) {
197 // Bytecode 0 = unexpected-opcode sentinel, 1 = return terminator (already
198 // the last operand of every AsmWriterInst).
199 // Pre-seeding ensures AWI.Operands' trailing "return;" maps to index 1.
200 MapVector<std::string, unsigned, StringMap<unsigned>> Commands;
201 Commands.insert(KV: {"llvm_unreachable(\"Unexpected opcode.\");", 0});
202 Commands.insert(KV: {"return;", 1});
203
204 // OpcodeToOffset[opcode] = starting index in OverflowProgram.
205 // Offset 0 is the unreachable sentinel for non-overflow opcodes.
206 // Real sequences start at offset 1.
207 std::vector<unsigned> OpcodeToOffset(NumberedInsts.size(), 0);
208 unsigned TotalSize = 1; // slot 0 = sentinel
209 for (const InstructionGroup &G : Groups) {
210 OpcodeToOffset[G.FirstInst.CGIIndex] = TotalSize;
211 for (const AsmWriterInst &AWI : G.SimilarInsts)
212 OpcodeToOffset[AWI.CGIIndex] = TotalSize;
213 TotalSize += G.FirstInst.Operands.size();
214 for (const AsmWriterOperand &Op : G.FirstInst.Operands)
215 Commands.try_emplace(Key: Op.getCode(PassSubtarget), Args: Commands.size());
216 }
217
218 StringRef OffsetType = getMinimalTypeForRange(Range: TotalSize - 1);
219 StringRef StmtType = getMinimalTypeForRange(Range: Commands.size() - 1);
220
221 O << " static const " << OffsetType << " OpcodeToOffset[] = {\n";
222 for (unsigned I = 0; I < NumberedInsts.size(); ++I)
223 O << " " << OpcodeToOffset[I] << ",\t// " << NumberedInsts[I]->getName()
224 << "\n";
225 O << " };\n";
226
227 O << " static const " << StmtType << " OverflowProgram[] = {\n"
228 << " /* 0 */ 0,\n"; // sentinel
229 unsigned Offset = 1;
230 for (const InstructionGroup &G : Groups) {
231 O << " /* " << Offset << " */";
232 for (const AsmWriterOperand &Op : G.FirstInst.Operands)
233 O << " " << Commands.lookup(Key: Op.getCode(PassSubtarget)) << ",";
234 O << "\n";
235 Offset += G.FirstInst.Operands.size();
236 }
237 O << " };\n";
238
239 O << " for (" << OffsetType
240 << " Idx = OpcodeToOffset[MI->getOpcode()];; ++Idx) {\n"
241 << " switch (OverflowProgram[Idx]) {\n"
242 << " default: llvm_unreachable(\"Unexpected bytecode command.\");\n";
243 for (auto &[Stmt, Idx] : Commands) {
244 O << " case " << Idx << ":\n " << Stmt << "\n";
245 if (Idx != 1) // bytecode 1 is the "return;" sequence terminator
246 O << " break;\n";
247 }
248 O << " }\n }\n";
249
250 LLVM_DEBUG(dbgs() << "[AsmWriter] " << TargetName << ": " << Groups.size()
251 << " unique sequences, " << Commands.size()
252 << " unique statements\n");
253}
254
255void AsmWriterEmitter::FindUniqueOperandCommands(
256 std::vector<std::string> &UniqueOperandCommands,
257 std::vector<std::vector<unsigned>> &InstIdxs,
258 std::vector<unsigned> &InstOpsUsed, bool PassSubtarget) const {
259 // This vector parallels UniqueOperandCommands, keeping track of which
260 // instructions each case are used for. It is a comma separated string of
261 // enums.
262 std::vector<std::string> InstrsForCase;
263 InstrsForCase.resize(new_size: UniqueOperandCommands.size());
264 InstOpsUsed.assign(n: UniqueOperandCommands.size(), val: 0);
265
266 for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
267 const AsmWriterInst &Inst = Instructions[i];
268 if (Inst.Operands.empty())
269 continue; // Instruction already done.
270
271 std::string Command =
272 " " + Inst.Operands[0].getCode(PassSubtarget) + "\n";
273
274 // Check to see if we already have 'Command' in UniqueOperandCommands.
275 // If not, add it.
276 auto I = llvm::find(Range&: UniqueOperandCommands, Val: Command);
277 if (I != UniqueOperandCommands.end()) {
278 size_t idx = I - UniqueOperandCommands.begin();
279 InstrsForCase[idx] += ", ";
280 InstrsForCase[idx] += Inst.CGI->getName();
281 InstIdxs[idx].push_back(x: i);
282 } else {
283 UniqueOperandCommands.push_back(x: std::move(Command));
284 InstrsForCase.push_back(x: Inst.CGI->getName().str());
285 InstIdxs.emplace_back();
286 InstIdxs.back().push_back(x: i);
287
288 // This command matches one operand so far.
289 InstOpsUsed.push_back(x: 1);
290 }
291 }
292
293 // For each entry of UniqueOperandCommands, there is a set of instructions
294 // that uses it. If the next command of all instructions in the set are
295 // identical, fold it into the command.
296 for (size_t CommandIdx = 0, e = UniqueOperandCommands.size(); CommandIdx != e;
297 ++CommandIdx) {
298
299 const auto &Idxs = InstIdxs[CommandIdx];
300
301 for (unsigned Op = 1;; ++Op) {
302 // Find the first instruction in the set.
303 const AsmWriterInst &FirstInst = Instructions[Idxs.front()];
304 // If this instruction has no more operands, we isn't anything to merge
305 // into this command.
306 if (FirstInst.Operands.size() == Op)
307 break;
308
309 // Otherwise, scan to see if all of the other instructions in this command
310 // set share the operand.
311 if (any_of(Range: drop_begin(RangeOrContainer: Idxs), P: [&](unsigned Idx) {
312 const AsmWriterInst &OtherInst = Instructions[Idx];
313 return OtherInst.Operands.size() == Op ||
314 OtherInst.Operands[Op] != FirstInst.Operands[Op];
315 }))
316 break;
317
318 // Okay, everything in this command set has the same next operand. Add it
319 // to UniqueOperandCommands and remember that it was consumed.
320 std::string Command =
321 " " + FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
322
323 UniqueOperandCommands[CommandIdx] += Command;
324 InstOpsUsed[CommandIdx]++;
325 }
326 }
327
328 // Prepend some of the instructions each case is used for onto the case val.
329 for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
330 std::string Instrs = InstrsForCase[i];
331 if (Instrs.size() > 70) {
332 Instrs.erase(first: Instrs.begin() + 70, last: Instrs.end());
333 Instrs += "...";
334 }
335
336 if (!Instrs.empty())
337 UniqueOperandCommands[i] =
338 " // " + Instrs + "\n" + UniqueOperandCommands[i];
339 }
340}
341
342static void UnescapeString(std::string &Str) {
343 for (unsigned i = 0; i != Str.size(); ++i) {
344 if (Str[i] == '\\' && i != Str.size() - 1) {
345 switch (Str[i + 1]) {
346 default:
347 continue; // Don't execute the code after the switch.
348 case 'a':
349 Str[i] = '\a';
350 break;
351 case 'b':
352 Str[i] = '\b';
353 break;
354 case 'e':
355 Str[i] = 27;
356 break;
357 case 'f':
358 Str[i] = '\f';
359 break;
360 case 'n':
361 Str[i] = '\n';
362 break;
363 case 'r':
364 Str[i] = '\r';
365 break;
366 case 't':
367 Str[i] = '\t';
368 break;
369 case 'v':
370 Str[i] = '\v';
371 break;
372 case '"':
373 Str[i] = '\"';
374 break;
375 case '\'':
376 Str[i] = '\'';
377 break;
378 case '\\':
379 Str[i] = '\\';
380 break;
381 }
382 // Nuke the second character.
383 Str.erase(position: Str.begin() + i + 1);
384 }
385 }
386}
387
388/// UnescapeAliasString - Supports literal braces in InstAlias asm string which
389/// are escaped with '\\' to avoid being interpreted as variants. Braces must
390/// be unescaped before c++ code is generated as (e.g.):
391///
392/// AsmString = "foo \{$\x01\}";
393///
394/// causes non-standard escape character warnings.
395static void UnescapeAliasString(std::string &Str) {
396 for (unsigned i = 0; i != Str.size(); ++i) {
397 if (Str[i] == '\\' && i != Str.size() - 1) {
398 switch (Str[i + 1]) {
399 default:
400 continue; // Don't execute the code after the switch.
401 case '{':
402 Str[i] = '{';
403 break;
404 case '}':
405 Str[i] = '}';
406 break;
407 }
408 // Nuke the second character.
409 Str.erase(position: Str.begin() + i + 1);
410 }
411 }
412}
413
414void AsmWriterEmitter::EmitGetMnemonic(
415 raw_ostream &O,
416 std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
417 unsigned &BitsLeft, unsigned &AsmStrBits) {
418 const Record *AsmWriter = Target.getAsmWriter();
419 StringRef ClassName = AsmWriter->getValueAsString(FieldName: "AsmWriterClassName");
420 bool PassSubtarget = AsmWriter->getValueAsInt(FieldName: "PassSubtarget");
421
422 O << "/// getMnemonic - This method is automatically generated by "
423 "tablegen\n"
424 "/// from the instruction set description.\n"
425 "std::pair<const char *, uint64_t>\n"
426 << Target.getName() << ClassName
427 << "::getMnemonic(const MCInst &MI) const {\n";
428
429 // Build an aggregate string, and build a table of offsets into it.
430 SequenceToOffsetTable<std::string> StringTable;
431
432 /// OpcodeInfo - This encodes the index of the string to use for the first
433 /// chunk of the output as well as indices used for operand printing.
434 std::vector<uint64_t> OpcodeInfo(NumberedInstructions.size());
435 const unsigned OpcodeInfoBits = 64;
436
437 // Add all strings to the string table upfront so it can generate an optimized
438 // representation.
439 for (AsmWriterInst &AWI : Instructions) {
440 if (AWI.Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand &&
441 !AWI.Operands[0].Str.empty()) {
442 std::string Str = AWI.Operands[0].Str;
443 UnescapeString(Str);
444 StringTable.add(Seq: Str);
445 }
446 }
447
448 StringTable.layout();
449
450 unsigned MaxStringIdx = 0;
451 for (AsmWriterInst &AWI : Instructions) {
452 unsigned Idx;
453 if (AWI.Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand ||
454 AWI.Operands[0].Str.empty()) {
455 // Something handled by the asmwriter printer, but with no leading string.
456 Idx = StringTable.get(Seq: "");
457 } else {
458 std::string Str = AWI.Operands[0].Str;
459 UnescapeString(Str);
460 Idx = StringTable.get(Seq: Str);
461 MaxStringIdx = std::max(a: MaxStringIdx, b: Idx);
462
463 // Nuke the string from the operand list. It is now handled!
464 AWI.Operands.erase(position: AWI.Operands.begin());
465 }
466
467 // Bias offset by one since we want 0 as a sentinel.
468 OpcodeInfo[AWI.CGIIndex] = Idx + 1;
469 }
470
471 // Figure out how many bits we used for the string index.
472 AsmStrBits = Log2_32_Ceil(Value: MaxStringIdx + 2);
473
474 // To reduce code size, we compactify common instructions into a few bits
475 // in the opcode-indexed table.
476 BitsLeft = OpcodeInfoBits - AsmStrBits;
477
478 while (true) {
479 std::vector<std::string> UniqueOperandCommands;
480 std::vector<std::vector<unsigned>> InstIdxs;
481 std::vector<unsigned> NumInstOpsHandled;
482 FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
483 InstOpsUsed&: NumInstOpsHandled, PassSubtarget);
484
485 // If we ran out of operands to print, we're done.
486 if (UniqueOperandCommands.empty())
487 break;
488
489 // Compute the number of bits we need to represent these cases, this is
490 // ceil(log2(numentries)).
491 unsigned NumBits = Log2_32_Ceil(Value: UniqueOperandCommands.size());
492
493 // If we don't have enough bits for this operand, don't include it.
494 if (NumBits > BitsLeft) {
495 LLVM_DEBUG(dbgs() << "Not enough bits to densely encode " << NumBits
496 << " more bits\n");
497 break;
498 }
499
500 // Otherwise, we can include this in the initial lookup table. Add it in.
501 for (size_t i = 0, e = InstIdxs.size(); i != e; ++i) {
502 unsigned NumOps = NumInstOpsHandled[i];
503 for (unsigned Idx : InstIdxs[i]) {
504 OpcodeInfo[Instructions[Idx].CGIIndex] |=
505 (uint64_t)i << (OpcodeInfoBits - BitsLeft);
506 // Remove the info about this operand from the instruction.
507 AsmWriterInst &Inst = Instructions[Idx];
508 if (!Inst.Operands.empty()) {
509 assert(NumOps <= Inst.Operands.size() &&
510 "Can't remove this many ops!");
511 Inst.Operands.erase(first: Inst.Operands.begin(),
512 last: Inst.Operands.begin() + NumOps);
513 }
514 }
515 }
516 BitsLeft -= NumBits;
517
518 // Remember the handlers for this set of operands.
519 TableDrivenOperandPrinters.push_back(x: std::move(UniqueOperandCommands));
520 }
521
522 // Emit the string table itself.
523 StringTable.emitStringLiteralDef(OS&: O, Decl: " static const char AsmStrs[]");
524
525 // Emit the lookup tables in pieces to minimize wasted bytes.
526 unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
527 unsigned Table = 0, Shift = 0;
528 SmallString<128> BitsString;
529 raw_svector_ostream BitsOS(BitsString);
530 // If the total bits is more than 32-bits we need to use a 64-bit type.
531 BitsOS << " uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
532 << "_t Bits = 0;\n";
533 while (BytesNeeded != 0) {
534 // Figure out how big this table section needs to be.
535 unsigned TableSize = llvm::bit_floor(Value: BytesNeeded);
536 BytesNeeded -= TableSize;
537 TableSize *= 8; // Convert to bits;
538 uint64_t Mask = maskTrailingOnes<uint64_t>(N: TableSize);
539 O << " static const uint" << TableSize << "_t OpInfo" << Table
540 << "[] = {\n";
541 StringRef Suffix = TableSize == 64 ? "ULL" : "U";
542 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
543 O << " " << ((OpcodeInfo[i] >> Shift) & Mask) << Suffix << ",\t// "
544 << NumberedInstructions[i]->getName() << '\n';
545 }
546 O << " };\n\n";
547 // Emit string to combine the individual table lookups.
548 BitsOS << " Bits |= ";
549 // If the total bits is more than 32-bits we need to use a 64-bit type.
550 if (BitsLeft < (OpcodeInfoBits - 32))
551 BitsOS << "(uint64_t)";
552 BitsOS << "OpInfo" << Table << "[MI.getOpcode()] << " << Shift << ";\n";
553 // Prepare the shift for the next iteration and increment the table count.
554 Shift += TableSize;
555 ++Table;
556 }
557
558 O << " // Emit the opcode for the instruction.\n";
559 O << BitsString;
560
561 // Make sure we don't return an invalid pointer if bits is 0
562 O << " if (Bits == 0)\n"
563 " return {nullptr, Bits};\n";
564
565 // Return mnemonic string and bits.
566 O << " return {AsmStrs+(Bits & " << (1 << AsmStrBits) - 1
567 << ")-1, Bits};\n\n";
568
569 O << "}\n";
570}
571
572/// EmitPrintInstruction - Generate the code for the "printInstruction" method
573/// implementation. Destroys all instances of AsmWriterInst information, by
574/// clearing the Instructions vector.
575void AsmWriterEmitter::EmitPrintInstruction(
576 raw_ostream &O,
577 std::vector<std::vector<std::string>> &TableDrivenOperandPrinters,
578 unsigned &BitsLeft, unsigned &AsmStrBits) {
579 const unsigned OpcodeInfoBits = 64;
580 const Record *AsmWriter = Target.getAsmWriter();
581 StringRef ClassName = AsmWriter->getValueAsString(FieldName: "AsmWriterClassName");
582 bool PassSubtarget = AsmWriter->getValueAsInt(FieldName: "PassSubtarget");
583 bool UseBytecode = AsmWriter->getValueAsBit(FieldName: "UseBytecode");
584
585 // This function has some huge switch statements that causing excessive
586 // compile time in LLVM profile instrumenation build. This print function
587 // usually is not frequently called in compilation. Here we disable the
588 // profile instrumenation for this function.
589 O << "/// printInstruction - This method is automatically generated by "
590 "tablegen\n"
591 "/// from the instruction set description.\n"
592 "LLVM_NO_PROFILE_INSTRUMENT_FUNCTION\n"
593 "void "
594 << Target.getName() << ClassName
595 << "::printInstruction(const MCInst *MI, uint64_t Address, "
596 << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
597 << "raw_ostream &O) {\n";
598
599 // Emit the initial tab character.
600 O << " O << \"\\t\";\n\n";
601
602 // Emit the starting string.
603 O << " auto MnemonicInfo = getMnemonic(*MI);\n\n";
604 O << " O << MnemonicInfo.first;\n\n";
605
606 O << " uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
607 << "_t Bits = MnemonicInfo.second;\n"
608 << " assert(Bits != 0 && \"Cannot print this instruction.\");\n";
609
610 // Output the table driven operand information.
611 BitsLeft = OpcodeInfoBits - AsmStrBits;
612 for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
613 std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
614
615 // Compute the number of bits we need to represent these cases, this is
616 // ceil(log2(numentries)).
617 unsigned NumBits = Log2_32_Ceil(Value: Commands.size());
618 assert(NumBits <= BitsLeft && "consistency error");
619
620 // Emit code to extract this field from Bits.
621 O << "\n // Fragment " << i << " encoded into " << NumBits << " bits for "
622 << Commands.size() << " unique commands.\n";
623
624 if (Commands.size() == 2) {
625 // Emit two possibilitys with if/else.
626 O << " if ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
627 << ((1 << NumBits) - 1) << ") {\n"
628 << Commands[1] << " } else {\n"
629 << Commands[0] << " }\n\n";
630 } else if (Commands.size() == 1) {
631 // Emit a single possibility.
632 O << Commands[0] << "\n\n";
633 } else {
634 O << " switch ((Bits >> " << (OpcodeInfoBits - BitsLeft) << ") & "
635 << ((1 << NumBits) - 1) << ") {\n"
636 << " default: llvm_unreachable(\"Invalid command number.\");\n";
637
638 // Print out all the cases.
639 for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
640 O << " case " << j << ":\n";
641 O << Commands[j];
642 O << " break;\n";
643 }
644 O << " }\n\n";
645 }
646 BitsLeft -= NumBits;
647 }
648
649 // Now that we've emitted all of the operand info that fit into 64 bits, emit
650 // information for those instructions that are left. This is a less dense
651 // encoding, but we expect the main 64-bit table to handle the majority of
652 // instructions.
653 // Delete instructions with no operand info left so that the emptiness check
654 // below only considers overflow instructions.
655 llvm::erase_if(C&: Instructions,
656 P: [](AsmWriterInst &Inst) { return Inst.Operands.empty(); });
657
658 if (!Instructions.empty()) {
659 // Because this is a vector, we want to emit from the end. Reverse all
660 // of the elements in the vector.
661 std::reverse(first: Instructions.begin(), last: Instructions.end());
662
663 std::vector<InstructionGroup> Groups =
664 groupInstructions(Insts&: Instructions, ExactMatch: UseBytecode);
665 if (UseBytecode) {
666 EmitOverflowBytecodeSection(O, TargetName: Target.getName(), Groups,
667 NumberedInsts: NumberedInstructions, PassSubtarget);
668 } else {
669 O << " switch (MI->getOpcode()) {\n";
670 O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
671 for (const InstructionGroup &G : Groups)
672 emitInstructions(G, O, PassSubtarget);
673
674 O << " }\n";
675 }
676 }
677
678 O << "}\n";
679}
680
681static void
682emitRegisterNameString(raw_ostream &O, StringRef AltName,
683 const std::deque<CodeGenRegister> &Registers) {
684 SequenceToOffsetTable<std::string> StringTable;
685 SmallVector<std::string, 4> AsmNames(Registers.size());
686 unsigned i = 0;
687 for (const auto &Reg : Registers) {
688 std::string &AsmName = AsmNames[i++];
689
690 // "NoRegAltName" is special. We don't need to do a lookup for that,
691 // as it's just a reference to the default register name.
692 if (AltName == "" || AltName == "NoRegAltName") {
693 AsmName = Reg.TheDef->getValueAsString(FieldName: "AsmName").str();
694 if (AsmName.empty())
695 AsmName = Reg.getName().str();
696 } else {
697 // Make sure the register has an alternate name for this index.
698 std::vector<const Record *> AltNameList =
699 Reg.TheDef->getValueAsListOfDefs(FieldName: "RegAltNameIndices");
700 unsigned Idx = 0, e;
701 for (e = AltNameList.size();
702 Idx < e && (AltNameList[Idx]->getName() != AltName); ++Idx)
703 ;
704 // If the register has an alternate name for this index, use it.
705 // Otherwise, leave it empty as an error flag.
706 if (Idx < e) {
707 std::vector<StringRef> AltNames =
708 Reg.TheDef->getValueAsListOfStrings(FieldName: "AltNames");
709 if (AltNames.size() <= Idx)
710 PrintFatalError(ErrorLoc: Reg.TheDef->getLoc(),
711 Msg: "Register definition missing alt name for '" +
712 AltName + "'.");
713 AsmName = AltNames[Idx].str();
714 }
715 }
716 StringTable.add(Seq: AsmName);
717 }
718
719 StringTable.layout();
720 StringTable.emitStringLiteralDef(OS&: O, Decl: Twine(" static const char AsmStrs") +
721 AltName + "[]");
722
723 O << " static const " << getMinimalTypeForRange(Range: StringTable.size() - 1, MaxSize: 32)
724 << " RegAsmOffset" << AltName << "[] = {";
725 for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
726 if ((i % 14) == 0)
727 O << "\n ";
728 O << StringTable.get(Seq: AsmNames[i]) << ", ";
729 }
730 O << "\n };\n"
731 << "\n";
732}
733
734void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
735 const Record *AsmWriter = Target.getAsmWriter();
736 StringRef ClassName = AsmWriter->getValueAsString(FieldName: "AsmWriterClassName");
737 const auto &Registers = Target.getRegBank().getRegisters();
738 ArrayRef<const Record *> AltNameIndices = Target.getRegAltNameIndices();
739 bool hasAltNames = AltNameIndices.size() > 1;
740 StringRef Namespace = Registers.front().TheDef->getValueAsString(FieldName: "Namespace");
741
742 O << "\n\n/// getRegisterName - This method is automatically generated by "
743 "tblgen\n"
744 "/// from the register set description. This returns the assembler "
745 "name\n"
746 "/// for the specified register.\n"
747 "const char *"
748 << Target.getName() << ClassName << "::";
749 if (hasAltNames)
750 O << "\ngetRegisterName(MCRegister Reg, unsigned AltIdx) {\n";
751 else
752 O << "getRegisterName(MCRegister Reg) {\n";
753 O << " unsigned RegNo = Reg.id();\n"
754 << " assert(RegNo && RegNo < " << (Registers.size() + 1)
755 << " && \"Invalid register number!\");\n"
756 << "\n";
757
758 if (hasAltNames) {
759 for (const Record *R : AltNameIndices)
760 emitRegisterNameString(O, AltName: R->getName(), Registers);
761 } else {
762 emitRegisterNameString(O, AltName: "", Registers);
763 }
764
765 if (hasAltNames) {
766 O << " switch(AltIdx) {\n"
767 << " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
768 for (const Record *R : AltNameIndices) {
769 StringRef AltName = R->getName();
770 O << " case ";
771 if (!Namespace.empty())
772 O << Namespace << "::";
773 O << AltName << ":\n";
774 if (R->isValueUnset(FieldName: "FallbackRegAltNameIndex"))
775 O << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
776 << "[RegNo-1]) &&\n"
777 << " \"Invalid alt name index for register!\");\n";
778 else {
779 O << " if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
780 << "[RegNo-1]))\n"
781 << " return getRegisterName(RegNo, ";
782 if (!Namespace.empty())
783 O << Namespace << "::";
784 O << R->getValueAsDef(FieldName: "FallbackRegAltNameIndex")->getName() << ");\n";
785 }
786 O << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName
787 << "[RegNo-1];\n";
788 }
789 O << " }\n";
790 } else {
791 O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
792 << " \"Invalid alt name index for register!\");\n"
793 << " return AsmStrs+RegAsmOffset[RegNo-1];\n";
794 }
795 O << "}\n";
796}
797
798namespace {
799
800// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
801// they both have the same conditionals. In which case, we cannot print out the
802// alias for that pattern.
803class IAPrinter {
804 std::map<StringRef, std::pair<int, int>> OpMap;
805
806 std::vector<std::string> Conds;
807
808 std::string Result;
809 std::string AsmString;
810
811 unsigned NumMIOps;
812
813public:
814 IAPrinter(std::string R, std::string AS, unsigned NumMIOps)
815 : Result(std::move(R)), AsmString(std::move(AS)), NumMIOps(NumMIOps) {}
816
817 void addCond(std::string C) { Conds.push_back(x: std::move(C)); }
818 ArrayRef<std::string> getConds() const { return Conds; }
819 size_t getCondCount() const { return Conds.size(); }
820
821 void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) {
822 assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range");
823 assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF && "Idx out of range");
824 OpMap[Op] = {OpIdx, PrintMethodIdx};
825 }
826
827 unsigned getNumMIOps() { return NumMIOps; }
828
829 StringRef getResult() { return Result; }
830
831 bool isOpMapped(StringRef Op) { return OpMap.find(x: Op) != OpMap.end(); }
832 int getOpIndex(StringRef Op) { return OpMap[Op].first; }
833 std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; }
834
835 std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start,
836 StringRef::iterator End) {
837 StringRef::iterator I = Start;
838 StringRef::iterator Next;
839 if (*I == '{') {
840 // ${some_name}
841 Start = ++I;
842 while (I != End && *I != '}')
843 ++I;
844 Next = I;
845 // eat the final '}'
846 if (Next != End)
847 ++Next;
848 } else {
849 // $name, just eat the usual suspects.
850 while (I != End && (isAlnum(C: *I) || *I == '_'))
851 ++I;
852 Next = I;
853 }
854
855 return {StringRef(Start, I - Start), Next};
856 }
857
858 std::string formatAliasString(uint32_t &UnescapedSize) {
859 // Directly mangle mapped operands into the string. Each operand is
860 // identified by a '$' sign followed by a byte identifying the number of the
861 // operand. We add one to the index to avoid zero bytes.
862 StringRef ASM(AsmString);
863 std::string OutString;
864 raw_string_ostream OS(OutString);
865 for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) {
866 OS << *I;
867 ++UnescapedSize;
868 if (*I == '$') {
869 StringRef Name;
870 std::tie(args&: Name, args&: I) = parseName(Start: ++I, End: E);
871 assert(isOpMapped(Name) && "Unmapped operand!");
872
873 int OpIndex, PrintIndex;
874 std::tie(args&: OpIndex, args&: PrintIndex) = getOpData(Op: Name);
875 if (PrintIndex == -1) {
876 // Can use the default printOperand route.
877 OS << format(Fmt: "\\x%02X", Vals: (unsigned char)OpIndex + 1);
878 ++UnescapedSize;
879 } else {
880 // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand
881 // number, and which of our pre-detected Methods to call.
882 OS << format(Fmt: "\\xFF\\x%02X\\x%02X", Vals: OpIndex + 1, Vals: PrintIndex + 1);
883 UnescapedSize += 3;
884 }
885 } else {
886 ++I;
887 }
888 }
889 return OutString;
890 }
891
892 bool operator==(const IAPrinter &RHS) const {
893 if (NumMIOps != RHS.NumMIOps)
894 return false;
895 if (Conds.size() != RHS.Conds.size())
896 return false;
897
898 unsigned Idx = 0;
899 for (const auto &str : Conds)
900 if (str != RHS.Conds[Idx++])
901 return false;
902
903 return true;
904 }
905};
906
907} // end anonymous namespace
908
909static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
910 return AsmString.count(C: ' ') + AsmString.count(C: '\t');
911}
912
913namespace {
914
915struct AliasPriorityComparator {
916 using ValueType = std::pair<CodeGenInstAlias, int>;
917 bool operator()(const ValueType &LHS, const ValueType &RHS) const {
918 if (LHS.second == RHS.second) {
919 // We don't actually care about the order, but for consistency it
920 // shouldn't depend on pointer comparisons.
921 return LessRecordByID()(LHS.first.TheDef, RHS.first.TheDef);
922 }
923
924 // Aliases with larger priorities should be considered first.
925 return LHS.second > RHS.second;
926 }
927};
928
929} // end anonymous namespace
930
931void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
932 const Record *AsmWriter = Target.getAsmWriter();
933
934 O << "\n#ifdef PRINT_ALIAS_INSTR\n";
935 O << "#undef PRINT_ALIAS_INSTR\n\n";
936
937 //////////////////////////////
938 // Gather information about aliases we need to print
939 //////////////////////////////
940
941 // Emit the method that prints the alias instruction.
942 StringRef ClassName = AsmWriter->getValueAsString(FieldName: "AsmWriterClassName");
943 unsigned Variant = AsmWriter->getValueAsInt(FieldName: "Variant");
944 bool PassSubtarget = AsmWriter->getValueAsInt(FieldName: "PassSubtarget");
945
946 // Create a map from the qualified name to a list of potential matches.
947 using AliasWithPriority =
948 std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>;
949 std::map<std::string, AliasWithPriority> AliasMap;
950 for (const Record *R : Records.getAllDerivedDefinitions(ClassName: "InstAlias")) {
951 int Priority = R->getValueAsInt(FieldName: "EmitPriority");
952 if (Priority < 1)
953 continue; // Aliases with priority 0 are never emitted.
954
955 const DagInit *DI = R->getValueAsDag(FieldName: "ResultInst");
956 AliasMap[getQualifiedName(R: DI->getOperatorAsDef(Loc: R->getLoc()))].emplace(
957 args: CodeGenInstAlias(R, Target), args&: Priority);
958 }
959
960 // A map of which conditions need to be met for each instruction operand
961 // before it can be matched to the mnemonic.
962 std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
963
964 std::vector<std::pair<std::string, bool>> PrintMethods;
965
966 // A list of MCOperandPredicates for all operands in use, and the reverse map
967 std::vector<const Record *> MCOpPredicates;
968 DenseMap<const Record *, unsigned> MCOpPredicateMap;
969
970 for (auto &Aliases : AliasMap) {
971 for (auto &Alias : Aliases.second) {
972 const CodeGenInstAlias &CGA = Alias.first;
973 unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
974 std::string FlatInstAsmString =
975 CodeGenInstruction::FlattenAsmStringVariants(
976 AsmString: CGA.ResultInst->AsmString, Variant);
977 unsigned NumResultOps = CountNumOperands(AsmString: FlatInstAsmString, Variant);
978
979 std::string FlatAliasAsmString =
980 CodeGenInstruction::FlattenAsmStringVariants(AsmString: CGA.AsmString, Variant);
981 UnescapeAliasString(Str&: FlatAliasAsmString);
982
983 // Don't emit the alias if it has more operands than what it's aliasing.
984 if (NumResultOps < CountNumOperands(AsmString: FlatAliasAsmString, Variant))
985 continue;
986
987 StringRef Namespace = Target.getName();
988 unsigned NumMIOps = 0;
989 for (auto &ResultInstOpnd : CGA.ResultInst->Operands)
990 NumMIOps += ResultInstOpnd.MINumOperands;
991
992 IAPrinter IAP(CGA.Result->getAsString(), FlatAliasAsmString, NumMIOps);
993
994 unsigned MIOpNum = 0;
995 for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
996 // Skip over tied operands as they're not part of an alias declaration.
997 auto &Operands = CGA.ResultInst->Operands;
998 while (true) {
999 unsigned OpNum = Operands.getSubOperandNumber(Op: MIOpNum).first;
1000 if (Operands[OpNum].MINumOperands == 1 &&
1001 Operands[OpNum].getTiedRegister() != -1) {
1002 // Tied operands of different RegisterClass should be explicit
1003 // within an instruction's syntax and so cannot be skipped.
1004 int TiedOpNum = Operands[OpNum].getTiedRegister();
1005 if (Operands[OpNum].Rec->getName() ==
1006 Operands[TiedOpNum].Rec->getName()) {
1007 ++MIOpNum;
1008 continue;
1009 }
1010 }
1011 break;
1012 }
1013
1014 // Ignore unchecked result operands.
1015 while (IAP.getCondCount() < MIOpNum)
1016 IAP.addCond(C: "AliasPatternCond::K_Ignore, 0");
1017
1018 const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
1019
1020 switch (RO.Kind) {
1021 case CodeGenInstAlias::ResultOperand::K_Record: {
1022 const Record *Rec = RO.getRecord();
1023 StringRef ROName = RO.getName();
1024 int PrintMethodIdx = -1;
1025
1026 // These two may have a PrintMethod, which we want to record (if it's
1027 // the first time we've seen it) and provide an index for the aliasing
1028 // code to use.
1029 if (Rec->isSubClassOf(Name: "RegisterOperand") ||
1030 Rec->isSubClassOf(Name: "Operand")) {
1031 StringRef PrintMethod = Rec->getValueAsString(FieldName: "PrintMethod");
1032 bool IsPCRel =
1033 Rec->getValueAsString(FieldName: "OperandType") == "OPERAND_PCREL";
1034 if (PrintMethod != "" && PrintMethod != "printOperand") {
1035 PrintMethodIdx = llvm::find_if(Range&: PrintMethods,
1036 P: [&](auto &X) {
1037 return X.first == PrintMethod;
1038 }) -
1039 PrintMethods.begin();
1040 if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
1041 PrintMethods.emplace_back(args: PrintMethod.str(), args&: IsPCRel);
1042 }
1043 }
1044
1045 if (Target.getAsRegClassLike(V: Rec)) {
1046 if (!IAP.isOpMapped(Op: ROName)) {
1047 IAP.addOperand(Op: ROName, OpIdx: MIOpNum, PrintMethodIdx);
1048 const Record *R =
1049 Target.getAsRegClassLike(V: CGA.ResultOperands[i].getRecord());
1050 assert(R && "Not a valid register class?");
1051 if (R->isSubClassOf(Name: "RegClassByHwMode")) {
1052 IAP.addCond(C: std::string(
1053 formatv(Fmt: "AliasPatternCond::K_RegClassByHwMode, {}::{}",
1054 Vals&: Namespace, Vals: R->getName())));
1055 } else {
1056 IAP.addCond(C: std::string(
1057 formatv(Fmt: "AliasPatternCond::K_RegClass, {}::{}RegClassID",
1058 Vals&: Namespace, Vals: R->getName())));
1059 }
1060 } else {
1061 IAP.addCond(C: std::string(formatv(Fmt: "AliasPatternCond::K_TiedReg, {}",
1062 Vals: IAP.getOpIndex(Op: ROName))));
1063 }
1064 } else {
1065 // Assume all printable operands are desired for now. This can be
1066 // overridden in the InstAlias instantiation if necessary.
1067 IAP.addOperand(Op: ROName, OpIdx: MIOpNum, PrintMethodIdx);
1068
1069 // There might be an additional predicate on the MCOperand
1070 unsigned &Entry = MCOpPredicateMap[Rec];
1071 if (!Entry) {
1072 if (!Rec->isValueUnset(FieldName: "MCOperandPredicate")) {
1073 MCOpPredicates.push_back(x: Rec);
1074 Entry = MCOpPredicates.size();
1075 } else {
1076 break; // No conditions on this operand at all
1077 }
1078 }
1079 IAP.addCond(
1080 C: std::string(formatv(Fmt: "AliasPatternCond::K_Custom, {}", Vals&: Entry)));
1081 }
1082 break;
1083 }
1084 case CodeGenInstAlias::ResultOperand::K_Imm: {
1085 // Just because the alias has an immediate result, doesn't mean the
1086 // MCInst will. An MCExpr could be present, for example.
1087 auto Imm = CGA.ResultOperands[i].getImm();
1088 int32_t Imm32 = int32_t(Imm);
1089 if (Imm != Imm32)
1090 PrintFatalError(Msg: "Matching an alias with an immediate out of the "
1091 "range of int32_t is not supported");
1092 IAP.addCond(C: std::string(
1093 formatv(Fmt: "AliasPatternCond::K_Imm, uint32_t({})", Vals&: Imm32)));
1094 break;
1095 }
1096 case CodeGenInstAlias::ResultOperand::K_Reg:
1097 if (!CGA.ResultOperands[i].getRegister()) {
1098 IAP.addCond(C: std::string(
1099 formatv(Fmt: "AliasPatternCond::K_Reg, {}::NoRegister", Vals&: Namespace)));
1100 break;
1101 }
1102
1103 const Record *Rec = CGA.ResultOperands[i].getRegister();
1104 StringRef Reg = Rec->getName();
1105 if (Rec->isSubClassOf(Name: "RegisterByHwMode")) {
1106 // Use a custom predicate to handle RegisterByHwMode since there
1107 // is no way to handle this in the generic code.
1108 unsigned &Entry = MCOpPredicateMap[Rec];
1109 if (!Entry) {
1110 MCOpPredicates.push_back(x: Rec);
1111 Entry = MCOpPredicates.size();
1112 }
1113 IAP.addCond(C: std::string(
1114 formatv(Fmt: "AliasPatternCond::K_Custom, {}/*{}*/", Vals&: Entry, Vals&: Reg)));
1115 } else {
1116 IAP.addCond(C: std::string(
1117 formatv(Fmt: "AliasPatternCond::K_Reg, {}::{}", Vals&: Namespace, Vals&: Reg)));
1118 }
1119 break;
1120 }
1121
1122 MIOpNum += RO.getMINumOperands();
1123 }
1124
1125 std::vector<const Record *> ReqFeatures;
1126 if (PassSubtarget) {
1127 // We only consider ReqFeatures predicates if PassSubtarget
1128 std::vector<const Record *> RF =
1129 CGA.TheDef->getValueAsListOfDefs(FieldName: "Predicates");
1130 copy_if(Range&: RF, Out: std::back_inserter(x&: ReqFeatures), P: [](const Record *R) {
1131 return R->getValueAsBit(FieldName: "AssemblerMatcherPredicate");
1132 });
1133 }
1134
1135 for (const Record *R : ReqFeatures) {
1136 const DagInit *D = R->getValueAsDag(FieldName: "AssemblerCondDag");
1137 auto *Op = dyn_cast<DefInit>(Val: D->getOperator());
1138 if (!Op)
1139 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Invalid AssemblerCondDag!");
1140 StringRef CombineType = Op->getDef()->getName();
1141 if (CombineType != "any_of" && CombineType != "all_of")
1142 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Invalid AssemblerCondDag!");
1143 if (D->getNumArgs() == 0)
1144 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Invalid AssemblerCondDag!");
1145 bool IsOr = CombineType == "any_of";
1146 // Change (any_of FeatureAll, (any_of ...)) to (any_of FeatureAll, ...).
1147 if (IsOr && D->getNumArgs() == 2 && isa<DagInit>(Val: D->getArg(Num: 1))) {
1148 const DagInit *RHS = cast<DagInit>(Val: D->getArg(Num: 1));
1149 SmallVector<std::pair<const Init *, const StringInit *>> Args{
1150 *D->getArgAndNames().begin()};
1151 llvm::append_range(C&: Args, R: RHS->getArgAndNames());
1152 D = DagInit::get(V: D->getOperator(), ArgAndNames: Args);
1153 }
1154
1155 for (auto *Arg : D->getArgs()) {
1156 bool IsNeg = false;
1157 if (auto *NotArg = dyn_cast<DagInit>(Val: Arg)) {
1158 if (NotArg->getOperator()->getAsString() != "not" ||
1159 NotArg->getNumArgs() != 1)
1160 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Invalid AssemblerCondDag!");
1161 Arg = NotArg->getArg(Num: 0);
1162 IsNeg = true;
1163 }
1164 if (!isa<DefInit>(Val: Arg) ||
1165 !cast<DefInit>(Val: Arg)->getDef()->isSubClassOf(Name: "SubtargetFeature"))
1166 PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Invalid AssemblerCondDag!");
1167
1168 IAP.addCond(C: std::string(formatv(
1169 Fmt: "AliasPatternCond::K_{}{}Feature, {}::{}", Vals: IsOr ? "Or" : "",
1170 Vals: IsNeg ? "Neg" : "", Vals&: Namespace, Vals: Arg->getAsString())));
1171 }
1172 // If an AssemblerPredicate with ors is used, note end of list should
1173 // these be combined.
1174 if (IsOr)
1175 IAP.addCond(C: "AliasPatternCond::K_EndOrFeatures, 0");
1176 }
1177
1178 IAPrinterMap[Aliases.first].push_back(x: std::move(IAP));
1179 }
1180 }
1181
1182 //////////////////////////////
1183 // Write out the printAliasInstr function
1184 //////////////////////////////
1185
1186 std::string Header;
1187 raw_string_ostream HeaderO(Header);
1188
1189 HeaderO << "bool " << Target.getName() << ClassName
1190 << "::printAliasInstr(const MCInst"
1191 << " *MI, uint64_t Address, "
1192 << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
1193 << "raw_ostream &OS) {\n";
1194
1195 std::string PatternsForOpcode;
1196 raw_string_ostream OpcodeO(PatternsForOpcode);
1197
1198 unsigned PatternCount = 0;
1199 std::string Patterns;
1200 raw_string_ostream PatternO(Patterns);
1201
1202 unsigned CondCount = 0;
1203 std::string Conds;
1204 raw_string_ostream CondO(Conds);
1205
1206 // All flattened alias strings.
1207 std::map<std::string, uint32_t> AsmStringOffsets;
1208 std::vector<std::pair<uint32_t, std::string>> AsmStrings;
1209 size_t AsmStringsSize = 0;
1210
1211 // Iterate over the opcodes in enum order so they are sorted by opcode for
1212 // binary search.
1213 for (const CodeGenInstruction *Inst : NumberedInstructions) {
1214 auto It = IAPrinterMap.find(x: getQualifiedName(R: Inst->TheDef));
1215 if (It == IAPrinterMap.end())
1216 continue;
1217 std::vector<IAPrinter> &IAPs = It->second;
1218 std::vector<IAPrinter *> UniqueIAPs;
1219
1220 // Remove any ambiguous alias rules.
1221 for (auto &LHS : IAPs) {
1222 bool IsDup = false;
1223 for (const auto &RHS : IAPs) {
1224 if (&LHS != &RHS && LHS == RHS) {
1225 IsDup = true;
1226 break;
1227 }
1228 }
1229
1230 if (!IsDup)
1231 UniqueIAPs.push_back(x: &LHS);
1232 }
1233
1234 if (UniqueIAPs.empty())
1235 continue;
1236
1237 unsigned PatternStart = PatternCount;
1238
1239 // Insert the pattern start and opcode in the pattern list for debugging.
1240 PatternO << formatv(Fmt: " // {} - {}\n", Vals: It->first, Vals&: PatternStart);
1241
1242 for (IAPrinter *IAP : UniqueIAPs) {
1243 // Start each condition list with a comment of the resulting pattern that
1244 // we're trying to match.
1245 unsigned CondStart = CondCount;
1246 CondO << formatv(Fmt: " // {} - {}\n", Vals: IAP->getResult(), Vals&: CondStart);
1247 for (const auto &Cond : IAP->getConds())
1248 CondO << " {" << Cond << "},\n";
1249 CondCount += IAP->getCondCount();
1250
1251 // After operands have been examined, re-encode the alias string with
1252 // escapes indicating how operands should be printed.
1253 uint32_t UnescapedSize = 0;
1254 std::string EncodedAsmString = IAP->formatAliasString(UnescapedSize);
1255 auto Insertion =
1256 AsmStringOffsets.try_emplace(k: EncodedAsmString, args&: AsmStringsSize);
1257 if (Insertion.second) {
1258 // If the string is new, add it to the vector.
1259 AsmStrings.emplace_back(args&: AsmStringsSize, args&: EncodedAsmString);
1260 AsmStringsSize += UnescapedSize + 1;
1261 }
1262 unsigned AsmStrOffset = Insertion.first->second;
1263
1264 PatternO << formatv(Fmt: " {{{}, {}, {}, {} },\n", Vals&: AsmStrOffset, Vals&: CondStart,
1265 Vals: IAP->getNumMIOps(), Vals: IAP->getCondCount());
1266 ++PatternCount;
1267 }
1268
1269 OpcodeO << formatv(Fmt: " {{{}, {}, {} },\n", Vals: It->first, Vals&: PatternStart,
1270 Vals: PatternCount - PatternStart);
1271 }
1272
1273 if (PatternsForOpcode.empty()) {
1274 O << Header;
1275 O << " return false;\n";
1276 O << "}\n\n";
1277 O << "#endif // PRINT_ALIAS_INSTR\n";
1278 return;
1279 }
1280
1281 // Forward declare the validation method if needed.
1282 if (!MCOpPredicates.empty())
1283 O << "static bool " << Target.getName() << ClassName
1284 << "ValidateMCOperand(const MCOperand &MCOp,\n"
1285 << " const MCSubtargetInfo &STI,\n"
1286 << " unsigned PredicateIndex);\n";
1287
1288 O << Header;
1289 O.indent(NumSpaces: 2) << "static const PatternsForOpcode OpToPatterns[] = {\n";
1290 O << PatternsForOpcode;
1291 O.indent(NumSpaces: 2) << "};\n\n";
1292 O.indent(NumSpaces: 2) << "static const AliasPattern Patterns[] = {\n";
1293 O << Patterns;
1294 O.indent(NumSpaces: 2) << "};\n\n";
1295 O.indent(NumSpaces: 2) << "static const AliasPatternCond Conds[] = {\n";
1296 O << Conds;
1297 O.indent(NumSpaces: 2) << "};\n\n";
1298 O.indent(NumSpaces: 2) << "static const char AsmStrings[] =\n";
1299 for (const auto &P : AsmStrings) {
1300 O.indent(NumSpaces: 4) << "/* " << P.first << " */ \"" << P.second << "\\0\"\n";
1301 }
1302
1303 O.indent(NumSpaces: 2) << ";\n\n";
1304
1305 // Assert that the opcode table is sorted. Use a static local constructor to
1306 // ensure that the check only happens once on first run.
1307 O << "#ifndef NDEBUG\n";
1308 O.indent(NumSpaces: 2) << "static struct SortCheck {\n";
1309 O.indent(NumSpaces: 2) << " SortCheck(ArrayRef<PatternsForOpcode> OpToPatterns) {\n";
1310 O.indent(NumSpaces: 2) << " assert(std::is_sorted(\n";
1311 O.indent(NumSpaces: 2) << " OpToPatterns.begin(), OpToPatterns.end(),\n";
1312 O.indent(NumSpaces: 2) << " [](const PatternsForOpcode &L, const "
1313 "PatternsForOpcode &R) {\n";
1314 O.indent(NumSpaces: 2) << " return L.Opcode < R.Opcode;\n";
1315 O.indent(NumSpaces: 2) << " }) &&\n";
1316 O.indent(NumSpaces: 2) << " \"tablegen failed to sort opcode patterns\");\n";
1317 O.indent(NumSpaces: 2) << " }\n";
1318 O.indent(NumSpaces: 2) << "} sortCheckVar(OpToPatterns);\n";
1319 O << "#endif\n\n";
1320
1321 O.indent(NumSpaces: 2) << "AliasMatchingData M {\n";
1322 O.indent(NumSpaces: 2) << " ArrayRef(OpToPatterns),\n";
1323 O.indent(NumSpaces: 2) << " ArrayRef(Patterns),\n";
1324 O.indent(NumSpaces: 2) << " ArrayRef(Conds),\n";
1325 O.indent(NumSpaces: 2) << " StringRef(AsmStrings, std::size(AsmStrings)),\n";
1326 if (MCOpPredicates.empty())
1327 O.indent(NumSpaces: 2) << " nullptr,\n";
1328 else
1329 O.indent(NumSpaces: 2) << " &" << Target.getName() << ClassName
1330 << "ValidateMCOperand,\n";
1331 O.indent(NumSpaces: 2) << "};\n";
1332
1333 O.indent(NumSpaces: 2) << "const char *AsmString = matchAliasPatterns(MI, "
1334 << (PassSubtarget ? "&STI" : "nullptr") << ", M);\n";
1335 O.indent(NumSpaces: 2) << "if (!AsmString) return false;\n\n";
1336
1337 // Code that prints the alias, replacing the operands with the ones from the
1338 // MCInst.
1339 O << " unsigned I = 0;\n";
1340 O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
1341 O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
1342 O << " ++I;\n";
1343 O << " OS << '\\t' << StringRef(AsmString, I);\n";
1344
1345 O << " if (AsmString[I] != '\\0') {\n";
1346 O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t') {\n";
1347 O << " OS << '\\t';\n";
1348 O << " ++I;\n";
1349 O << " }\n";
1350 O << " do {\n";
1351 O << " if (AsmString[I] == '$') {\n";
1352 O << " ++I;\n";
1353 O << " if (AsmString[I] == (char)0xff) {\n";
1354 O << " ++I;\n";
1355 O << " int OpIdx = AsmString[I++] - 1;\n";
1356 O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
1357 O << " printCustomAliasOperand(MI, Address, OpIdx, PrintMethodIdx, ";
1358 O << (PassSubtarget ? "STI, " : "");
1359 O << "OS);\n";
1360 O << " } else\n";
1361 O << " printOperand(MI, unsigned(AsmString[I++]) - 1, ";
1362 O << (PassSubtarget ? "STI, " : "");
1363 O << "OS);\n";
1364 O << " } else {\n";
1365 O << " OS << AsmString[I++];\n";
1366 O << " }\n";
1367 O << " } while (AsmString[I] != '\\0');\n";
1368 O << " }\n\n";
1369
1370 O << " return true;\n";
1371 O << "}\n\n";
1372
1373 //////////////////////////////
1374 // Write out the printCustomAliasOperand function
1375 //////////////////////////////
1376
1377 O << "void " << Target.getName() << ClassName << "::"
1378 << "printCustomAliasOperand(\n"
1379 << " const MCInst *MI, uint64_t Address, unsigned OpIdx,\n"
1380 << " unsigned PrintMethodIdx,\n"
1381 << (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
1382 << " raw_ostream &OS) {\n";
1383 if (PrintMethods.empty())
1384 O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n";
1385 else {
1386 O << " switch (PrintMethodIdx) {\n"
1387 << " default:\n"
1388 << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"
1389 << " break;\n";
1390
1391 for (unsigned i = 0; i < PrintMethods.size(); ++i) {
1392 O << " case " << i << ":\n"
1393 << " " << PrintMethods[i].first << "(MI, "
1394 << (PrintMethods[i].second ? "Address, " : "") << "OpIdx, "
1395 << (PassSubtarget ? "STI, " : "") << "OS);\n"
1396 << " break;\n";
1397 }
1398 O << " }\n";
1399 }
1400 O << "}\n\n";
1401
1402 if (!MCOpPredicates.empty()) {
1403 O << "static bool " << Target.getName() << ClassName
1404 << "ValidateMCOperand(const MCOperand &MCOp,\n"
1405 << " const MCSubtargetInfo &STI,\n"
1406 << " unsigned PredicateIndex) {\n"
1407 << " switch (PredicateIndex) {\n"
1408 << " default:\n"
1409 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
1410 << " break;\n";
1411
1412 for (auto [I, Rec] : enumerate(First&: MCOpPredicates)) {
1413 O << " case " << I + 1 << ": {\n";
1414 // We have to handle RegClassByHwMode predicates here since there is no
1415 // special case opcode for them.
1416 if (Rec->isSubClassOf(Name: "RegisterByHwMode")) {
1417 if (!PassSubtarget)
1418 PrintFatalError(ErrorLoc: Target.getAsmWriter()->getLoc(),
1419 Msg: "PassSubtarget must be set in "
1420 "AsmWriter to handle RegisterByHwMode");
1421 O << " return MCOp.isReg() && MCOp.getReg() == ";
1422 RegisterByHwMode(Rec, Target.getRegBank())
1423 .emitResolverCall(OS&: O,
1424 HwMode: "STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)");
1425 O << ";\n";
1426 } else {
1427 // Normal MCOperandPredicate code snippet, emit verbatim.
1428 O << Rec->getValueAsString(FieldName: "MCOperandPredicate") << "\n";
1429 }
1430 O << " }\n";
1431 }
1432 O << " }\n"
1433 << "}\n\n";
1434 }
1435
1436 O << "#endif // PRINT_ALIAS_INSTR\n";
1437}
1438
1439AsmWriterEmitter::AsmWriterEmitter(const RecordKeeper &R)
1440 : Records(R), Target(R) {
1441 const Record *AsmWriter = Target.getAsmWriter();
1442 unsigned Variant = AsmWriter->getValueAsInt(FieldName: "Variant");
1443
1444 // Get the instruction numbering.
1445 NumberedInstructions = Target.getInstructions();
1446
1447 for (const auto &[Idx, I] : enumerate(First&: NumberedInstructions)) {
1448 if (!I->AsmString.empty() && I->getName() != "PHI")
1449 Instructions.emplace_back(args: *I, args&: Idx, args&: Variant);
1450 }
1451}
1452
1453void AsmWriterEmitter::run(raw_ostream &O) {
1454 std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
1455 unsigned BitsLeft = 0;
1456 unsigned AsmStrBits = 0;
1457 emitSourceFileHeader(Desc: "Assembly Writer Source Fragment", OS&: O, Record: Records);
1458 EmitGetMnemonic(O, TableDrivenOperandPrinters, BitsLeft, AsmStrBits);
1459 EmitPrintInstruction(O, TableDrivenOperandPrinters, BitsLeft, AsmStrBits);
1460 EmitGetRegisterName(O);
1461 EmitPrintAliasInstruction(O);
1462}
1463
1464static TableGen::Emitter::OptClass<AsmWriterEmitter>
1465 X("gen-asm-writer", "Generate assembly writer");
1466