From ec3524064c57fbc2c5976ca301bbaadc94006d07 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 1 Aug 2004 05:04:00 +0000 Subject: [PATCH] Add, and start using, the CodeGenInstruction class. This class represents an instance of the Instruction tablegen class. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15385 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/CodeGenInstruction.h | 49 +++++++++++++++++++ utils/TableGen/CodeGenTarget.cpp | 36 ++++++++++++++ utils/TableGen/CodeGenTarget.h | 26 +++++++--- utils/TableGen/InstrInfoEmitter.cpp | 76 ++++++++++++++--------------- utils/TableGen/InstrInfoEmitter.h | 4 +- 5 files changed, 144 insertions(+), 47 deletions(-) create mode 100644 utils/TableGen/CodeGenInstruction.h diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h new file mode 100644 index 00000000000..88f2c17d9d8 --- /dev/null +++ b/utils/TableGen/CodeGenInstruction.h @@ -0,0 +1,49 @@ +//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a wrapper class for the 'Instruction' TableGen class. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_INSTRUCTION_H +#define CODEGEN_INSTRUCTION_H + +#include +#include +#include + +namespace llvm { + class Record; + + struct CodeGenInstruction { + Record *TheDef; // The actual record defining this instruction. + std::string Name; // Contents of the 'Name' field. + std::string Namespace; // The namespace the instruction is in. + + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; + + /// OperandList - The list of declared operands, along with their declared + /// type (which is a record). + std::vector > OperandList; + + // Various boolean values we track for the instruction. + bool isReturn; + bool isBranch; + bool isBarrier; + bool isCall; + bool isTwoAddress; + bool isTerminator; + + CodeGenInstruction(Record *R); + }; +} + +#endif diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index eef94db0b99..026119d8d0a 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -97,3 +97,39 @@ Record *CodeGenTarget::getInstructionSet() const { return TargetRec->getValueAsDef("InstructionSet"); } +void CodeGenTarget::ReadInstructions() const { + std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); + + if (Insts.size() == 0) + 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])); +} + +/// getPHIInstruction - Return the designated PHI instruction. +const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const { + Record *PHI = getInstructionSet()->getValueAsDef("PHIInst"); + std::map::const_iterator I = + getInstructions().find(PHI->getName()); + if (I == Instructions.end()) + throw "Could not find PHI instruction named '" + PHI->getName() + "'!"; + return I->second; +} + +CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R) { + Name = R->getValueAsString("Name"); + Namespace = R->getValueAsString("Namespace"); + AsmString = R->getValueAsString("AsmString"); + + //TODO: Parse OperandList + + isReturn = R->getValueAsBit("isReturn"); + isBranch = R->getValueAsBit("isBranch"); + isBarrier = R->getValueAsBit("isBarrier"); + isCall = R->getValueAsBit("isCall"); + isTwoAddress = R->getValueAsBit("isTwoAddress"); + isTerminator = R->getValueAsBit("isTerminator"); +} + + diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index aad277c516a..c3bd1e11535 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -17,10 +17,10 @@ #ifndef CODEGEN_TARGET_H #define CODEGEN_TARGET_H +#include "CodeGenInstruction.h" #include "llvm/CodeGen/ValueTypes.h" #include -#include -#include +#include namespace llvm { @@ -43,6 +43,8 @@ class CodeGenTarget { std::vector CalleeSavedRegisters; MVT::ValueType PointerType; + mutable std::map Instructions; + void ReadInstructions() const; public: CodeGenTarget(); @@ -55,12 +57,24 @@ public: MVT::ValueType getPointerType() const { return PointerType; } - // getInstructionSet - Return the InstructionSet object... + // getInstructionSet - Return the InstructionSet object. + /// Record *getInstructionSet() const; - // getInstructionSet - Return the CodeGenInstructionSet object for this - // target, lazily reading it from the record keeper as needed. - // CodeGenInstructionSet *getInstructionSet - + /// getPHIInstruction - Return the designated PHI instruction. + const CodeGenInstruction &getPHIInstruction() const; + + /// getInstructions - Return all of the instructions defined for this target. + /// + const std::map &getInstructions() const { + if (Instructions.empty()) ReadInstructions(); + return Instructions; + } + + typedef std::map::const_iterator inst_iterator; + inst_iterator inst_begin() const { return getInstructions().begin(); } + inst_iterator inst_end() const { return Instructions.end(); } }; } // End llvm namespace diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index a1c1984f3da..383e2a63e0d 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -19,31 +19,28 @@ using namespace llvm; // runEnums - Print out enum values for all of the instructions. void InstrInfoEmitter::runEnums(std::ostream &OS) { - std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); - - if (Insts.size() == 0) - throw std::string("No 'Instruction' subclasses defined!"); - - std::string Namespace = Insts[0]->getValueAsString("Namespace"); - EmitSourceFileHeader("Target Instruction Enum Values", OS); - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << " enum {\n"; - CodeGenTarget Target; // We must emit the PHI opcode first... Record *InstrInfo = Target.getInstructionSet(); Record *PHI = InstrInfo->getValueAsDef("PHIInst"); + std::string Namespace = Target.inst_begin()->second.Namespace; + + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << " enum {\n"; + OS << " " << PHI->getName() << ", \t// 0 (fixed for all targets)\n"; - // Print out the rest of the instructions now... - for (unsigned i = 0, e = Insts.size(); i != e; ++i) - if (Insts[i] != PHI) - OS << " " << Insts[i]->getName() << ", \t// " << i+1 << "\n"; + // Print out the rest of the instructions now. + unsigned i = 0; + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) + if (II->second.TheDef != PHI) + OS << " " << II->first << ", \t// " << ++i << "\n"; OS << " };\n"; if (!Namespace.empty()) @@ -71,16 +68,14 @@ void InstrInfoEmitter::run(std::ostream &OS) { Record *InstrInfo = Target.getInstructionSet(); Record *PHI = InstrInfo->getValueAsDef("PHIInst"); - std::vector Instructions = - Records.getAllDerivedDefinitions("Instruction"); - // Emit empty implicit uses and defs lists OS << "static const unsigned EmptyImpUses[] = { 0 };\n" << "static const unsigned EmptyImpDefs[] = { 0 };\n"; // Emit all of the instruction's implicit uses and defs... - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { - Record *Inst = Instructions[i]; + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) { + Record *Inst = II->second.TheDef; ListInit *LI = Inst->getValueAsListInit("Uses"); if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS); LI = Inst->getValueAsListInit("Defs"); @@ -89,27 +84,28 @@ void InstrInfoEmitter::run(std::ostream &OS) { OS << "\nstatic const TargetInstrDescriptor " << TargetName << "Insts[] = {\n"; - emitRecord(PHI, 0, InstrInfo, OS); + emitRecord(Target.getPHIInstruction(), 0, InstrInfo, OS); - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) - if (Instructions[i] != PHI) - emitRecord(Instructions[i], i+1, InstrInfo, OS); + unsigned i = 0; + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) + if (II->second.TheDef != PHI) + emitRecord(II->second, ++i, InstrInfo, OS); OS << "};\n"; EmitSourceFileTail(OS); } -void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo, - std::ostream &OS) { - OS << " { \"" << R->getValueAsString("Name") - << "\",\t-1, -1, 0, false, 0, 0, 0, 0"; +void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, + Record *InstrInfo, std::ostream &OS) { + OS << " { \"" << Inst.Name << "\",\t-1, -1, 0, false, 0, 0, 0, 0"; // Emit all of the target indepedent flags... - if (R->getValueAsBit("isReturn")) OS << "|M_RET_FLAG"; - if (R->getValueAsBit("isBranch")) OS << "|M_BRANCH_FLAG"; - if (R->getValueAsBit("isBarrier")) OS << "|M_BARRIER_FLAG"; - if (R->getValueAsBit("isCall" )) OS << "|M_CALL_FLAG"; - if (R->getValueAsBit("isTwoAddress")) OS << "|M_2_ADDR_FLAG"; - if (R->getValueAsBit("isTerminator")) OS << "|M_TERMINATOR_FLAG"; + if (Inst.isReturn) OS << "|M_RET_FLAG"; + if (Inst.isBranch) OS << "|M_BRANCH_FLAG"; + if (Inst.isBarrier) OS << "|M_BARRIER_FLAG"; + if (Inst.isCall) OS << "|M_CALL_FLAG"; + if (Inst.isTwoAddress) OS << "|M_2_ADDR_FLAG"; + if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG"; OS << ", 0"; // Emit all of the target-specific flags... @@ -120,25 +116,25 @@ void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo, ":(TargetInfoFields, TargetInfoPositions) must be equal!"; for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - emitShiftedValue(R, dynamic_cast(LI->getElement(i)), + emitShiftedValue(Inst.TheDef, dynamic_cast(LI->getElement(i)), dynamic_cast(Shift->getElement(i)), OS); OS << ", "; // Emit the implicit uses and defs lists... - LI = R->getValueAsListInit("Uses"); + LI = Inst.TheDef->getValueAsListInit("Uses"); if (!LI->getSize()) OS << "EmptyImpUses, "; else - OS << R->getName() << "ImpUses, "; + OS << Inst.TheDef->getName() << "ImpUses, "; - LI = R->getValueAsListInit("Defs"); + LI = Inst.TheDef->getValueAsListInit("Defs"); if (!LI->getSize()) OS << "EmptyImpDefs "; else - OS << R->getName() << "ImpDefs "; + OS << Inst.TheDef->getName() << "ImpDefs "; - OS << " }, // Inst #" << Num << " = " << R->getName() << "\n"; + OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 2a6b063debd..87a140b43aa 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -22,6 +22,7 @@ namespace llvm { class StringInit; class IntInit; class ListInit; +class CodeGenInstruction; class InstrInfoEmitter : public TableGenBackend { RecordKeeper &Records; @@ -36,7 +37,8 @@ public: private: void printDefList(ListInit *LI, const std::string &Name, std::ostream &OS) const; - void emitRecord(Record *R, unsigned Num, Record *InstrInfo, std::ostream &OS); + void emitRecord(const CodeGenInstruction &Inst, unsigned Num, + Record *InstrInfo, std::ostream &OS); void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, std::ostream &OS); }; -- 2.34.1