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 15 #include "MipsMCInstLower.h" 16 #include "MCTargetDesc/MipsBaseInfo.h" 17 #include "MCTargetDesc/MipsMCExpr.h" 18 #include "MipsAsmPrinter.h" 19 #include "llvm/CodeGen/MachineBasicBlock.h" 20 #include "llvm/CodeGen/MachineInstr.h" 21 #include "llvm/CodeGen/MachineOperand.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include <cassert> 26 27 using namespace llvm; 28 29 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) 30 : AsmPrinter(asmprinter) {} 31 32 void MipsMCInstLower::Initialize(MCContext *C) { 33 Ctx = C; 34 } 35 36 MCOperand 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 case MipsII::MO_JALR: 121 return MCOperand(); 122 } 123 124 switch (MOTy) { 125 case MachineOperand::MO_MachineBasicBlock: 126 Symbol = MO.getMBB()->getSymbol(); 127 break; 128 129 case MachineOperand::MO_GlobalAddress: 130 Symbol = AsmPrinter.getSymbol(MO.getGlobal()); 131 Offset += MO.getOffset(); 132 break; 133 134 case MachineOperand::MO_BlockAddress: 135 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 136 Offset += MO.getOffset(); 137 break; 138 139 case MachineOperand::MO_ExternalSymbol: 140 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 141 Offset += MO.getOffset(); 142 break; 143 144 case MachineOperand::MO_MCSymbol: 145 Symbol = MO.getMCSymbol(); 146 Offset += MO.getOffset(); 147 break; 148 149 case MachineOperand::MO_JumpTableIndex: 150 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 151 break; 152 153 case MachineOperand::MO_ConstantPoolIndex: 154 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 155 Offset += MO.getOffset(); 156 break; 157 158 default: 159 llvm_unreachable("<unknown operand type>"); 160 } 161 162 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); 163 164 if (Offset) { 165 // Assume offset is never negative. 166 assert(Offset > 0); 167 168 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), 169 *Ctx); 170 } 171 172 if (IsGpOff) 173 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); 174 else if (TargetKind != MipsMCExpr::MEK_None) 175 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); 176 177 return MCOperand::createExpr(Expr); 178 } 179 180 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, 181 unsigned offset) const { 182 MachineOperandType MOTy = MO.getType(); 183 184 switch (MOTy) { 185 default: llvm_unreachable("unknown operand type"); 186 case MachineOperand::MO_Register: 187 // Ignore all implicit register operands. 188 if (MO.isImplicit()) break; 189 return MCOperand::createReg(MO.getReg()); 190 case MachineOperand::MO_Immediate: 191 return MCOperand::createImm(MO.getImm() + offset); 192 case MachineOperand::MO_MachineBasicBlock: 193 case MachineOperand::MO_GlobalAddress: 194 case MachineOperand::MO_ExternalSymbol: 195 case MachineOperand::MO_MCSymbol: 196 case MachineOperand::MO_JumpTableIndex: 197 case MachineOperand::MO_ConstantPoolIndex: 198 case MachineOperand::MO_BlockAddress: 199 return LowerSymbolOperand(MO, MOTy, offset); 200 case MachineOperand::MO_RegisterMask: 201 break; 202 } 203 204 return MCOperand(); 205 } 206 207 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, 208 MachineBasicBlock *BB2, 209 MipsMCExpr::MipsExprKind Kind) const { 210 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); 211 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); 212 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); 213 214 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); 215 } 216 217 void MipsMCInstLower:: 218 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { 219 OutMI.setOpcode(Mips::LUi); 220 221 // Lower register operand. 222 OutMI.addOperand(LowerOperand(MI->getOperand(0))); 223 224 MipsMCExpr::MipsExprKind Kind; 225 unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); 226 switch (TargetFlags) { 227 case MipsII::MO_HIGHEST: 228 Kind = MipsMCExpr::MEK_HIGHEST; 229 break; 230 case MipsII::MO_HIGHER: 231 Kind = MipsMCExpr::MEK_HIGHER; 232 break; 233 case MipsII::MO_ABS_HI: 234 Kind = MipsMCExpr::MEK_HI; 235 break; 236 case MipsII::MO_ABS_LO: 237 Kind = MipsMCExpr::MEK_LO; 238 break; 239 default: 240 report_fatal_error("Unexpected flags for lowerLongBranchLUi"); 241 } 242 243 if (MI->getNumOperands() == 2) { 244 const MCExpr *Expr = 245 MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); 246 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 247 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 248 } else if (MI->getNumOperands() == 3) { 249 // Create %hi($tgt-$baltgt). 250 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 251 MI->getOperand(2).getMBB(), Kind)); 252 } 253 } 254 255 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, 256 MCInst &OutMI, int Opcode) const { 257 OutMI.setOpcode(Opcode); 258 259 MipsMCExpr::MipsExprKind Kind; 260 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 261 switch (TargetFlags) { 262 case MipsII::MO_HIGHEST: 263 Kind = MipsMCExpr::MEK_HIGHEST; 264 break; 265 case MipsII::MO_HIGHER: 266 Kind = MipsMCExpr::MEK_HIGHER; 267 break; 268 case MipsII::MO_ABS_HI: 269 Kind = MipsMCExpr::MEK_HI; 270 break; 271 case MipsII::MO_ABS_LO: 272 Kind = MipsMCExpr::MEK_LO; 273 break; 274 default: 275 report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); 276 } 277 278 // Lower two register operands. 279 for (unsigned I = 0, E = 2; I != E; ++I) { 280 const MachineOperand &MO = MI->getOperand(I); 281 OutMI.addOperand(LowerOperand(MO)); 282 } 283 284 if (MI->getNumOperands() == 3) { 285 // Lower register operand. 286 const MCExpr *Expr = 287 MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); 288 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 289 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 290 } else if (MI->getNumOperands() == 4) { 291 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 292 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 293 MI->getOperand(3).getMBB(), Kind)); 294 } 295 } 296 297 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 298 MCInst &OutMI) const { 299 switch (MI->getOpcode()) { 300 default: 301 return false; 302 case Mips::LONG_BRANCH_LUi: 303 case Mips::LONG_BRANCH_LUi2Op: 304 case Mips::LONG_BRANCH_LUi2Op_64: 305 lowerLongBranchLUi(MI, OutMI); 306 return true; 307 case Mips::LONG_BRANCH_ADDiu: 308 case Mips::LONG_BRANCH_ADDiu2Op: 309 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); 310 return true; 311 case Mips::LONG_BRANCH_DADDiu: 312 case Mips::LONG_BRANCH_DADDiu2Op: 313 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); 314 return true; 315 } 316 } 317 318 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 319 if (lowerLongBranch(MI, OutMI)) 320 return; 321 322 OutMI.setOpcode(MI->getOpcode()); 323 324 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 325 const MachineOperand &MO = MI->getOperand(i); 326 MCOperand MCOp = LowerOperand(MO); 327 328 if (MCOp.isValid()) 329 OutMI.addOperand(MCOp); 330 } 331 } 332