LLVM API Documentation

MipsMCInstLower.cpp
Go to the documentation of this file.
00001 //===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains code to lower Mips MachineInstrs to their corresponding
00011 // MCInst records.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 #include "MipsMCInstLower.h"
00015 #include "MCTargetDesc/MipsBaseInfo.h"
00016 #include "MipsAsmPrinter.h"
00017 #include "MipsInstrInfo.h"
00018 #include "llvm/CodeGen/MachineFunction.h"
00019 #include "llvm/CodeGen/MachineInstr.h"
00020 #include "llvm/CodeGen/MachineOperand.h"
00021 #include "llvm/IR/Mangler.h"
00022 #include "llvm/MC/MCContext.h"
00023 #include "llvm/MC/MCExpr.h"
00024 #include "llvm/MC/MCInst.h"
00025 
00026 using namespace llvm;
00027 
00028 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
00029   : AsmPrinter(asmprinter) {}
00030 
00031 void MipsMCInstLower::Initialize(MCContext *C) {
00032   Ctx = C;
00033 }
00034 
00035 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
00036                                               MachineOperandType MOTy,
00037                                               unsigned Offset) const {
00038   MCSymbolRefExpr::VariantKind Kind;
00039   const MCSymbol *Symbol;
00040 
00041   switch(MO.getTargetFlags()) {
00042   default:                   llvm_unreachable("Invalid target flag!");
00043   case MipsII::MO_NO_FLAG:   Kind = MCSymbolRefExpr::VK_None; break;
00044   case MipsII::MO_GPREL:     Kind = MCSymbolRefExpr::VK_Mips_GPREL; break;
00045   case MipsII::MO_GOT_CALL:  Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break;
00046   case MipsII::MO_GOT16:     Kind = MCSymbolRefExpr::VK_Mips_GOT16; break;
00047   case MipsII::MO_GOT:       Kind = MCSymbolRefExpr::VK_Mips_GOT; break;
00048   case MipsII::MO_ABS_HI:    Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break;
00049   case MipsII::MO_ABS_LO:    Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;
00050   case MipsII::MO_TLSGD:     Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break;
00051   case MipsII::MO_TLSLDM:    Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break;
00052   case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break;
00053   case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break;
00054   case MipsII::MO_GOTTPREL:  Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break;
00055   case MipsII::MO_TPREL_HI:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break;
00056   case MipsII::MO_TPREL_LO:  Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break;
00057   case MipsII::MO_GPOFF_HI:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
00058   case MipsII::MO_GPOFF_LO:  Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
00059   case MipsII::MO_GOT_DISP:  Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break;
00060   case MipsII::MO_GOT_PAGE:  Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
00061   case MipsII::MO_GOT_OFST:  Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
00062   case MipsII::MO_HIGHER:    Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
00063   case MipsII::MO_HIGHEST:   Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
00064   case MipsII::MO_GOT_HI16:  Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break;
00065   case MipsII::MO_GOT_LO16:  Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break;
00066   case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break;
00067   case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break;
00068   }
00069 
00070   switch (MOTy) {
00071   case MachineOperand::MO_MachineBasicBlock:
00072     Symbol = MO.getMBB()->getSymbol();
00073     break;
00074 
00075   case MachineOperand::MO_GlobalAddress:
00076     Symbol = AsmPrinter.getSymbol(MO.getGlobal());
00077     Offset += MO.getOffset();
00078     break;
00079 
00080   case MachineOperand::MO_BlockAddress:
00081     Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
00082     Offset += MO.getOffset();
00083     break;
00084 
00085   case MachineOperand::MO_ExternalSymbol:
00086     Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
00087     Offset += MO.getOffset();
00088     break;
00089 
00090   case MachineOperand::MO_JumpTableIndex:
00091     Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
00092     break;
00093 
00094   case MachineOperand::MO_ConstantPoolIndex:
00095     Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
00096     Offset += MO.getOffset();
00097     break;
00098 
00099   default:
00100     llvm_unreachable("<unknown operand type>");
00101   }
00102 
00103   const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx);
00104 
00105   if (!Offset)
00106     return MCOperand::CreateExpr(MCSym);
00107 
00108   // Assume offset is never negative.
00109   assert(Offset > 0);
00110 
00111   const MCConstantExpr *OffsetExpr =  MCConstantExpr::Create(Offset, *Ctx);
00112   const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx);
00113   return MCOperand::CreateExpr(Add);
00114 }
00115 
00116 /*
00117 static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0,
00118                          const MCOperand &Opnd1,
00119                          const MCOperand &Opnd2 = MCOperand()) {
00120   Inst.setOpcode(Opc);
00121   Inst.addOperand(Opnd0);
00122   Inst.addOperand(Opnd1);
00123   if (Opnd2.isValid())
00124     Inst.addOperand(Opnd2);
00125 }
00126 */
00127 
00128 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
00129                                         unsigned offset) const {
00130   MachineOperandType MOTy = MO.getType();
00131 
00132   switch (MOTy) {
00133   default: llvm_unreachable("unknown operand type");
00134   case MachineOperand::MO_Register:
00135     // Ignore all implicit register operands.
00136     if (MO.isImplicit()) break;
00137     return MCOperand::CreateReg(MO.getReg());
00138   case MachineOperand::MO_Immediate:
00139     return MCOperand::CreateImm(MO.getImm() + offset);
00140   case MachineOperand::MO_MachineBasicBlock:
00141   case MachineOperand::MO_GlobalAddress:
00142   case MachineOperand::MO_ExternalSymbol:
00143   case MachineOperand::MO_JumpTableIndex:
00144   case MachineOperand::MO_ConstantPoolIndex:
00145   case MachineOperand::MO_BlockAddress:
00146     return LowerSymbolOperand(MO, MOTy, offset);
00147   case MachineOperand::MO_RegisterMask:
00148     break;
00149  }
00150 
00151   return MCOperand();
00152 }
00153 
00154 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
00155                                      MachineBasicBlock *BB2,
00156                                      MCSymbolRefExpr::VariantKind Kind) const {
00157   const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx);
00158   const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx);
00159   const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx);
00160 
00161   return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx));
00162 }
00163 
00164 void MipsMCInstLower::
00165 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
00166   OutMI.setOpcode(Mips::LUi);
00167 
00168   // Lower register operand.
00169   OutMI.addOperand(LowerOperand(MI->getOperand(0)));
00170 
00171   // Create %hi($tgt-$baltgt).
00172   OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
00173                              MI->getOperand(2).getMBB(),
00174                              MCSymbolRefExpr::VK_Mips_ABS_HI));
00175 }
00176 
00177 void MipsMCInstLower::
00178 lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
00179                      MCSymbolRefExpr::VariantKind Kind) const {
00180   OutMI.setOpcode(Opcode);
00181 
00182   // Lower two register operands.
00183   for (unsigned I = 0, E = 2; I != E; ++I) {
00184     const MachineOperand &MO = MI->getOperand(I);
00185     OutMI.addOperand(LowerOperand(MO));
00186   }
00187 
00188   // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
00189   OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
00190                              MI->getOperand(3).getMBB(), Kind));
00191 }
00192 
00193 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
00194                                       MCInst &OutMI) const {
00195   switch (MI->getOpcode()) {
00196   default:
00197     return false;
00198   case Mips::LONG_BRANCH_LUi:
00199     lowerLongBranchLUi(MI, OutMI);
00200     return true;
00201   case Mips::LONG_BRANCH_ADDiu:
00202     lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
00203                          MCSymbolRefExpr::VK_Mips_ABS_LO);
00204     return true;
00205   case Mips::LONG_BRANCH_DADDiu:
00206     unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
00207     if (TargetFlags == MipsII::MO_ABS_HI)
00208       lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
00209                            MCSymbolRefExpr::VK_Mips_ABS_HI);
00210     else if (TargetFlags == MipsII::MO_ABS_LO)
00211       lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
00212                            MCSymbolRefExpr::VK_Mips_ABS_LO);
00213     else
00214       report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
00215     return true;
00216   }
00217 }
00218 
00219 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
00220   if (lowerLongBranch(MI, OutMI))
00221     return;
00222 
00223   OutMI.setOpcode(MI->getOpcode());
00224 
00225   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
00226     const MachineOperand &MO = MI->getOperand(i);
00227     MCOperand MCOp = LowerOperand(MO);
00228 
00229     if (MCOp.isValid())
00230       OutMI.addOperand(MCOp);
00231   }
00232 }
00233