X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FPseudoLoweringEmitter.cpp;h=1ea6f7932a3e7d0204aa0b460f3f6a4d3424a187;hb=d573aba8e13c2afc5ad7c3c3c442a3a84f8bd94d;hp=5cfa587f1d9e47867ab60e20ac14da443d138fe7;hpb=f37dd02f7743ebd2424480361f5a7db510495c4f;p=oota-llvm.git diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 5cfa587f1d9..1ea6f7932a3 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -8,27 +8,73 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pseudo-lowering" -#include "Error.h" #include "CodeGenInstruction.h" -#include "PseudoLoweringEmitter.h" -#include "Record.h" +#include "CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include using namespace llvm; +namespace { +class PseudoLoweringEmitter { + struct OpData { + enum MapKind { Operand, Imm, Reg }; + MapKind Kind; + union { + unsigned Operand; // Operand number mapped to. + uint64_t Imm; // Integer immedate value. + Record *Reg; // Physical register. + } Data; + }; + struct PseudoExpansion { + CodeGenInstruction Source; // The source pseudo instruction definition. + CodeGenInstruction Dest; // The destination instruction to lower to. + IndexedMap OperandMap; + + PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, + IndexedMap &m) : + Source(s), Dest(d), OperandMap(m) {} + }; + + RecordKeeper &Records; + + // It's overkill to have an instance of the full CodeGenTarget object, + // but it loads everything on demand, not in the constructor, so it's + // lightweight in performance, so it works out OK. + CodeGenTarget Target; + + SmallVector Expansions; + + unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, + CodeGenInstruction &Insn, + IndexedMap &OperandMap, + unsigned BaseIdx); + void evaluateExpansion(Record *Pseudo); + void emitLoweringEmitter(raw_ostream &o); +public: + PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} + + /// run - Output the pseudo-lowerings. + void run(raw_ostream &o); +}; +} // End anonymous namespace + // FIXME: This pass currently can only expand a pseudo to a single instruction. // The pseudo expansion really should take a list of dags, not just // a single dag, so we can do fancier things. unsigned PseudoLoweringEmitter:: -addDagOperandMapping(Record *Rec, const DagInit *Dag, CodeGenInstruction &Insn, +addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, IndexedMap &OperandMap, unsigned BaseIdx) { unsigned OpsAdded = 0; for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { - if (const DefInit *DI = dynamic_cast(Dag->getArg(i))) { + if (DefInit *DI = dyn_cast(Dag->getArg(i))) { // Physical register reference. Explicit check for the special case // "zero_reg" definition. if (DI->getDef()->isSubClassOf("Register") || @@ -44,7 +90,7 @@ addDagOperandMapping(Record *Rec, const DagInit *Dag, CodeGenInstruction &Insn, // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) - throw TGError(Rec->getLoc(), + PrintFatalError(Rec->getLoc(), "Pseudo operand type '" + DI->getDef()->getName() + "' does not match expansion operand type '" + Insn.Operands[BaseIdx + i].Rec->getName() + "'"); @@ -54,11 +100,11 @@ addDagOperandMapping(Record *Rec, const DagInit *Dag, CodeGenInstruction &Insn, for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) OperandMap[BaseIdx + i + I].Kind = OpData::Operand; OpsAdded += Insn.Operands[i].MINumOperands; - } else if (const IntInit *II = dynamic_cast(Dag->getArg(i))) { + } else if (IntInit *II = dyn_cast(Dag->getArg(i))) { OperandMap[BaseIdx + i].Kind = OpData::Imm; OperandMap[BaseIdx + i].Data.Imm = II->getValue(); ++OpsAdded; - } else if (const DagInit *SubDag = dynamic_cast(Dag->getArg(i))) { + } else if (DagInit *SubDag = dyn_cast(Dag->getArg(i))) { // Just add the operands recursively. This is almost certainly // a constant value for a complex operand (> 1 MI operand). unsigned NewOps = @@ -67,7 +113,7 @@ addDagOperandMapping(Record *Rec, const DagInit *Dag, CodeGenInstruction &Insn, // Since we added more than one, we also need to adjust the base. BaseIdx += NewOps - 1; } else - assert(0 && "Unhandled pseudo-expansion argument type!"); + llvm_unreachable("Unhandled pseudo-expansion argument type!"); } return OpsAdded; } @@ -77,37 +123,40 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { // Validate that the result pattern has the corrent number and types // of arguments for the instruction it references. - const DagInit *Dag = Rec->getValueAsDag("ResultInst"); + DagInit *Dag = Rec->getValueAsDag("ResultInst"); assert(Dag && "Missing result instruction in pseudo expansion!"); DEBUG(dbgs() << " Result: " << *Dag << "\n"); - const DefInit *OpDef = dynamic_cast(Dag->getOperator()); + DefInit *OpDef = dyn_cast(Dag->getOperator()); if (!OpDef) - throw TGError(Rec->getLoc(), Rec->getName() + + PrintFatalError(Rec->getLoc(), Rec->getName() + " has unexpected operator type!"); Record *Operator = OpDef->getDef(); if (!Operator->isSubClassOf("Instruction")) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' is not an instruction!"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' is not an instruction!"); CodeGenInstruction Insn(Operator); if (Insn.isCodeGenOnly || Insn.isPseudo) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' cannot be another pseudo instruction!"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' cannot be another pseudo instruction!"); if (Insn.Operands.size() != Dag->getNumArgs()) - throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + - "' operand count mismatch"); + PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' operand count mismatch"); + unsigned NumMIOperands = 0; + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) + NumMIOperands += Insn.Operands[i].MINumOperands; IndexedMap OperandMap; - OperandMap.grow(Insn.Operands.size()); + OperandMap.grow(NumMIOperands); addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); // If there are more operands that weren't in the DAG, they have to // be operands that have default values, or we have an error. Currently, - // PredicateOperand and OptionalDefOperand both have default values. + // Operands that are a sublass of OperandWithDefaultOp have default values. // Validate that each result pattern argument has a matching (by name) @@ -130,9 +179,9 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { StringMap::iterator SourceOp = SourceOperands.find(Dag->getArgName(i)); if (SourceOp == SourceOperands.end()) - throw TGError(Rec->getLoc(), - "Pseudo output operand '" + Dag->getArgName(i) + - "' has no matching source operand."); + PrintFatalError(Rec->getLoc(), + "Pseudo output operand '" + Dag->getArgName(i) + + "' has no matching source operand."); // Map the source operand to the destination operand index for each // MachineInstr operand. for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) @@ -147,7 +196,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { // Emit file header. - EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); + emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); o << "bool " << Target.getName() + "AsmPrinter" << "::\n" << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" @@ -176,8 +225,6 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; i != e; ++i) { switch (Expansion.OperandMap[MIOpNo + i].Kind) { - default: - llvm_unreachable("Unknown operand type?!"); case OpData::Operand: o << " lowerOperand(MI->getOperand(" << Source.Operands[Expansion.OperandMap[MIOpNo].Data @@ -205,6 +252,7 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { MIOpNo += Dest.Operands[OpNo].MINumOperands; } if (Dest.Operands.isVariadic) { + MIOpNo = Source.Operands.size() + 1; o << " // variable_ops\n"; o << " for (unsigned i = " << MIOpNo << ", e = MI->getNumOperands(); i != e; ++i)\n" @@ -220,7 +268,7 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { void PseudoLoweringEmitter::run(raw_ostream &o) { Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); - Record *InstructionClass = Records.getClass("PseudoInstExpansion"); + Record *InstructionClass = Records.getClass("Instruction"); assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); assert(InstructionClass && "Instruction class definition missing!"); @@ -241,3 +289,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) { emitLoweringEmitter(o); } +namespace llvm { + +void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) { + PseudoLoweringEmitter(RK).run(OS); +} + +} // End llvm namespace