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 } 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 178 MCOperand 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 205 MCOperand 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 215 void MipsMCInstLower:: 216 lowerLongBranchLUi(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 MipsMCExpr::MipsExprKind Kind; 223 unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); 224 switch (TargetFlags) { 225 case MipsII::MO_HIGHEST: 226 Kind = MipsMCExpr::MEK_HIGHEST; 227 break; 228 case MipsII::MO_HIGHER: 229 Kind = MipsMCExpr::MEK_HIGHER; 230 break; 231 case MipsII::MO_ABS_HI: 232 Kind = MipsMCExpr::MEK_HI; 233 break; 234 case MipsII::MO_ABS_LO: 235 Kind = MipsMCExpr::MEK_LO; 236 break; 237 default: 238 report_fatal_error("Unexpected flags for lowerLongBranchLUi"); 239 } 240 241 if (MI->getNumOperands() == 2) { 242 const MCExpr *Expr = 243 MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); 244 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 245 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 246 } else if (MI->getNumOperands() == 3) { 247 // Create %hi($tgt-$baltgt). 248 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 249 MI->getOperand(2).getMBB(), Kind)); 250 } 251 } 252 253 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, 254 MCInst &OutMI, int Opcode) const { 255 OutMI.setOpcode(Opcode); 256 257 MipsMCExpr::MipsExprKind Kind; 258 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 259 switch (TargetFlags) { 260 case MipsII::MO_HIGHEST: 261 Kind = MipsMCExpr::MEK_HIGHEST; 262 break; 263 case MipsII::MO_HIGHER: 264 Kind = MipsMCExpr::MEK_HIGHER; 265 break; 266 case MipsII::MO_ABS_HI: 267 Kind = MipsMCExpr::MEK_HI; 268 break; 269 case MipsII::MO_ABS_LO: 270 Kind = MipsMCExpr::MEK_LO; 271 break; 272 default: 273 report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); 274 } 275 276 // Lower two register operands. 277 for (unsigned I = 0, E = 2; I != E; ++I) { 278 const MachineOperand &MO = MI->getOperand(I); 279 OutMI.addOperand(LowerOperand(MO)); 280 } 281 282 if (MI->getNumOperands() == 3) { 283 // Lower register operand. 284 const MCExpr *Expr = 285 MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); 286 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 287 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 288 } else if (MI->getNumOperands() == 4) { 289 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 290 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 291 MI->getOperand(3).getMBB(), Kind)); 292 } 293 } 294 295 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 296 MCInst &OutMI) const { 297 switch (MI->getOpcode()) { 298 default: 299 return false; 300 case Mips::LONG_BRANCH_LUi: 301 lowerLongBranchLUi(MI, OutMI); 302 return true; 303 case Mips::LONG_BRANCH_ADDiu: 304 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); 305 return true; 306 case Mips::LONG_BRANCH_DADDiu: 307 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); 308 return true; 309 } 310 } 311 312 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 313 if (lowerLongBranch(MI, OutMI)) 314 return; 315 316 OutMI.setOpcode(MI->getOpcode()); 317 318 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 319 const MachineOperand &MO = MI->getOperand(i); 320 MCOperand MCOp = LowerOperand(MO); 321 322 if (MCOp.isValid()) 323 OutMI.addOperand(MCOp); 324 } 325 } 326