LLVM API Documentation
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