1
//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This tablegen backend is responsible for emitting a description of each
11
// instruction in a format that the enhanced disassembler can use to tokenize
12
// and parse instructions.
14
//===----------------------------------------------------------------------===//
16
#include "EDEmitter.h"
18
#include "AsmWriterInst.h"
19
#include "CodeGenTarget.h"
22
#include "llvm/Support/ErrorHandling.h"
23
#include "llvm/Support/Format.h"
24
#include "llvm/Support/raw_ostream.h"
29
#define MAX_OPERANDS 5
30
#define MAX_SYNTAXES 2
34
///////////////////////////////////////////////////////////
35
// Support classes for emitting nested C data structures //
36
///////////////////////////////////////////////////////////
43
std::vector<std::string> Entries;
45
EnumEmitter(const char *N) : Name(N) {
47
int addEntry(const char *e) {
48
Entries.push_back(std::string(e));
49
return Entries.size() - 1;
51
void emit(raw_ostream &o, unsigned int &i) {
52
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
55
unsigned int index = 0;
56
unsigned int numEntries = Entries.size();
57
for(index = 0; index < numEntries; ++index) {
58
o.indent(i) << Entries[index];
59
if(index < (numEntries - 1))
65
o.indent(i) << "};" << "\n";
68
void emitAsFlags(raw_ostream &o, unsigned int &i) {
69
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
72
unsigned int index = 0;
73
unsigned int numEntries = Entries.size();
74
unsigned int flag = 1;
75
for (index = 0; index < numEntries; ++index) {
76
o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
77
if (index < (numEntries - 1))
84
o.indent(i) << "};" << "\n";
91
std::vector<std::string> MemberTypes;
92
std::vector<std::string> MemberNames;
94
StructEmitter(const char *N) : Name(N) {
96
void addMember(const char *t, const char *n) {
97
MemberTypes.push_back(std::string(t));
98
MemberNames.push_back(std::string(n));
100
void emit(raw_ostream &o, unsigned int &i) {
101
o.indent(i) << "struct " << Name.c_str() << " {" << "\n";
104
unsigned int index = 0;
105
unsigned int numMembers = MemberTypes.size();
106
for (index = 0; index < numMembers; ++index) {
107
o.indent(i) << MemberTypes[index] << " " << MemberNames[index] << ";";
112
o.indent(i) << "};" << "\n";
116
class ConstantEmitter {
118
virtual ~ConstantEmitter() { }
119
virtual void emit(raw_ostream &o, unsigned int &i) = 0;
122
class LiteralConstantEmitter : public ConstantEmitter {
126
LiteralConstantEmitter(const char *literal) : Literal(literal) {
128
LiteralConstantEmitter(int literal) {
130
snprintf(buf, 256, "%d", literal);
133
void emit(raw_ostream &o, unsigned int &i) {
138
class CompoundConstantEmitter : public ConstantEmitter {
140
std::vector<ConstantEmitter*> Entries;
142
CompoundConstantEmitter() {
144
~CompoundConstantEmitter() {
146
unsigned int numEntries = Entries.size();
147
for (index = 0; index < numEntries; ++index) {
148
delete Entries[index];
151
CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
152
Entries.push_back(e);
155
void emit(raw_ostream &o, unsigned int &i) {
160
unsigned int numEntries = Entries.size();
161
for (index = 0; index < numEntries; ++index) {
163
Entries[index]->emit(o, i);
164
if (index < (numEntries - 1))
174
class FlagsConstantEmitter : public ConstantEmitter {
176
std::vector<std::string> Flags;
178
FlagsConstantEmitter() {
180
FlagsConstantEmitter &addEntry(const char *f) {
181
Flags.push_back(std::string(f));
184
void emit(raw_ostream &o, unsigned int &i) {
186
unsigned int numFlags = Flags.size();
190
for (index = 0; index < numFlags; ++index) {
191
o << Flags[index].c_str();
192
if (index < (numFlags - 1))
199
EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
202
/// populateOperandOrder - Accepts a CodeGenInstruction and generates its
203
/// AsmWriterInst for the desired assembly syntax, giving an ordered list of
204
/// operands in the order they appear in the printed instruction. Then, for
205
/// each entry in that list, determines the index of the same operand in the
206
/// CodeGenInstruction, and emits the resulting mapping into an array, filling
207
/// in unused slots with -1.
209
/// @arg operandOrder - The array that will be populated with the operand
210
/// mapping. Each entry will contain -1 (invalid index
211
/// into the operands present in the AsmString) or a number
212
/// representing an index in the operand descriptor array.
213
/// @arg inst - The instruction to use when looking up the operands
214
/// @arg syntax - The syntax to use, according to LLVM's enumeration
215
void populateOperandOrder(CompoundConstantEmitter *operandOrder,
216
const CodeGenInstruction &inst,
218
unsigned int numArgs = 0;
220
AsmWriterInst awInst(inst, syntax, -1, -1);
222
std::vector<AsmWriterOperand>::iterator operandIterator;
224
for (operandIterator = awInst.Operands.begin();
225
operandIterator != awInst.Operands.end();
227
if (operandIterator->OperandType ==
228
AsmWriterOperand::isMachineInstrOperand) {
230
snprintf(buf, sizeof(buf), "%u", operandIterator->CGIOpNo);
231
operandOrder->addEntry(new LiteralConstantEmitter(buf));
236
for(; numArgs < MAX_OPERANDS; numArgs++) {
237
operandOrder->addEntry(new LiteralConstantEmitter("-1"));
241
/////////////////////////////////////////////////////
242
// Support functions for handling X86 instructions //
243
/////////////////////////////////////////////////////
245
#define ADDFLAG(flag) flags->addEntry(flag)
247
#define REG(str) if (name == str) { ADDFLAG("kOperandFlagRegister"); return 0; }
248
#define MEM(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); return 0; }
249
#define LEA(str) if (name == str) { ADDFLAG("kOperandFlagEffectiveAddress"); \
251
#define IMM(str) if (name == str) { ADDFLAG("kOperandFlagImmediate"); \
253
#define PCR(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); \
254
ADDFLAG("kOperandFlagPCRelative"); \
257
/// X86FlagFromOpName - Processes the name of a single X86 operand (which is
258
/// actually its type) and translates it into an operand flag
260
/// @arg flags - The flags object to add the flag to
261
/// @arg name - The name of the operand
262
static int X86FlagFromOpName(FlagsConstantEmitter *flags,
263
const std::string &name) {
280
REG("CONTROL_REG_32");
281
REG("CONTROL_REG_64");
313
IMM("i64i32imm_pcrel");
333
/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding
334
/// the appropriate flags to their descriptors
336
/// @operandFlags - A reference the array of operand flag objects
337
/// @inst - The instruction to use as a source of information
338
static void X86PopulateOperands(
339
FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
340
const CodeGenInstruction &inst) {
341
if (!inst.TheDef->isSubClassOf("X86Inst"))
345
unsigned int numOperands = inst.OperandList.size();
347
for (index = 0; index < numOperands; ++index) {
348
const CodeGenInstruction::OperandInfo &operandInfo =
349
inst.OperandList[index];
350
Record &rec = *operandInfo.Rec;
352
if (X86FlagFromOpName(operandFlags[index], rec.getName())) {
353
errs() << "Operand type: " << rec.getName().c_str() << "\n";
354
errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
355
errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
356
llvm_unreachable("Unhandled type");
361
/// decorate1 - Decorates a named operand with a new flag
363
/// @operandFlags - The array of operand flag objects, which don't have names
364
/// @inst - The CodeGenInstruction, which provides a way to translate
365
/// between names and operand indices
366
/// @opName - The name of the operand
367
/// @flag - The name of the flag to add
368
static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
369
const CodeGenInstruction &inst,
371
const char *opFlag) {
374
opIndex = inst.getOperandNamed(std::string(opName));
376
operandFlags[opIndex]->addEntry(opFlag);
379
#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag)
381
#define MOV(source, target) { \
382
instFlags.addEntry("kInstructionFlagMove"); \
383
DECORATE1(source, "kOperandFlagSource"); \
384
DECORATE1(target, "kOperandFlagTarget"); \
387
#define BRANCH(target) { \
388
instFlags.addEntry("kInstructionFlagBranch"); \
389
DECORATE1(target, "kOperandFlagTarget"); \
392
#define PUSH(source) { \
393
instFlags.addEntry("kInstructionFlagPush"); \
394
DECORATE1(source, "kOperandFlagSource"); \
397
#define POP(target) { \
398
instFlags.addEntry("kInstructionFlagPop"); \
399
DECORATE1(target, "kOperandFlagTarget"); \
402
#define CALL(target) { \
403
instFlags.addEntry("kInstructionFlagCall"); \
404
DECORATE1(target, "kOperandFlagTarget"); \
408
instFlags.addEntry("kInstructionFlagReturn"); \
411
/// X86ExtractSemantics - Performs various checks on the name of an X86
412
/// instruction to determine what sort of an instruction it is and then adds
413
/// the appropriate flags to the instruction and its operands
415
/// @arg instFlags - A reference to the flags for the instruction as a whole
416
/// @arg operandFlags - A reference to the array of operand flag object pointers
417
/// @arg inst - A reference to the original instruction
418
static void X86ExtractSemantics(FlagsConstantEmitter &instFlags,
419
FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
420
const CodeGenInstruction &inst) {
421
const std::string &name = inst.TheDef->getName();
423
if (name.find("MOV") != name.npos) {
424
if (name.find("MOV_V") != name.npos) {
425
// ignore (this is a pseudoinstruction)
427
else if (name.find("MASK") != name.npos) {
428
// ignore (this is a masking move)
430
else if (name.find("r0") != name.npos) {
431
// ignore (this is a pseudoinstruction)
433
else if (name.find("PS") != name.npos ||
434
name.find("PD") != name.npos) {
435
// ignore (this is a shuffling move)
437
else if (name.find("MOVS") != name.npos) {
438
// ignore (this is a string move)
440
else if (name.find("_F") != name.npos) {
441
// TODO handle _F moves to ST(0)
443
else if (name.find("a") != name.npos) {
444
// TODO handle moves to/from %ax
446
else if (name.find("CMOV") != name.npos) {
449
else if (name.find("PC") != name.npos) {
457
if (name.find("JMP") != name.npos ||
458
name.find("J") == 0) {
459
if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
467
if (name.find("PUSH") != name.npos) {
468
if (name.find("FS") != name.npos ||
469
name.find("GS") != name.npos) {
470
instFlags.addEntry("kInstructionFlagPush");
471
// TODO add support for fixed operands
473
else if (name.find("F") != name.npos) {
474
// ignore (this pushes onto the FP stack)
476
else if (name[name.length() - 1] == 'm') {
479
else if (name.find("i") != name.npos) {
487
if (name.find("POP") != name.npos) {
488
if (name.find("POPCNT") != name.npos) {
489
// ignore (not a real pop)
491
else if (name.find("FS") != name.npos ||
492
name.find("GS") != name.npos) {
493
instFlags.addEntry("kInstructionFlagPop");
494
// TODO add support for fixed operands
496
else if (name.find("F") != name.npos) {
497
// ignore (this pops from the FP stack)
499
else if (name[name.length() - 1] == 'm') {
507
if (name.find("CALL") != name.npos) {
508
if (name.find("ADJ") != name.npos) {
509
// ignore (not a call)
511
else if (name.find("SYSCALL") != name.npos) {
512
// ignore (doesn't go anywhere we know about)
514
else if (name.find("VMCALL") != name.npos) {
515
// ignore (rather different semantics than a regular call)
517
else if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
525
if (name.find("RET") != name.npos) {
537
#undef COND_DECORATE_2
538
#undef COND_DECORATE_1
541
/// populateInstInfo - Fills an array of InstInfos with information about each
542
/// instruction in a target
544
/// @arg infoArray - The array of InstInfo objects to populate
545
/// @arg target - The CodeGenTarget to use as a source of instructions
546
static void populateInstInfo(CompoundConstantEmitter &infoArray,
547
CodeGenTarget &target) {
548
std::vector<const CodeGenInstruction*> numberedInstructions;
549
target.getInstructionsByEnumValue(numberedInstructions);
552
unsigned int numInstructions = numberedInstructions.size();
554
for (index = 0; index < numInstructions; ++index) {
555
const CodeGenInstruction& inst = *numberedInstructions[index];
557
CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
558
infoArray.addEntry(infoStruct);
560
FlagsConstantEmitter *instFlags = new FlagsConstantEmitter;
561
infoStruct->addEntry(instFlags);
563
LiteralConstantEmitter *numOperandsEmitter =
564
new LiteralConstantEmitter(inst.OperandList.size());
565
infoStruct->addEntry(numOperandsEmitter);
567
CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
568
infoStruct->addEntry(operandFlagArray);
570
FlagsConstantEmitter *operandFlags[MAX_OPERANDS];
572
for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) {
573
operandFlags[operandIndex] = new FlagsConstantEmitter;
574
operandFlagArray->addEntry(operandFlags[operandIndex]);
577
unsigned numSyntaxes = 0;
579
if (target.getName() == "X86") {
580
X86PopulateOperands(operandFlags, inst);
581
X86ExtractSemantics(*instFlags, operandFlags, inst);
585
CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
586
infoStruct->addEntry(operandOrderArray);
588
for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) {
589
CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter;
590
operandOrderArray->addEntry(operandOrder);
592
if (syntaxIndex < numSyntaxes) {
593
populateOperandOrder(operandOrder, inst, syntaxIndex);
596
for (unsigned operandIndex = 0;
597
operandIndex < MAX_OPERANDS;
599
operandOrder->addEntry(new LiteralConstantEmitter("-1"));
606
void EDEmitter::run(raw_ostream &o) {
609
CompoundConstantEmitter infoArray;
610
CodeGenTarget target;
612
populateInstInfo(infoArray, target);
614
o << "InstInfo instInfo" << target.getName().c_str() << "[] = ";
615
infoArray.emit(o, i);
619
void EDEmitter::runHeader(raw_ostream &o) {
620
EmitSourceFileHeader("Enhanced Disassembly Info Header", o);
622
o << "#ifndef EDInfo_" << "\n";
623
o << "#define EDInfo_" << "\n";
625
o << "#include <inttypes.h>" << "\n";
627
o << "#define MAX_OPERANDS " << format("%d", MAX_OPERANDS) << "\n";
628
o << "#define MAX_SYNTAXES " << format("%d", MAX_SYNTAXES) << "\n";
633
EnumEmitter operandFlags("OperandFlags");
634
operandFlags.addEntry("kOperandFlagImmediate");
635
operandFlags.addEntry("kOperandFlagRegister");
636
operandFlags.addEntry("kOperandFlagMemory");
637
operandFlags.addEntry("kOperandFlagEffectiveAddress");
638
operandFlags.addEntry("kOperandFlagPCRelative");
639
operandFlags.addEntry("kOperandFlagSource");
640
operandFlags.addEntry("kOperandFlagTarget");
641
operandFlags.emitAsFlags(o, i);
645
EnumEmitter instructionFlags("InstructionFlags");
646
instructionFlags.addEntry("kInstructionFlagMove");
647
instructionFlags.addEntry("kInstructionFlagBranch");
648
instructionFlags.addEntry("kInstructionFlagPush");
649
instructionFlags.addEntry("kInstructionFlagPop");
650
instructionFlags.addEntry("kInstructionFlagCall");
651
instructionFlags.addEntry("kInstructionFlagReturn");
652
instructionFlags.emitAsFlags(o, i);
656
StructEmitter instInfo("InstInfo");
657
instInfo.addMember("uint32_t", "instructionFlags");
658
instInfo.addMember("uint8_t", "numOperands");
659
instInfo.addMember("uint8_t", "operandFlags[MAX_OPERANDS]");
660
instInfo.addMember("const char", "operandOrders[MAX_SYNTAXES][MAX_OPERANDS]");
664
o << "#endif" << "\n";