Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/CodeEmitterGen.cpp
35258 views
1
//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
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
// CodeEmitterGen uses the descriptions of instructions and their fields to
10
// construct an automated code emitter: a function called
11
// getBinaryCodeForInstr() that, given a MCInst, returns the value of the
12
// instruction - either as an uint64_t or as an APInt, depending on the
13
// maximum bit width of all Inst definitions.
14
//
15
// In addition, it generates another function called getOperandBitOffset()
16
// that, given a MCInst and an operand index, returns the minimum of indices of
17
// all bits that carry some portion of the respective operand. When the target's
18
// encodeInstruction() stores the instruction in a little-endian byte order, the
19
// returned value is the offset of the start of the operand in the encoded
20
// instruction. Other targets might need to adjust the returned value according
21
// to their encodeInstruction() implementation.
22
//
23
//===----------------------------------------------------------------------===//
24
25
#include "Common/CodeGenHwModes.h"
26
#include "Common/CodeGenInstruction.h"
27
#include "Common/CodeGenTarget.h"
28
#include "Common/InfoByHwMode.h"
29
#include "Common/VarLenCodeEmitterGen.h"
30
#include "llvm/ADT/APInt.h"
31
#include "llvm/ADT/ArrayRef.h"
32
#include "llvm/ADT/StringExtras.h"
33
#include "llvm/Support/Casting.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 <cstdint>
39
#include <map>
40
#include <set>
41
#include <string>
42
#include <utility>
43
#include <vector>
44
45
using namespace llvm;
46
47
namespace {
48
49
class CodeEmitterGen {
50
RecordKeeper &Records;
51
52
public:
53
CodeEmitterGen(RecordKeeper &R) : Records(R) {}
54
55
void run(raw_ostream &o);
56
57
private:
58
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
59
std::pair<std::string, std::string>
60
getInstructionCases(Record *R, CodeGenTarget &Target);
61
void addInstructionCasesForEncoding(Record *R, Record *EncodingDef,
62
CodeGenTarget &Target, std::string &Case,
63
std::string &BitOffsetCase);
64
bool addCodeToMergeInOperand(Record *R, BitsInit *BI,
65
const std::string &VarName, std::string &Case,
66
std::string &BitOffsetCase,
67
CodeGenTarget &Target);
68
69
void emitInstructionBaseValues(
70
raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
71
CodeGenTarget &Target, unsigned HwMode = DefaultMode);
72
void
73
emitCaseMap(raw_ostream &o,
74
const std::map<std::string, std::vector<std::string>> &CaseMap);
75
unsigned BitWidth = 0u;
76
bool UseAPInt = false;
77
};
78
79
// If the VarBitInit at position 'bit' matches the specified variable then
80
// return the variable bit position. Otherwise return -1.
81
int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI,
82
int bit) {
83
if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
84
if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
85
if (VI->getName() == VarName)
86
return VBI->getBitNum();
87
} else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
88
if (VI->getName() == VarName)
89
return 0;
90
}
91
92
return -1;
93
}
94
95
// Returns true if it succeeds, false if an error.
96
bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI,
97
const std::string &VarName,
98
std::string &Case,
99
std::string &BitOffsetCase,
100
CodeGenTarget &Target) {
101
CodeGenInstruction &CGI = Target.getInstruction(R);
102
103
// Determine if VarName actually contributes to the Inst encoding.
104
int bit = BI->getNumBits() - 1;
105
106
// Scan for a bit that this contributed to.
107
for (; bit >= 0;) {
108
if (getVariableBit(VarName, BI, bit) != -1)
109
break;
110
111
--bit;
112
}
113
114
// If we found no bits, ignore this value, otherwise emit the call to get the
115
// operand encoding.
116
if (bit < 0)
117
return true;
118
119
// If the operand matches by name, reference according to that
120
// operand number. Non-matching operands are assumed to be in
121
// order.
122
unsigned OpIdx;
123
std::pair<unsigned, unsigned> SubOp;
124
if (CGI.Operands.hasSubOperandAlias(VarName, SubOp)) {
125
OpIdx = CGI.Operands[SubOp.first].MIOperandNo + SubOp.second;
126
} else if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
127
// Get the machine operand number for the indicated operand.
128
OpIdx = CGI.Operands[OpIdx].MIOperandNo;
129
} else {
130
PrintError(R, Twine("No operand named ") + VarName + " in record " +
131
R->getName());
132
return false;
133
}
134
135
if (CGI.Operands.isFlatOperandNotEmitted(OpIdx)) {
136
PrintError(R,
137
"Operand " + VarName + " used but also marked as not emitted!");
138
return false;
139
}
140
141
std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
142
std::string &EncoderMethodName =
143
CGI.Operands[SO.first].EncoderMethodNames[SO.second];
144
145
if (UseAPInt)
146
Case += " op.clearAllBits();\n";
147
148
Case += " // op: " + VarName + "\n";
149
150
// If the source operand has a custom encoder, use it.
151
if (!EncoderMethodName.empty()) {
152
if (UseAPInt) {
153
Case += " " + EncoderMethodName + "(MI, " + utostr(OpIdx);
154
Case += ", op";
155
} else {
156
Case += " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
157
}
158
Case += ", Fixups, STI);\n";
159
} else {
160
if (UseAPInt) {
161
Case +=
162
" getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
163
Case += ", op, Fixups, STI";
164
} else {
165
Case += " op = getMachineOpValue(MI, MI.getOperand(" +
166
utostr(OpIdx) + ")";
167
Case += ", Fixups, STI";
168
}
169
Case += ");\n";
170
}
171
172
// Precalculate the number of lits this variable contributes to in the
173
// operand. If there is a single lit (consecutive range of bits) we can use a
174
// destructive sequence on APInt that reduces memory allocations.
175
int numOperandLits = 0;
176
for (int tmpBit = bit; tmpBit >= 0;) {
177
int varBit = getVariableBit(VarName, BI, tmpBit);
178
179
// If this bit isn't from a variable, skip it.
180
if (varBit == -1) {
181
--tmpBit;
182
continue;
183
}
184
185
// Figure out the consecutive range of bits covered by this operand, in
186
// order to generate better encoding code.
187
int beginVarBit = varBit;
188
int N = 1;
189
for (--tmpBit; tmpBit >= 0;) {
190
varBit = getVariableBit(VarName, BI, tmpBit);
191
if (varBit == -1 || varBit != (beginVarBit - N))
192
break;
193
++N;
194
--tmpBit;
195
}
196
++numOperandLits;
197
}
198
199
unsigned BitOffset = -1;
200
for (; bit >= 0;) {
201
int varBit = getVariableBit(VarName, BI, bit);
202
203
// If this bit isn't from a variable, skip it.
204
if (varBit == -1) {
205
--bit;
206
continue;
207
}
208
209
// Figure out the consecutive range of bits covered by this operand, in
210
// order to generate better encoding code.
211
int beginInstBit = bit;
212
int beginVarBit = varBit;
213
int N = 1;
214
for (--bit; bit >= 0;) {
215
varBit = getVariableBit(VarName, BI, bit);
216
if (varBit == -1 || varBit != (beginVarBit - N))
217
break;
218
++N;
219
--bit;
220
}
221
222
std::string maskStr;
223
int opShift;
224
225
unsigned loBit = beginVarBit - N + 1;
226
unsigned hiBit = loBit + N;
227
unsigned loInstBit = beginInstBit - N + 1;
228
BitOffset = loInstBit;
229
if (UseAPInt) {
230
std::string extractStr;
231
if (N >= 64) {
232
extractStr = "op.extractBits(" + itostr(hiBit - loBit) + ", " +
233
itostr(loBit) + ")";
234
Case += " Value.insertBits(" + extractStr + ", " +
235
itostr(loInstBit) + ");\n";
236
} else {
237
extractStr = "op.extractBitsAsZExtValue(" + itostr(hiBit - loBit) +
238
", " + itostr(loBit) + ")";
239
Case += " Value.insertBits(" + extractStr + ", " +
240
itostr(loInstBit) + ", " + itostr(hiBit - loBit) + ");\n";
241
}
242
} else {
243
uint64_t opMask = ~(uint64_t)0 >> (64 - N);
244
opShift = beginVarBit - N + 1;
245
opMask <<= opShift;
246
maskStr = "UINT64_C(" + utostr(opMask) + ")";
247
opShift = beginInstBit - beginVarBit;
248
249
if (numOperandLits == 1) {
250
Case += " op &= " + maskStr + ";\n";
251
if (opShift > 0) {
252
Case += " op <<= " + itostr(opShift) + ";\n";
253
} else if (opShift < 0) {
254
Case += " op >>= " + itostr(-opShift) + ";\n";
255
}
256
Case += " Value |= op;\n";
257
} else {
258
if (opShift > 0) {
259
Case += " Value |= (op & " + maskStr + ") << " +
260
itostr(opShift) + ";\n";
261
} else if (opShift < 0) {
262
Case += " Value |= (op & " + maskStr + ") >> " +
263
itostr(-opShift) + ";\n";
264
} else {
265
Case += " Value |= (op & " + maskStr + ");\n";
266
}
267
}
268
}
269
}
270
271
if (BitOffset != (unsigned)-1) {
272
BitOffsetCase += " case " + utostr(OpIdx) + ":\n";
273
BitOffsetCase += " // op: " + VarName + "\n";
274
BitOffsetCase += " return " + utostr(BitOffset) + ";\n";
275
}
276
277
return true;
278
}
279
280
std::pair<std::string, std::string>
281
CodeEmitterGen::getInstructionCases(Record *R, CodeGenTarget &Target) {
282
std::string Case, BitOffsetCase;
283
284
auto append = [&](const std::string &S) {
285
Case += S;
286
BitOffsetCase += S;
287
};
288
289
if (const RecordVal *RV = R->getValue("EncodingInfos")) {
290
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
291
const CodeGenHwModes &HWM = Target.getHwModes();
292
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
293
294
// Invoke the interface to obtain the HwMode ID controlling the
295
// EncodingInfo for the current subtarget. This interface will
296
// mask off irrelevant HwMode IDs.
297
append(" unsigned HwMode = "
298
"STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);\n");
299
Case += " switch (HwMode) {\n";
300
Case += " default: llvm_unreachable(\"Unknown hardware mode!\"); "
301
"break;\n";
302
for (auto &[ModeId, Encoding] : EBM) {
303
if (ModeId == DefaultMode) {
304
Case +=
305
" case " + itostr(DefaultMode) + ": InstBitsByHw = InstBits";
306
} else {
307
Case += " case " + itostr(ModeId) +
308
": InstBitsByHw = InstBits_" +
309
std::string(HWM.getMode(ModeId).Name);
310
}
311
Case += "; break;\n";
312
}
313
Case += " };\n";
314
315
// We need to remodify the 'Inst' value from the table we found above.
316
if (UseAPInt) {
317
int NumWords = APInt::getNumWords(BitWidth);
318
Case += " Inst = APInt(" + itostr(BitWidth);
319
Case += ", ArrayRef(InstBitsByHw + opcode * " + itostr(NumWords) +
320
", " + itostr(NumWords);
321
Case += "));\n";
322
Case += " Value = Inst;\n";
323
} else {
324
Case += " Value = InstBitsByHw[opcode];\n";
325
}
326
327
append(" switch (HwMode) {\n");
328
append(" default: llvm_unreachable(\"Unhandled HwMode\");\n");
329
for (auto &[ModeId, Encoding] : EBM) {
330
append(" case " + itostr(ModeId) + ": {\n");
331
addInstructionCasesForEncoding(R, Encoding, Target, Case,
332
BitOffsetCase);
333
append(" break;\n");
334
append(" }\n");
335
}
336
append(" }\n");
337
return std::pair(std::move(Case), std::move(BitOffsetCase));
338
}
339
}
340
addInstructionCasesForEncoding(R, R, Target, Case, BitOffsetCase);
341
return std::pair(std::move(Case), std::move(BitOffsetCase));
342
}
343
344
void CodeEmitterGen::addInstructionCasesForEncoding(
345
Record *R, Record *EncodingDef, CodeGenTarget &Target, std::string &Case,
346
std::string &BitOffsetCase) {
347
BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
348
349
// Loop over all of the fields in the instruction, determining which are the
350
// operands to the instruction.
351
bool Success = true;
352
size_t OrigBitOffsetCaseSize = BitOffsetCase.size();
353
BitOffsetCase += " switch (OpNum) {\n";
354
size_t BitOffsetCaseSizeBeforeLoop = BitOffsetCase.size();
355
for (const RecordVal &RV : EncodingDef->getValues()) {
356
// Ignore fixed fields in the record, we're looking for values like:
357
// bits<5> RST = { ?, ?, ?, ?, ? };
358
if (RV.isNonconcreteOK() || RV.getValue()->isComplete())
359
continue;
360
361
Success &= addCodeToMergeInOperand(R, BI, std::string(RV.getName()), Case,
362
BitOffsetCase, Target);
363
}
364
// Avoid empty switches.
365
if (BitOffsetCase.size() == BitOffsetCaseSizeBeforeLoop)
366
BitOffsetCase.resize(OrigBitOffsetCaseSize);
367
else
368
BitOffsetCase += " }\n";
369
370
if (!Success) {
371
// Dump the record, so we can see what's going on...
372
std::string E;
373
raw_string_ostream S(E);
374
S << "Dumping record for previous error:\n";
375
S << *R;
376
PrintNote(E);
377
}
378
379
StringRef PostEmitter = R->getValueAsString("PostEncoderMethod");
380
if (!PostEmitter.empty()) {
381
Case += " Value = ";
382
Case += PostEmitter;
383
Case += "(MI, Value";
384
Case += ", STI";
385
Case += ");\n";
386
}
387
}
388
389
static void emitInstBits(raw_ostream &OS, const APInt &Bits) {
390
for (unsigned I = 0; I < Bits.getNumWords(); ++I)
391
OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I])
392
<< ")";
393
}
394
395
void CodeEmitterGen::emitInstructionBaseValues(
396
raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions,
397
CodeGenTarget &Target, unsigned HwMode) {
398
const CodeGenHwModes &HWM = Target.getHwModes();
399
if (HwMode == DefaultMode)
400
o << " static const uint64_t InstBits[] = {\n";
401
else
402
o << " static const uint64_t InstBits_"
403
<< HWM.getModeName(HwMode, /*IncludeDefault=*/true) << "[] = {\n";
404
405
for (const CodeGenInstruction *CGI : NumberedInstructions) {
406
Record *R = CGI->TheDef;
407
408
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
409
R->getValueAsBit("isPseudo")) {
410
o << " ";
411
emitInstBits(o, APInt(BitWidth, 0));
412
o << ",\n";
413
continue;
414
}
415
416
Record *EncodingDef = R;
417
if (const RecordVal *RV = R->getValue("EncodingInfos")) {
418
if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
419
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
420
if (EBM.hasMode(HwMode)) {
421
EncodingDef = EBM.get(HwMode);
422
} else {
423
// If the HwMode does not match, then Encoding '0'
424
// should be generated.
425
APInt Value(BitWidth, 0);
426
o << " ";
427
emitInstBits(o, Value);
428
o << "," << '\t' << "// " << R->getName() << "\n";
429
continue;
430
}
431
}
432
}
433
BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst");
434
435
// Start by filling in fixed values.
436
APInt Value(BitWidth, 0);
437
for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
438
if (auto *B = dyn_cast<BitInit>(BI->getBit(i)); B && B->getValue())
439
Value.setBit(i);
440
}
441
o << " ";
442
emitInstBits(o, Value);
443
o << "," << '\t' << "// " << R->getName() << "\n";
444
}
445
o << " UINT64_C(0)\n };\n";
446
}
447
448
void CodeEmitterGen::emitCaseMap(
449
raw_ostream &o,
450
const std::map<std::string, std::vector<std::string>> &CaseMap) {
451
std::map<std::string, std::vector<std::string>>::const_iterator IE, EE;
452
for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
453
const std::string &Case = IE->first;
454
const std::vector<std::string> &InstList = IE->second;
455
456
for (int i = 0, N = InstList.size(); i < N; i++) {
457
if (i)
458
o << "\n";
459
o << " case " << InstList[i] << ":";
460
}
461
o << " {\n";
462
o << Case;
463
o << " break;\n"
464
<< " }\n";
465
}
466
}
467
468
void CodeEmitterGen::run(raw_ostream &o) {
469
emitSourceFileHeader("Machine Code Emitter", o);
470
471
CodeGenTarget Target(Records);
472
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
473
474
// For little-endian instruction bit encodings, reverse the bit order
475
Target.reverseBitsForLittleEndianEncoding();
476
477
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
478
Target.getInstructionsByEnumValue();
479
480
if (Target.hasVariableLengthEncodings()) {
481
emitVarLenCodeEmitter(Records, o);
482
} else {
483
const CodeGenHwModes &HWM = Target.getHwModes();
484
// The set of HwModes used by instruction encodings.
485
std::set<unsigned> HwModes;
486
BitWidth = 0;
487
for (const CodeGenInstruction *CGI : NumberedInstructions) {
488
Record *R = CGI->TheDef;
489
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
490
R->getValueAsBit("isPseudo"))
491
continue;
492
493
if (const RecordVal *RV = R->getValue("EncodingInfos")) {
494
if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) {
495
EncodingInfoByHwMode EBM(DI->getDef(), HWM);
496
for (auto &KV : EBM) {
497
BitsInit *BI = KV.second->getValueAsBitsInit("Inst");
498
BitWidth = std::max(BitWidth, BI->getNumBits());
499
HwModes.insert(KV.first);
500
}
501
continue;
502
}
503
}
504
BitsInit *BI = R->getValueAsBitsInit("Inst");
505
BitWidth = std::max(BitWidth, BI->getNumBits());
506
}
507
UseAPInt = BitWidth > 64;
508
509
// Emit function declaration
510
if (UseAPInt) {
511
o << "void " << Target.getName()
512
<< "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
513
<< " SmallVectorImpl<MCFixup> &Fixups,\n"
514
<< " APInt &Inst,\n"
515
<< " APInt &Scratch,\n"
516
<< " const MCSubtargetInfo &STI) const {\n";
517
} else {
518
o << "uint64_t " << Target.getName();
519
o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
520
<< " SmallVectorImpl<MCFixup> &Fixups,\n"
521
<< " const MCSubtargetInfo &STI) const {\n";
522
}
523
524
// Emit instruction base values
525
emitInstructionBaseValues(o, NumberedInstructions, Target, DefaultMode);
526
if (!HwModes.empty()) {
527
// Emit table for instrs whose encodings are controlled by HwModes.
528
for (unsigned HwMode : HwModes) {
529
if (HwMode == DefaultMode)
530
continue;
531
emitInstructionBaseValues(o, NumberedInstructions, Target, HwMode);
532
}
533
534
// This pointer will be assigned to the HwMode table later.
535
o << " const uint64_t *InstBitsByHw;\n";
536
}
537
538
// Map to accumulate all the cases.
539
std::map<std::string, std::vector<std::string>> CaseMap;
540
std::map<std::string, std::vector<std::string>> BitOffsetCaseMap;
541
542
// Construct all cases statement for each opcode
543
for (Record *R : Insts) {
544
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
545
R->getValueAsBit("isPseudo"))
546
continue;
547
std::string InstName =
548
(R->getValueAsString("Namespace") + "::" + R->getName()).str();
549
std::string Case, BitOffsetCase;
550
std::tie(Case, BitOffsetCase) = getInstructionCases(R, Target);
551
552
CaseMap[Case].push_back(InstName);
553
BitOffsetCaseMap[BitOffsetCase].push_back(std::move(InstName));
554
}
555
556
// Emit initial function code
557
if (UseAPInt) {
558
int NumWords = APInt::getNumWords(BitWidth);
559
o << " const unsigned opcode = MI.getOpcode();\n"
560
<< " if (Scratch.getBitWidth() != " << BitWidth << ")\n"
561
<< " Scratch = Scratch.zext(" << BitWidth << ");\n"
562
<< " Inst = APInt(" << BitWidth << ", ArrayRef(InstBits + opcode * "
563
<< NumWords << ", " << NumWords << "));\n"
564
<< " APInt &Value = Inst;\n"
565
<< " APInt &op = Scratch;\n"
566
<< " switch (opcode) {\n";
567
} else {
568
o << " const unsigned opcode = MI.getOpcode();\n"
569
<< " uint64_t Value = InstBits[opcode];\n"
570
<< " uint64_t op = 0;\n"
571
<< " (void)op; // suppress warning\n"
572
<< " switch (opcode) {\n";
573
}
574
575
// Emit each case statement
576
emitCaseMap(o, CaseMap);
577
578
// Default case: unhandled opcode
579
o << " default:\n"
580
<< " std::string msg;\n"
581
<< " raw_string_ostream Msg(msg);\n"
582
<< " Msg << \"Not supported instr: \" << MI;\n"
583
<< " report_fatal_error(Msg.str().c_str());\n"
584
<< " }\n";
585
if (UseAPInt)
586
o << " Inst = Value;\n";
587
else
588
o << " return Value;\n";
589
o << "}\n\n";
590
591
o << "#ifdef GET_OPERAND_BIT_OFFSET\n"
592
<< "#undef GET_OPERAND_BIT_OFFSET\n\n"
593
<< "uint32_t " << Target.getName()
594
<< "MCCodeEmitter::getOperandBitOffset(const MCInst &MI,\n"
595
<< " unsigned OpNum,\n"
596
<< " const MCSubtargetInfo &STI) const {\n"
597
<< " switch (MI.getOpcode()) {\n";
598
emitCaseMap(o, BitOffsetCaseMap);
599
o << " }\n"
600
<< " std::string msg;\n"
601
<< " raw_string_ostream Msg(msg);\n"
602
<< " Msg << \"Not supported instr[opcode]: \" << MI << \"[\" << OpNum "
603
"<< \"]\";\n"
604
<< " report_fatal_error(Msg.str().c_str());\n"
605
<< "}\n\n"
606
<< "#endif // GET_OPERAND_BIT_OFFSET\n\n";
607
}
608
}
609
610
} // end anonymous namespace
611
612
static TableGen::Emitter::OptClass<CodeEmitterGen>
613
X("gen-emitter", "Generate machine code emitter");
614
615