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#include "llvm/MC/MCStreamer.h" 26 27using namespace llvm; 28 29MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) 30 : AsmPrinter(asmprinter) {} 31 32void MipsMCInstLower::Initialize(MCContext *C) { 33 Ctx = C; 34} 35 36MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 37 MachineOperandType MOTy, 38 unsigned Offset) const { 39 MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; 40 MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None; 41 bool IsGpOff = false; 42 const MCSymbol *Symbol; 43 44 switch(MO.getTargetFlags()) { 45 default: 46 llvm_unreachable("Invalid target flag!"); 47 case MipsII::MO_NO_FLAG: 48 break; 49 case MipsII::MO_GPREL: 50 TargetKind = MipsMCExpr::MEK_GPREL; 51 break; 52 case MipsII::MO_GOT_CALL: 53 TargetKind = MipsMCExpr::MEK_GOT_CALL; 54 break; 55 case MipsII::MO_GOT: 56 TargetKind = MipsMCExpr::MEK_GOT; 57 break; 58 case MipsII::MO_ABS_HI: 59 TargetKind = MipsMCExpr::MEK_HI; 60 break; 61 case MipsII::MO_ABS_LO: 62 TargetKind = MipsMCExpr::MEK_LO; 63 break; 64 case MipsII::MO_TLSGD: 65 TargetKind = MipsMCExpr::MEK_TLSGD; 66 break; 67 case MipsII::MO_TLSLDM: 68 TargetKind = MipsMCExpr::MEK_TLSLDM; 69 break; 70 case MipsII::MO_DTPREL_HI: 71 TargetKind = MipsMCExpr::MEK_DTPREL_HI; 72 break; 73 case MipsII::MO_DTPREL_LO: 74 TargetKind = MipsMCExpr::MEK_DTPREL_LO; 75 break; 76 case MipsII::MO_GOTTPREL: 77 TargetKind = MipsMCExpr::MEK_GOTTPREL; 78 break; 79 case MipsII::MO_TPREL_HI: 80 TargetKind = MipsMCExpr::MEK_TPREL_HI; 81 break; 82 case MipsII::MO_TPREL_LO: 83 TargetKind = MipsMCExpr::MEK_TPREL_LO; 84 break; 85 case MipsII::MO_GPOFF_HI: 86 TargetKind = MipsMCExpr::MEK_HI; 87 IsGpOff = true; 88 break; 89 case MipsII::MO_GPOFF_LO: 90 TargetKind = MipsMCExpr::MEK_LO; 91 IsGpOff = true; 92 break; 93 case MipsII::MO_GOT_DISP: 94 TargetKind = MipsMCExpr::MEK_GOT_DISP; 95 break; 96 case MipsII::MO_GOT_HI16: 97 TargetKind = MipsMCExpr::MEK_GOT_HI16; 98 break; 99 case MipsII::MO_GOT_LO16: 100 TargetKind = MipsMCExpr::MEK_GOT_LO16; 101 break; 102 case MipsII::MO_GOT_PAGE: 103 TargetKind = MipsMCExpr::MEK_GOT_PAGE; 104 break; 105 case MipsII::MO_GOT_OFST: 106 TargetKind = MipsMCExpr::MEK_GOT_OFST; 107 break; 108 case MipsII::MO_HIGHER: 109 TargetKind = MipsMCExpr::MEK_HIGHER; 110 break; 111 case MipsII::MO_HIGHEST: 112 TargetKind = MipsMCExpr::MEK_HIGHEST; 113 break; 114 case MipsII::MO_CALL_HI16: 115 TargetKind = MipsMCExpr::MEK_CALL_HI16; 116 break; 117 case MipsII::MO_CALL_LO16: 118 TargetKind = MipsMCExpr::MEK_CALL_LO16; 119 break; 120 } 121 122 switch (MOTy) { 123 case MachineOperand::MO_MachineBasicBlock: 124 Symbol = MO.getMBB()->getSymbol(); 125 break; 126 127 case MachineOperand::MO_GlobalAddress: 128 Symbol = AsmPrinter.getSymbol(MO.getGlobal()); 129 Offset += MO.getOffset(); 130 break; 131 132 case MachineOperand::MO_BlockAddress: 133 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 134 Offset += MO.getOffset(); 135 break; 136 137 case MachineOperand::MO_ExternalSymbol: 138 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 139 Offset += MO.getOffset(); 140 break; 141 142 case MachineOperand::MO_MCSymbol: 143 Symbol = MO.getMCSymbol(); 144 Offset += MO.getOffset(); 145 break; 146 147 case MachineOperand::MO_JumpTableIndex: 148 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 149 break; 150 151 case MachineOperand::MO_ConstantPoolIndex: 152 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 153 Offset += MO.getOffset(); 154 break; 155 156 default: 157 llvm_unreachable("<unknown operand type>"); 158 } 159 160 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); 161 162 if (Offset) { 163 // Assume offset is never negative. 164 assert(Offset > 0); 165 166 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), 167 *Ctx); 168 } 169 170 if (IsGpOff) 171 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); 172 else if (TargetKind != MipsMCExpr::MEK_None) 173 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); 174 175 return MCOperand::createExpr(Expr); 176} 177 178MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, 179 unsigned offset) const { 180 MachineOperandType MOTy = MO.getType(); 181 182 switch (MOTy) { 183 default: llvm_unreachable("unknown operand type"); 184 case MachineOperand::MO_Register: 185 // Ignore all implicit register operands. 186 if (MO.isImplicit()) break; 187 return MCOperand::createReg(MO.getReg()); 188 case MachineOperand::MO_Immediate: 189 return MCOperand::createImm(MO.getImm() + offset); 190 case MachineOperand::MO_MachineBasicBlock: 191 case MachineOperand::MO_GlobalAddress: 192 case MachineOperand::MO_ExternalSymbol: 193 case MachineOperand::MO_MCSymbol: 194 case MachineOperand::MO_JumpTableIndex: 195 case MachineOperand::MO_ConstantPoolIndex: 196 case MachineOperand::MO_BlockAddress: 197 return LowerSymbolOperand(MO, MOTy, offset); 198 case MachineOperand::MO_RegisterMask: 199 break; 200 } 201 202 return MCOperand(); 203} 204 205MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, 206 MachineBasicBlock *BB2, 207 MipsMCExpr::MipsExprKind Kind) const { 208 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); 209 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); 210 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); 211 212 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); 213} 214 215void MipsMCInstLower:: 216lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { 217 OutMI.setOpcode(Mips::LUi); 218 219 // Lower register operand. 220 OutMI.addOperand(LowerOperand(MI->getOperand(0))); 221 222 // Create %hi($tgt-$baltgt). 223 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 224 MI->getOperand(2).getMBB(), 225 MipsMCExpr::MEK_HI)); 226} 227 228void MipsMCInstLower::lowerLongBranchADDiu( 229 const MachineInstr *MI, MCInst &OutMI, int Opcode, 230 MipsMCExpr::MipsExprKind Kind) const { 231 OutMI.setOpcode(Opcode); 232 233 // Lower two register operands. 234 for (unsigned I = 0, E = 2; I != E; ++I) { 235 const MachineOperand &MO = MI->getOperand(I); 236 OutMI.addOperand(LowerOperand(MO)); 237 } 238 239 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 240 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 241 MI->getOperand(3).getMBB(), Kind)); 242} 243 244bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 245 MCInst &OutMI) const { 246 switch (MI->getOpcode()) { 247 default: 248 return false; 249 case Mips::LONG_BRANCH_LUi: 250 lowerLongBranchLUi(MI, OutMI); 251 return true; 252 case Mips::LONG_BRANCH_ADDiu: 253 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO); 254 return true; 255 case Mips::LONG_BRANCH_DADDiu: 256 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 257 if (TargetFlags == MipsII::MO_ABS_HI) 258 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI); 259 else if (TargetFlags == MipsII::MO_ABS_LO) 260 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO); 261 else 262 report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu"); 263 return true; 264 } 265} 266 267void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 268 if (lowerLongBranch(MI, OutMI)) 269 return; 270 271 OutMI.setOpcode(MI->getOpcode()); 272 273 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 274 const MachineOperand &MO = MI->getOperand(i); 275 MCOperand MCOp = LowerOperand(MO); 276 277 if (MCOp.isValid()) 278 OutMI.addOperand(MCOp); 279 } 280} 281 282