1//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains code to lower Mips MachineInstrs to their corresponding 11// MCInst records. 12// 13//===----------------------------------------------------------------------===// 14#include "MipsMCInstLower.h" 15#include "MCTargetDesc/MipsBaseInfo.h" 16#include "MipsAsmPrinter.h" 17#include "MipsInstrInfo.h" 18#include "llvm/CodeGen/MachineFunction.h" 19#include "llvm/CodeGen/MachineInstr.h" 20#include "llvm/CodeGen/MachineOperand.h" 21#include "llvm/IR/Mangler.h" 22#include "llvm/MC/MCContext.h" 23#include "llvm/MC/MCExpr.h" 24#include "llvm/MC/MCInst.h" 25 26using namespace llvm; 27 28MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) 29 : AsmPrinter(asmprinter) {} 30 31void MipsMCInstLower::Initialize(MCContext *C) { 32 Ctx = C; 33} 34 35MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 36 MachineOperandType MOTy, 37 unsigned Offset) const { 38 MCSymbolRefExpr::VariantKind Kind; 39 const MCSymbol *Symbol; 40 41 switch(MO.getTargetFlags()) { 42 default: llvm_unreachable("Invalid target flag!"); 43 case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; 44 case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; 45 case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; 46 case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; 47 case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; 48 case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; 49 case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; 50 case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; 51 case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; 52 case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; 53 case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; 54 case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; 55 case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; 56 case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; 57 case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; 58 case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; 59 case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; 60 case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; 61 case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; 62 case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break; 63 case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break; 64 case MipsII::MO_GOT_HI16: Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break; 65 case MipsII::MO_GOT_LO16: Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break; 66 case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break; 67 case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break; 68 } 69 70 switch (MOTy) { 71 case MachineOperand::MO_MachineBasicBlock: 72 Symbol = MO.getMBB()->getSymbol(); 73 break; 74 75 case MachineOperand::MO_GlobalAddress: 76 Symbol = AsmPrinter.getSymbol(MO.getGlobal()); 77 Offset += MO.getOffset(); 78 break; 79 80 case MachineOperand::MO_BlockAddress: 81 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 82 Offset += MO.getOffset(); 83 break; 84 85 case MachineOperand::MO_ExternalSymbol: 86 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 87 Offset += MO.getOffset(); 88 break; 89 90 case MachineOperand::MO_JumpTableIndex: 91 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 92 break; 93 94 case MachineOperand::MO_ConstantPoolIndex: 95 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 96 Offset += MO.getOffset(); 97 break; 98 99 default: 100 llvm_unreachable("<unknown operand type>"); 101 } 102 103 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx); 104 105 if (!Offset) 106 return MCOperand::CreateExpr(MCSym); 107 108 // Assume offset is never negative. 109 assert(Offset > 0); 110 111 const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, *Ctx); 112 const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx); 113 return MCOperand::CreateExpr(Add); 114} 115 116/* 117static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0, 118 const MCOperand &Opnd1, 119 const MCOperand &Opnd2 = MCOperand()) { 120 Inst.setOpcode(Opc); 121 Inst.addOperand(Opnd0); 122 Inst.addOperand(Opnd1); 123 if (Opnd2.isValid()) 124 Inst.addOperand(Opnd2); 125} 126*/ 127 128MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, 129 unsigned offset) const { 130 MachineOperandType MOTy = MO.getType(); 131 132 switch (MOTy) { 133 default: llvm_unreachable("unknown operand type"); 134 case MachineOperand::MO_Register: 135 // Ignore all implicit register operands. 136 if (MO.isImplicit()) break; 137 return MCOperand::CreateReg(MO.getReg()); 138 case MachineOperand::MO_Immediate: 139 return MCOperand::CreateImm(MO.getImm() + offset); 140 case MachineOperand::MO_MachineBasicBlock: 141 case MachineOperand::MO_GlobalAddress: 142 case MachineOperand::MO_ExternalSymbol: 143 case MachineOperand::MO_JumpTableIndex: 144 case MachineOperand::MO_ConstantPoolIndex: 145 case MachineOperand::MO_BlockAddress: 146 return LowerSymbolOperand(MO, MOTy, offset); 147 case MachineOperand::MO_RegisterMask: 148 break; 149 } 150 151 return MCOperand(); 152} 153 154MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, 155 MachineBasicBlock *BB2, 156 MCSymbolRefExpr::VariantKind Kind) const { 157 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx); 158 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx); 159 const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx); 160 161 return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx)); 162} 163 164void MipsMCInstLower:: 165lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { 166 OutMI.setOpcode(Mips::LUi); 167 168 // Lower register operand. 169 OutMI.addOperand(LowerOperand(MI->getOperand(0))); 170 171 // Create %hi($tgt-$baltgt). 172 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 173 MI->getOperand(2).getMBB(), 174 MCSymbolRefExpr::VK_Mips_ABS_HI)); 175} 176 177void MipsMCInstLower:: 178lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode, 179 MCSymbolRefExpr::VariantKind Kind) const { 180 OutMI.setOpcode(Opcode); 181 182 // Lower two register operands. 183 for (unsigned I = 0, E = 2; I != E; ++I) { 184 const MachineOperand &MO = MI->getOperand(I); 185 OutMI.addOperand(LowerOperand(MO)); 186 } 187 188 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 189 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 190 MI->getOperand(3).getMBB(), Kind)); 191} 192 193bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 194 MCInst &OutMI) const { 195 switch (MI->getOpcode()) { 196 default: 197 return false; 198 case Mips::LONG_BRANCH_LUi: 199 lowerLongBranchLUi(MI, OutMI); 200 return true; 201 case Mips::LONG_BRANCH_ADDiu: 202 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, 203 MCSymbolRefExpr::VK_Mips_ABS_LO); 204 return true; 205 case Mips::LONG_BRANCH_DADDiu: 206 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 207 if (TargetFlags == MipsII::MO_ABS_HI) 208 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, 209 MCSymbolRefExpr::VK_Mips_ABS_HI); 210 else if (TargetFlags == MipsII::MO_ABS_LO) 211 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, 212 MCSymbolRefExpr::VK_Mips_ABS_LO); 213 else 214 report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu"); 215 return true; 216 } 217} 218 219void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 220 if (lowerLongBranch(MI, OutMI)) 221 return; 222 223 OutMI.setOpcode(MI->getOpcode()); 224 225 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 226 const MachineOperand &MO = MI->getOperand(i); 227 MCOperand MCOp = LowerOperand(MO); 228 229 if (MCOp.isValid()) 230 OutMI.addOperand(MCOp); 231 } 232} 233 234