PseudoLoweringEmitter.cpp revision 267654
150397Sobrien//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// 250397Sobrien// 390075Sobrien// The LLVM Compiler Infrastructure 450397Sobrien// 590075Sobrien// This file is distributed under the University of Illinois Open Source 650397Sobrien// License. See LICENSE.TXT for details. 790075Sobrien// 890075Sobrien//===----------------------------------------------------------------------===// 990075Sobrien 1090075Sobrien#define DEBUG_TYPE "pseudo-lowering" 1150397Sobrien#include "CodeGenInstruction.h" 1290075Sobrien#include "CodeGenTarget.h" 1390075Sobrien#include "llvm/ADT/IndexedMap.h" 1490075Sobrien#include "llvm/ADT/SmallVector.h" 1590075Sobrien#include "llvm/ADT/StringMap.h" 1650397Sobrien#include "llvm/Support/Debug.h" 1750397Sobrien#include "llvm/Support/ErrorHandling.h" 1890075Sobrien#include "llvm/TableGen/Error.h" 1990075Sobrien#include "llvm/TableGen/Record.h" 2090075Sobrien#include "llvm/TableGen/TableGenBackend.h" 2150397Sobrien#include <vector> 2250397Sobrienusing namespace llvm; 2350397Sobrien 2450397Sobriennamespace { 2550397Sobrienclass PseudoLoweringEmitter { 2650397Sobrien struct OpData { 2750397Sobrien enum MapKind { Operand, Imm, Reg }; 2850397Sobrien MapKind Kind; 2990075Sobrien union { 3090075Sobrien unsigned Operand; // Operand number mapped to. 3150397Sobrien uint64_t Imm; // Integer immedate value. 3290075Sobrien Record *Reg; // Physical register. 3390075Sobrien } Data; 3490075Sobrien }; 3590075Sobrien struct PseudoExpansion { 3690075Sobrien CodeGenInstruction Source; // The source pseudo instruction definition. 3790075Sobrien CodeGenInstruction Dest; // The destination instruction to lower to. 3850397Sobrien IndexedMap<OpData> OperandMap; 3950397Sobrien 4090075Sobrien PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, 4150397Sobrien IndexedMap<OpData> &m) : 4250397Sobrien Source(s), Dest(d), OperandMap(m) {} 4350397Sobrien }; 4450397Sobrien 4550397Sobrien RecordKeeper &Records; 4690075Sobrien 4790075Sobrien // It's overkill to have an instance of the full CodeGenTarget object, 4890075Sobrien // but it loads everything on demand, not in the constructor, so it's 4990075Sobrien // lightweight in performance, so it works out OK. 5090075Sobrien CodeGenTarget Target; 5190075Sobrien 5250397Sobrien SmallVector<PseudoExpansion, 64> Expansions; 5350397Sobrien 5450397Sobrien unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, 5550397Sobrien CodeGenInstruction &Insn, 5650397Sobrien IndexedMap<OpData> &OperandMap, 5750397Sobrien unsigned BaseIdx); 5890075Sobrien void evaluateExpansion(Record *Pseudo); 5990075Sobrien void emitLoweringEmitter(raw_ostream &o); 6090075Sobrienpublic: 6190075Sobrien PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} 6250397Sobrien 6350397Sobrien /// run - Output the pseudo-lowerings. 6450397Sobrien void run(raw_ostream &o); 6550397Sobrien}; 6690075Sobrien} // End anonymous namespace 6750397Sobrien 6850397Sobrien// FIXME: This pass currently can only expand a pseudo to a single instruction. 6950397Sobrien// The pseudo expansion really should take a list of dags, not just 7050397Sobrien// a single dag, so we can do fancier things. 7190075Sobrien 7250397Sobrienunsigned PseudoLoweringEmitter:: 7350397SobrienaddDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, 7450397Sobrien IndexedMap<OpData> &OperandMap, unsigned BaseIdx) { 7550397Sobrien unsigned OpsAdded = 0; 7690075Sobrien for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { 7790075Sobrien if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i))) { 7890075Sobrien // Physical register reference. Explicit check for the special case 7990075Sobrien // "zero_reg" definition. 8090075Sobrien if (DI->getDef()->isSubClassOf("Register") || 8190075Sobrien DI->getDef()->getName() == "zero_reg") { 8290075Sobrien OperandMap[BaseIdx + i].Kind = OpData::Reg; 8390075Sobrien OperandMap[BaseIdx + i].Data.Reg = DI->getDef(); 8490075Sobrien ++OpsAdded; 8590075Sobrien continue; 8690075Sobrien } 8790075Sobrien 8890075Sobrien // Normal operands should always have the same type, or we have a 8950397Sobrien // problem. 9090075Sobrien // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. 9190075Sobrien assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); 9250397Sobrien if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) 9390075Sobrien PrintFatalError(Rec->getLoc(), 9450397Sobrien "Pseudo operand type '" + DI->getDef()->getName() + 9550397Sobrien "' does not match expansion operand type '" + 9650397Sobrien Insn.Operands[BaseIdx + i].Rec->getName() + "'"); 9750397Sobrien // Source operand maps to destination operand. The Data element 9850397Sobrien // will be filled in later, just set the Kind for now. Do it 9950397Sobrien // for each corresponding MachineInstr operand, not just the first. 10050397Sobrien for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) 10190075Sobrien OperandMap[BaseIdx + i + I].Kind = OpData::Operand; 10250397Sobrien OpsAdded += Insn.Operands[i].MINumOperands; 10350397Sobrien } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(i))) { 10450397Sobrien OperandMap[BaseIdx + i].Kind = OpData::Imm; 10550397Sobrien OperandMap[BaseIdx + i].Data.Imm = II->getValue(); 10650397Sobrien ++OpsAdded; 10750397Sobrien } else if (DagInit *SubDag = dyn_cast<DagInit>(Dag->getArg(i))) { 10890075Sobrien // Just add the operands recursively. This is almost certainly 10990075Sobrien // a constant value for a complex operand (> 1 MI operand). 11090075Sobrien unsigned NewOps = 11190075Sobrien addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i); 11290075Sobrien OpsAdded += NewOps; 11390075Sobrien // Since we added more than one, we also need to adjust the base. 11490075Sobrien BaseIdx += NewOps - 1; 11590075Sobrien } else 11690075Sobrien llvm_unreachable("Unhandled pseudo-expansion argument type!"); 11790075Sobrien } 11890075Sobrien return OpsAdded; 11950397Sobrien} 12090075Sobrien 12150397Sobrienvoid PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { 12250397Sobrien DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n"); 12390075Sobrien 12490075Sobrien // Validate that the result pattern has the corrent number and types 12590075Sobrien // of arguments for the instruction it references. 12690075Sobrien DagInit *Dag = Rec->getValueAsDag("ResultInst"); 12790075Sobrien assert(Dag && "Missing result instruction in pseudo expansion!"); 12890075Sobrien DEBUG(dbgs() << " Result: " << *Dag << "\n"); 12990075Sobrien 13090075Sobrien DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator()); 13190075Sobrien if (!OpDef) 13290075Sobrien PrintFatalError(Rec->getLoc(), Rec->getName() + 13390075Sobrien " has unexpected operator type!"); 13490075Sobrien Record *Operator = OpDef->getDef(); 13590075Sobrien if (!Operator->isSubClassOf("Instruction")) 13690075Sobrien PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 13790075Sobrien "' is not an instruction!"); 13890075Sobrien 13990075Sobrien CodeGenInstruction Insn(Operator); 14090075Sobrien 14190075Sobrien if (Insn.isCodeGenOnly || Insn.isPseudo) 14290075Sobrien PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 14390075Sobrien "' cannot be another pseudo instruction!"); 14490075Sobrien 14590075Sobrien if (Insn.Operands.size() != Dag->getNumArgs()) 14690075Sobrien PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + 14790075Sobrien "' operand count mismatch"); 14890075Sobrien 14990075Sobrien unsigned NumMIOperands = 0; 15090075Sobrien for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) 15190075Sobrien NumMIOperands += Insn.Operands[i].MINumOperands; 15290075Sobrien IndexedMap<OpData> OperandMap; 15390075Sobrien OperandMap.grow(NumMIOperands); 15490075Sobrien 15590075Sobrien addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); 15690075Sobrien 15790075Sobrien // If there are more operands that weren't in the DAG, they have to 15890075Sobrien // be operands that have default values, or we have an error. Currently, 15990075Sobrien // Operands that are a sublass of OperandWithDefaultOp have default values. 16090075Sobrien 16190075Sobrien 16290075Sobrien // Validate that each result pattern argument has a matching (by name) 16390075Sobrien // argument in the source instruction, in either the (outs) or (ins) list. 16490075Sobrien // Also check that the type of the arguments match. 16590075Sobrien // 16690075Sobrien // Record the mapping of the source to result arguments for use by 16790075Sobrien // the lowering emitter. 16890075Sobrien CodeGenInstruction SourceInsn(Rec); 16990075Sobrien StringMap<unsigned> SourceOperands; 17090075Sobrien for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i) 17190075Sobrien SourceOperands[SourceInsn.Operands[i].Name] = i; 17290075Sobrien 17390075Sobrien DEBUG(dbgs() << " Operand mapping:\n"); 17490075Sobrien for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) { 17590075Sobrien // We've already handled constant values. Just map instruction operands 17690075Sobrien // here. 17790075Sobrien if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) 17890075Sobrien continue; 17990075Sobrien StringMap<unsigned>::iterator SourceOp = 18090075Sobrien SourceOperands.find(Dag->getArgName(i)); 18190075Sobrien if (SourceOp == SourceOperands.end()) 18290075Sobrien PrintFatalError(Rec->getLoc(), 18390075Sobrien "Pseudo output operand '" + Dag->getArgName(i) + 18490075Sobrien "' has no matching source operand."); 18590075Sobrien // Map the source operand to the destination operand index for each 18690075Sobrien // MachineInstr operand. 18790075Sobrien for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) 18890075Sobrien OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand = 18990075Sobrien SourceOp->getValue(); 19090075Sobrien 19190075Sobrien DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n"); 19290075Sobrien } 19390075Sobrien 19490075Sobrien Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap)); 19590075Sobrien} 19690075Sobrien 19790075Sobrienvoid PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { 19890075Sobrien // Emit file header. 19990075Sobrien emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); 20090075Sobrien 20190075Sobrien o << "bool " << Target.getName() + "AsmPrinter" << "::\n" 20290075Sobrien << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" 20390075Sobrien << " const MachineInstr *MI) {\n" 20490075Sobrien << " switch (MI->getOpcode()) {\n" 20590075Sobrien << " default: return false;\n"; 20690075Sobrien for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { 20790075Sobrien PseudoExpansion &Expansion = Expansions[i]; 20890075Sobrien CodeGenInstruction &Source = Expansion.Source; 20990075Sobrien CodeGenInstruction &Dest = Expansion.Dest; 21090075Sobrien o << " case " << Source.Namespace << "::" 21190075Sobrien << Source.TheDef->getName() << ": {\n" 21290075Sobrien << " MCInst TmpInst;\n" 21390075Sobrien << " MCOperand MCOp;\n" 21490075Sobrien << " TmpInst.setOpcode(" << Dest.Namespace << "::" 21590075Sobrien << Dest.TheDef->getName() << ");\n"; 21690075Sobrien 21790075Sobrien // Copy the operands from the source instruction. 21890075Sobrien // FIXME: Instruction operands with defaults values (predicates and cc_out 21990075Sobrien // in ARM, for example shouldn't need explicit values in the 22090075Sobrien // expansion DAG. 22190075Sobrien unsigned MIOpNo = 0; 22290075Sobrien for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; 22390075Sobrien ++OpNo) { 22490075Sobrien o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; 22590075Sobrien for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; 22690075Sobrien i != e; ++i) { 22790075Sobrien switch (Expansion.OperandMap[MIOpNo + i].Kind) { 22890075Sobrien case OpData::Operand: 22990075Sobrien o << " lowerOperand(MI->getOperand(" 23090075Sobrien << Source.Operands[Expansion.OperandMap[MIOpNo].Data 23190075Sobrien .Operand].MIOperandNo + i 23290075Sobrien << "), MCOp);\n" 23390075Sobrien << " TmpInst.addOperand(MCOp);\n"; 23490075Sobrien break; 23590075Sobrien case OpData::Imm: 23690075Sobrien o << " TmpInst.addOperand(MCOperand::CreateImm(" 23790075Sobrien << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; 23890075Sobrien break; 23990075Sobrien case OpData::Reg: { 24090075Sobrien Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; 24190075Sobrien o << " TmpInst.addOperand(MCOperand::CreateReg("; 24290075Sobrien // "zero_reg" is special. 24390075Sobrien if (Reg->getName() == "zero_reg") 24490075Sobrien o << "0"; 24590075Sobrien else 24690075Sobrien o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); 24790075Sobrien o << "));\n"; 24890075Sobrien break; 24990075Sobrien } 25090075Sobrien } 25190075Sobrien } 25290075Sobrien MIOpNo += Dest.Operands[OpNo].MINumOperands; 25390075Sobrien } 25490075Sobrien if (Dest.Operands.isVariadic) { 25590075Sobrien MIOpNo = Source.Operands.size() + 1; 25690075Sobrien o << " // variable_ops\n"; 25790075Sobrien o << " for (unsigned i = " << MIOpNo 25890075Sobrien << ", e = MI->getNumOperands(); i != e; ++i)\n" 25990075Sobrien << " if (lowerOperand(MI->getOperand(i), MCOp))\n" 26090075Sobrien << " TmpInst.addOperand(MCOp);\n"; 26190075Sobrien } 26290075Sobrien o << " OutStreamer.EmitInstruction(TmpInst);\n" 26390075Sobrien << " break;\n" 26490075Sobrien << " }\n"; 26590075Sobrien } 26690075Sobrien o << " }\n return true;\n}\n\n"; 26790075Sobrien} 26890075Sobrien 26990075Sobrienvoid PseudoLoweringEmitter::run(raw_ostream &o) { 27090075Sobrien Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); 27190075Sobrien Record *InstructionClass = Records.getClass("Instruction"); 27290075Sobrien assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); 27390075Sobrien assert(InstructionClass && "Instruction class definition missing!"); 27490075Sobrien 27590075Sobrien std::vector<Record*> Insts; 27690075Sobrien for (std::map<std::string, Record*>::const_iterator I = 27790075Sobrien Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { 27890075Sobrien if (I->second->isSubClassOf(ExpansionClass) && 27990075Sobrien I->second->isSubClassOf(InstructionClass)) 28090075Sobrien Insts.push_back(I->second); 28190075Sobrien } 28290075Sobrien 28390075Sobrien // Process the pseudo expansion definitions, validating them as we do so. 28490075Sobrien for (unsigned i = 0, e = Insts.size(); i != e; ++i) 28590075Sobrien evaluateExpansion(Insts[i]); 28690075Sobrien 28790075Sobrien // Generate expansion code to lower the pseudo to an MCInst of the real 28890075Sobrien // instruction. 28990075Sobrien emitLoweringEmitter(o); 29090075Sobrien} 29190075Sobrien 29290075Sobriennamespace llvm { 29390075Sobrien 29490075Sobrienvoid EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) { 29590075Sobrien PseudoLoweringEmitter(RK).run(OS); 29690075Sobrien} 29790075Sobrien 29890075Sobrien} // End llvm namespace 29990075Sobrien