* Add option to read isLittleEndianEncoding for InstrInfo classes
[oota-llvm.git] / utils / TableGen / CodeGenTarget.cpp
index eef6afe7b0356395b0a502c33f0e2008cdc01297..3680f197c4913ff4c5c418f37b614d9faf82edf7 100644 (file)
 
 #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) {
@@ -97,17 +103,92 @@ Record *CodeGenTarget::getInstructionSet() const {
   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 =
@@ -117,40 +198,51 @@ const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const {
   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!";
       }
@@ -166,6 +258,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) {
 /// 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)