186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// 286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// 386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// The LLVM Compiler Infrastructure 486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// 586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// This file is distributed under the University of Illinois Open Source 686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// License. See LICENSE.TXT for details. 786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// 886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach//===----------------------------------------------------------------------===// 986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 1086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#define DEBUG_TYPE "pseudo-lowering" 1186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#include "CodeGenInstruction.h" 126f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "CodeGenTarget.h" 1386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#include "llvm/ADT/IndexedMap.h" 146f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/ADT/SmallVector.h" 1586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#include "llvm/ADT/StringMap.h" 1686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#include "llvm/Support/Debug.h" 176f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/Support/ErrorHandling.h" 186f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/Error.h" 196f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/Record.h" 206f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h" 2186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach#include <vector> 2286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbachusing namespace llvm; 2386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 246f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace { 256f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenclass PseudoLoweringEmitter { 266f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen struct OpData { 276f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen enum MapKind { Operand, Imm, Reg }; 286f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen MapKind Kind; 296f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen union { 306f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned Operand; // Operand number mapped to. 316f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen uint64_t Imm; // Integer immedate value. 326f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen Record *Reg; // Physical register. 336f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen } Data; 346f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen }; 356f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen struct PseudoExpansion { 366f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen CodeGenInstruction Source; // The source pseudo instruction definition. 376f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen CodeGenInstruction Dest; // The destination instruction to lower to. 386f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen IndexedMap<OpData> OperandMap; 396f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 406f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, 416f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen IndexedMap<OpData> &m) : 426f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen Source(s), Dest(d), OperandMap(m) {} 436f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen }; 446f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 456f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen RecordKeeper &Records; 466f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 476f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen // It's overkill to have an instance of the full CodeGenTarget object, 486f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen // but it loads everything on demand, not in the constructor, so it's 496f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen // lightweight in performance, so it works out OK. 506f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen CodeGenTarget Target; 516f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 526f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen SmallVector<PseudoExpansion, 64> Expansions; 536f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 546f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, 556f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen CodeGenInstruction &Insn, 566f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen IndexedMap<OpData> &OperandMap, 576f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned BaseIdx); 586f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void evaluateExpansion(Record *Pseudo); 596f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void emitLoweringEmitter(raw_ostream &o); 606f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenpublic: 616f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} 626f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen /// run - Output the pseudo-lowerings. 646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void run(raw_ostream &o); 656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen}; 666f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End anonymous namespace 676f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 6886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// FIXME: This pass currently can only expand a pseudo to a single instruction. 6986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// The pseudo expansion really should take a list of dags, not just 7086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach// a single dag, so we can do fancier things. 7186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 7286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbachunsigned PseudoLoweringEmitter:: 7305bce0beee87512e52428d4b80f5a8e79a949576David GreeneaddDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, 7486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach IndexedMap<OpData> &OperandMap, unsigned BaseIdx) { 7586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach unsigned OpsAdded = 0; 7686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { 7705bce0beee87512e52428d4b80f5a8e79a949576David Greene if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) { 7886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Physical register reference. Explicit check for the special case 7986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // "zero_reg" definition. 8086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (DI->getDef()->isSubClassOf("Register") || 8186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach DI->getDef()->getName() == "zero_reg") { 8286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[BaseIdx + i].Kind = OpData::Reg; 8386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[BaseIdx + i].Data.Reg = DI->getDef(); 8486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach ++OpsAdded; 8586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach continue; 8686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 8786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 8886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Normal operands should always have the same type, or we have a 8986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // problem. 9086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. 9186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); 9286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) 9386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), 9486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "Pseudo operand type '" + DI->getDef()->getName() + 9586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "' does not match expansion operand type '" + 9686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Insn.Operands[BaseIdx + i].Rec->getName() + "'"); 9786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Source operand maps to destination operand. The Data element 9886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // will be filled in later, just set the Kind for now. Do it 9986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // for each corresponding MachineInstr operand, not just the first. 10086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) 10186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[BaseIdx + i + I].Kind = OpData::Operand; 10286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OpsAdded += Insn.Operands[i].MINumOperands; 10305bce0beee87512e52428d4b80f5a8e79a949576David Greene } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) { 10486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[BaseIdx + i].Kind = OpData::Imm; 10586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[BaseIdx + i].Data.Imm = II->getValue(); 10686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach ++OpsAdded; 10705bce0beee87512e52428d4b80f5a8e79a949576David Greene } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) { 10886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Just add the operands recursively. This is almost certainly 10986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // a constant value for a complex operand (> 1 MI operand). 11086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach unsigned NewOps = 11186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i); 11286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OpsAdded += NewOps; 11386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Since we added more than one, we also need to adjust the base. 11486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach BaseIdx += NewOps - 1; 11586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } else 116655b8de7b2ab773a977e0c524307e71354d8af29Craig Topper llvm_unreachable("Unhandled pseudo-expansion argument type!"); 11786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 11886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach return OpsAdded; 11986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach} 12086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 12186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbachvoid PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { 12286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n"); 12386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 12486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Validate that the result pattern has the corrent number and types 12586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // of arguments for the instruction it references. 12605bce0beee87512e52428d4b80f5a8e79a949576David Greene DagInit *Dag = Rec->getValueAsDag("ResultInst"); 12786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach assert(Dag && "Missing result instruction in pseudo expansion!"); 12886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach DEBUG(dbgs() << " Result: " << *Dag << "\n"); 12986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 13005bce0beee87512e52428d4b80f5a8e79a949576David Greene DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); 13186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (!OpDef) 13286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), Rec->getName() + 13386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach " has unexpected operator type!"); 13486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Record *Operator = OpDef->getDef(); 13586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (!Operator->isSubClassOf("Instruction")) 13686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 13786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "' is not an instruction!"); 13886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 13986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach CodeGenInstruction Insn(Operator); 14086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 14186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (Insn.isCodeGenOnly || Insn.isPseudo) 14286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 14386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "' cannot be another pseudo instruction!"); 14486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 14586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (Insn.Operands.size() != Dag->getNumArgs()) 14686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 14786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "' operand count mismatch"); 14886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 149aa7b3df1788e6ffdaa9b661cfdccdc41ad181567Evan Cheng unsigned NumMIOperands = 0; 150aa7b3df1788e6ffdaa9b661cfdccdc41ad181567Evan Cheng for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) 151aa7b3df1788e6ffdaa9b661cfdccdc41ad181567Evan Cheng NumMIOperands += Insn.Operands[i].MINumOperands; 15286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach IndexedMap<OpData> OperandMap; 153aa7b3df1788e6ffdaa9b661cfdccdc41ad181567Evan Cheng OperandMap.grow(NumMIOperands); 15486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 15586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); 15686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 15786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // If there are more operands that weren't in the DAG, they have to 15886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // be operands that have default values, or we have an error. Currently, 1596d3d7656539188b496089a3313ed4d13759adba3Tom Stellard // Operands that are a sublass of OperandWithDefaultOp have default values. 16086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 16186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 16286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Validate that each result pattern argument has a matching (by name) 16386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // argument in the source instruction, in either the (outs) or (ins) list. 16486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Also check that the type of the arguments match. 16586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // 16686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Record the mapping of the source to result arguments for use by 16786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // the lowering emitter. 16886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach CodeGenInstruction SourceInsn(Rec); 16986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach StringMap<unsigned> SourceOperands; 17086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i) 17186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach SourceOperands[SourceInsn.Operands[i].Name] = i; 17286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 17386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach DEBUG(dbgs() << " Operand mapping:\n"); 17486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) { 17586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // We've already handled constant values. Just map instruction operands 17686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // here. 17786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) 17886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach continue; 17986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach StringMap<unsigned>::iterator SourceOp = 18086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach SourceOperands.find(Dag->getArgName(i)); 18186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (SourceOp == SourceOperands.end()) 18286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach throw TGError(Rec->getLoc(), 18386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "Pseudo output operand '" + Dag->getArgName(i) + 18486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach "' has no matching source operand."); 18586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Map the source operand to the destination operand index for each 18686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // MachineInstr operand. 18786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) 18886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand = 18986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach SourceOp->getValue(); 19086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 19186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n"); 19286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 19386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 19486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap)); 19586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach} 19686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 19786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbachvoid PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { 19886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Emit file header. 1996f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); 20086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 20186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << "bool " << Target.getName() + "AsmPrinter" << "::\n" 20286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" 20386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " const MachineInstr *MI) {\n" 20486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " switch (MI->getOpcode()) {\n" 20586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " default: return false;\n"; 20686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { 20786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach PseudoExpansion &Expansion = Expansions[i]; 20886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach CodeGenInstruction &Source = Expansion.Source; 20986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach CodeGenInstruction &Dest = Expansion.Dest; 21086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " case " << Source.Namespace << "::" 21186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << Source.TheDef->getName() << ": {\n" 21286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " MCInst TmpInst;\n" 21386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " MCOperand MCOp;\n" 21486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " TmpInst.setOpcode(" << Dest.Namespace << "::" 21586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << Dest.TheDef->getName() << ");\n"; 21686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 21786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Copy the operands from the source instruction. 21886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // FIXME: Instruction operands with defaults values (predicates and cc_out 21986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // in ARM, for example shouldn't need explicit values in the 22086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // expansion DAG. 22186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach unsigned MIOpNo = 0; 22286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; 22386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach ++OpNo) { 22486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; 22586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; 22686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach i != e; ++i) { 22786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach switch (Expansion.OperandMap[MIOpNo + i].Kind) { 22886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach case OpData::Operand: 22986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " lowerOperand(MI->getOperand(" 23086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << Source.Operands[Expansion.OperandMap[MIOpNo].Data 23186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach .Operand].MIOperandNo + i 23286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << "), MCOp);\n" 23386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " TmpInst.addOperand(MCOp);\n"; 23486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach break; 23586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach case OpData::Imm: 23686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " TmpInst.addOperand(MCOperand::CreateImm(" 23786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; 23886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach break; 23986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach case OpData::Reg: { 24086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; 24186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " TmpInst.addOperand(MCOperand::CreateReg("; 24286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // "zero_reg" is special. 24386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (Reg->getName() == "zero_reg") 24486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << "0"; 24586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach else 24686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); 24786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << "));\n"; 24886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach break; 24986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 25086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 25186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 25286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach MIOpNo += Dest.Operands[OpNo].MINumOperands; 25386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 25486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (Dest.Operands.isVariadic) { 25586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " // variable_ops\n"; 25686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " for (unsigned i = " << MIOpNo 25786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << ", e = MI->getNumOperands(); i != e; ++i)\n" 25886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " if (lowerOperand(MI->getOperand(i), MCOp))\n" 25986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " TmpInst.addOperand(MCOp);\n"; 26086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 26186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " OutStreamer.EmitInstruction(TmpInst);\n" 26286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " break;\n" 26386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach << " }\n"; 26486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 26586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach o << " }\n return true;\n}\n\n"; 26686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach} 26786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 26886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbachvoid PseudoLoweringEmitter::run(raw_ostream &o) { 26986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); 27086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Record *InstructionClass = Records.getClass("PseudoInstExpansion"); 27186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); 27286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach assert(InstructionClass && "Instruction class definition missing!"); 27386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 27486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach std::vector<Record*> Insts; 27586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (std::map<std::string, Record*>::const_iterator I = 27686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { 27786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach if (I->second->isSubClassOf(ExpansionClass) && 27886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach I->second->isSubClassOf(InstructionClass)) 27986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach Insts.push_back(I->second); 28086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach } 28186f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 28286f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Process the pseudo expansion definitions, validating them as we do so. 28386f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach for (unsigned i = 0, e = Insts.size(); i != e; ++i) 28486f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach evaluateExpansion(Insts[i]); 28586f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 28686f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // Generate expansion code to lower the pseudo to an MCInst of the real 28786f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach // instruction. 28886f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach emitLoweringEmitter(o); 28986f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach} 29086f9adb8becf5da6962bd89301e96bccba26f72aJim Grosbach 2916f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace llvm { 2926f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 2936f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenvoid EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) { 2946f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen PseudoLoweringEmitter(RK).run(OS); 2956f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} 2966f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 2976f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End llvm namespace 298