#include "CodeGenTarget.h"
#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
+static cl::opt<unsigned>
+AsmWriterNum("asmwriternum", cl::init(0),
+ cl::desc("Make -gen-asm-writer emit assembly writer #N"));
+
/// getValueType - Return the MCV::ValueType that the specified TableGen record
/// corresponds to.
MVT::ValueType llvm::getValueType(Record *Rec) {
return TargetRec->getValueAsDef("InstructionSet");
}
+/// getAsmWriter - Return the AssemblyWriter definition for this target.
+///
+Record *CodeGenTarget::getAsmWriter() const {
+ ListInit *LI = TargetRec->getValueAsListInit("AssemblyWriters");
+ if (AsmWriterNum >= LI->getSize())
+ throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!";
+ DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(AsmWriterNum));
+ if (!DI) throw std::string("AssemblyWriter list should be a list of defs!");
+ return DI->getDef();
+}
+
+void CodeGenTarget::ReadRegisters() const {
+ std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
+ if (Regs.empty())
+ throw std::string("No 'Register' subclasses defined!");
+
+ Registers.reserve(Regs.size());
+ Registers.assign(Regs.begin(), Regs.end());
+}
+
+CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) {
+ DeclaredSpillSize = R->getValueAsInt("SpillSize");
+ DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment");
+}
+
+const std::string &CodeGenRegister::getName() const {
+ return TheDef->getName();
+}
+
+void CodeGenTarget::ReadRegisterClasses() const {
+ std::vector<Record*> RegClasses =
+ Records.getAllDerivedDefinitions("RegisterClass");
+ if (RegClasses.empty())
+ throw std::string("No 'RegisterClass' subclasses defined!");
+
+ RegisterClasses.reserve(RegClasses.size());
+ RegisterClasses.assign(RegClasses.begin(), RegClasses.end());
+}
+
+CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
+ SpillSize = R->getValueAsInt("Size");
+ SpillAlignment = R->getValueAsInt("Alignment");
+
+ if (CodeInit *CI = dynamic_cast<CodeInit*>(R->getValueInit("Methods")))
+ MethodDefinitions = CI->getValue();
+ else
+ throw "Expected 'code' fragment for 'Methods' value in register class '"+
+ getName() + "'!";
+
+ ListInit *RegList = R->getValueAsListInit("MemberList");
+ for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
+ DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i));
+ if (!RegDef) throw "Register class member is not a record!";
+ Record *Reg = RegDef->getDef();
+
+ if (!Reg->isSubClassOf("Register"))
+ throw "Register Class member '" + Reg->getName() +
+ "' does not derive from the Register class!";
+ Elements.push_back(Reg);
+ }
+}
+
+const std::string &CodeGenRegisterClass::getName() const {
+ return TheDef->getName();
+}
+
+
+
void CodeGenTarget::ReadInstructions() const {
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
- if (Insts.size() == 0)
+ if (Insts.empty())
throw std::string("No 'Instruction' subclasses defined!");
- for (unsigned i = 0, e = Insts.size(); i != e; ++i)
- Instructions.insert(std::make_pair(Insts[i]->getName(), Insts[i]));
+ std::string InstFormatName =
+ getAsmWriter()->getValueAsString("InstFormatName");
+
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
+ std::string AsmStr = Insts[i]->getValueAsString(InstFormatName);
+ Instructions.insert(std::make_pair(Insts[i]->getName(),
+ CodeGenInstruction(Insts[i], AsmStr)));
+ }
}
/// getPHIInstruction - Return the designated PHI instruction.
+///
const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const {
Record *PHI = getInstructionSet()->getValueAsDef("PHIInst");
std::map<std::string, CodeGenInstruction>::const_iterator I =
return I->second;
}
-CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) {
+/// isLittleEndianEncoding - Return whether this target encodes its instruction
+/// in little-endian format, i.e. bits laid out in the order [0..n]
+///
+bool CodeGenTarget::isLittleEndianEncoding() const {
+ return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
+}
+
+CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
+ : TheDef(R), AsmString(AsmStr) {
Name = R->getValueAsString("Name");
Namespace = R->getValueAsString("Namespace");
- AsmString = R->getValueAsString("AsmString");
isReturn = R->getValueAsBit("isReturn");
isBranch = R->getValueAsBit("isBranch");
isBarrier = R->getValueAsBit("isBarrier");
isCall = R->getValueAsBit("isCall");
+ isLoad = R->getValueAsBit("isLoad");
+ isStore = R->getValueAsBit("isStore");
isTwoAddress = R->getValueAsBit("isTwoAddress");
isTerminator = R->getValueAsBit("isTerminator");
+ hasDelaySlot = R->getValueAsBit("hasDelaySlot");
try {
DagInit *DI = R->getValueAsDag("OperandList");
+ unsigned MIOperandNo = 0;
for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i)
if (DefInit *Arg = dynamic_cast<DefInit*>(DI->getArg(i))) {
Record *Rec = Arg->getDef();
MVT::ValueType Ty;
+ std::string PrintMethod = "printOperand";
+ unsigned NumOps = 1;
if (Rec->isSubClassOf("RegisterClass"))
Ty = getValueType(Rec->getValueAsDef("RegType"));
- else if (Rec->getName() == "i8imm")
- Ty = MVT::i8;
- else if (Rec->getName() == "i16imm")
- Ty = MVT::i16;
- else if (Rec->getName() == "i32imm")
- Ty = MVT::i32;
- else if (Rec->getName() == "i64imm")
- Ty = MVT::i64;
- else
+ else if (Rec->isSubClassOf("Operand")) {
+ Ty = getValueType(Rec->getValueAsDef("Type"));
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ NumOps = Rec->getValueAsInt("NumMIOperands");
+ } else
throw "Unknown operand class '" + Rec->getName() +
"' in instruction '" + R->getName() + "' instruction!";
- OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i)));
+ OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i),
+ PrintMethod, MIOperandNo));
+ MIOperandNo += NumOps;
} else {
throw "Illegal operand for the '" + R->getName() + "' instruction!";
}
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, throw an exception.
+///
unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
assert(!Name.empty() && "Cannot search for operand with no name!");
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)