//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of each
// instruction in a format that the enhanced disassembler can use to tokenize
// and parse instructions.
//
//===----------------------------------------------------------------------===//
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <string>
#include <vector>
using namespace llvm;
// TODO: There's a suspiciously large amount of "table" data in this
// backend which should probably be in the TableGen file itself.
///////////////////////////////////////////////////////////
// Support classes for emitting nested C data structures //
///////////////////////////////////////////////////////////
// TODO: These classes are probably generally useful to other backends;
// add them to TableGen's "helper" API's.
namespace {
class EnumEmitter {
private:
std::string Name;
std::vector<std::string> Entries;
public:
EnumEmitter(const char *N) : Name(N) {
}
int addEntry(const char *e) {
Entries.push_back(std::string(e));
return Entries.size() - 1;
}
void emit(raw_ostream &o, unsigned int &i) {
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
i += 2;
unsigned int index = 0;
unsigned int numEntries = Entries.size();
for (index = 0; index < numEntries; ++index) {
o.indent(i) << Entries[index];
if (index < (numEntries - 1))
o << ",";
o << "\n";
}
i -= 2;
o.indent(i) << "};" << "\n";
}
void emitAsFlags(raw_ostream &o, unsigned int &i) {
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
i += 2;
unsigned int index = 0;
unsigned int numEntries = Entries.size();
unsigned int flag = 1;
for (index = 0; index < numEntries; ++index) {
o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
if (index < (numEntries - 1))
o << ",";
o << "\n";
flag <<= 1;
}
i -= 2;
o.indent(i) << "};" << "\n";
}
};
} // End anonymous namespace
namespace {
class ConstantEmitter {
public:
virtual ~ConstantEmitter() { }
virtual void emit(raw_ostream &o, unsigned int &i) = 0;
};
} // End anonymous namespace
namespace {
class LiteralConstantEmitter : public ConstantEmitter {
private:
bool IsNumber;
union {
int Number;
const char* String;
};
public:
LiteralConstantEmitter(int number = 0) :
IsNumber(true),
Number(number) {
}
void set(const char *string) {
IsNumber = false;
Number = 0;
String = string;
}
bool is(const char *string) {
return !strcmp(String, string);
}
void emit(raw_ostream &o, unsigned int &i) {
if (IsNumber)
o << Number;
else
o