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