1 //===- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains code to lower Mips MachineInstrs to their corresponding 10 // MCInst records. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MipsMCInstLower.h" 15 #include "MCTargetDesc/MipsBaseInfo.h" 16 #include "MCTargetDesc/MipsMCExpr.h" 17 #include "MipsAsmPrinter.h" 18 #include "llvm/CodeGen/MachineBasicBlock.h" 19 #include "llvm/CodeGen/MachineInstr.h" 20 #include "llvm/CodeGen/MachineOperand.h" 21 #include "llvm/MC/MCExpr.h" 22 #include "llvm/MC/MCInst.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include <cassert> 25 26 using namespace llvm; 27 28 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter) 29 : AsmPrinter(asmprinter) {} 30 31 void MipsMCInstLower::Initialize(MCContext *C) { 32 Ctx = C; 33 } 34 35 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 36 MachineOperandType MOTy, 37 unsigned Offset) const { 38 MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; 39 MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None; 40 bool IsGpOff = false; 41 const MCSymbol *Symbol; 42 43 switch(MO.getTargetFlags()) { 44 default: 45 llvm_unreachable("Invalid target flag!"); 46 case MipsII::MO_NO_FLAG: 47 break; 48 case MipsII::MO_GPREL: 49 TargetKind = MipsMCExpr::MEK_GPREL; 50 break; 51 case MipsII::MO_GOT_CALL: 52 TargetKind = MipsMCExpr::MEK_GOT_CALL; 53 break; 54 case MipsII::MO_GOT: 55 TargetKind = MipsMCExpr::MEK_GOT; 56 break; 57 case MipsII::MO_ABS_HI: 58 TargetKind = MipsMCExpr::MEK_HI; 59 break; 60 case MipsII::MO_ABS_LO: 61 TargetKind = MipsMCExpr::MEK_LO; 62 break; 63 case MipsII::MO_TLSGD: 64 TargetKind = MipsMCExpr::MEK_TLSGD; 65 break; 66 case MipsII::MO_TLSLDM: 67 TargetKind = MipsMCExpr::MEK_TLSLDM; 68 break; 69 case MipsII::MO_DTPREL_HI: 70 TargetKind = MipsMCExpr::MEK_DTPREL_HI; 71 break; 72 case MipsII::MO_DTPREL_LO: 73 TargetKind = MipsMCExpr::MEK_DTPREL_LO; 74 break; 75 case MipsII::MO_GOTTPREL: 76 TargetKind = MipsMCExpr::MEK_GOTTPREL; 77 break; 78 case MipsII::MO_TPREL_HI: 79 TargetKind = MipsMCExpr::MEK_TPREL_HI; 80 break; 81 case MipsII::MO_TPREL_LO: 82 TargetKind = MipsMCExpr::MEK_TPREL_LO; 83 break; 84 case MipsII::MO_GPOFF_HI: 85 TargetKind = MipsMCExpr::MEK_HI; 86 IsGpOff = true; 87 break; 88 case MipsII::MO_GPOFF_LO: 89 TargetKind = MipsMCExpr::MEK_LO; 90 IsGpOff = true; 91 break; 92 case MipsII::MO_GOT_DISP: 93 TargetKind = MipsMCExpr::MEK_GOT_DISP; 94 break; 95 case MipsII::MO_GOT_HI16: 96 TargetKind = MipsMCExpr::MEK_GOT_HI16; 97 break; 98 case MipsII::MO_GOT_LO16: 99 TargetKind = MipsMCExpr::MEK_GOT_LO16; 100 break; 101 case MipsII::MO_GOT_PAGE: 102 TargetKind = MipsMCExpr::MEK_GOT_PAGE; 103 break; 104 case MipsII::MO_GOT_OFST: 105 TargetKind = MipsMCExpr::MEK_GOT_OFST; 106 break; 107 case MipsII::MO_HIGHER: 108 TargetKind = MipsMCExpr::MEK_HIGHER; 109 break; 110 case MipsII::MO_HIGHEST: 111 TargetKind = MipsMCExpr::MEK_HIGHEST; 112 break; 113 case MipsII::MO_CALL_HI16: 114 TargetKind = MipsMCExpr::MEK_CALL_HI16; 115 break; 116 case MipsII::MO_CALL_LO16: 117 TargetKind = MipsMCExpr::MEK_CALL_LO16; 118 break; 119 case MipsII::MO_JALR: 120 return MCOperand(); 121 } 122 123 switch (MOTy) { 124 case MachineOperand::MO_MachineBasicBlock: 125 Symbol = MO.getMBB()->getSymbol(); 126 break; 127 128 case MachineOperand::MO_GlobalAddress: 129 Symbol = AsmPrinter.getSymbol(MO.getGlobal()); 130 Offset += MO.getOffset(); 131 break; 132 133 case MachineOperand::MO_BlockAddress: 134 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 135 Offset += MO.getOffset(); 136 break; 137 138 case MachineOperand::MO_ExternalSymbol: 139 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 140 Offset += MO.getOffset(); 141 break; 142 143 case MachineOperand::MO_MCSymbol: 144 Symbol = MO.getMCSymbol(); 145 Offset += MO.getOffset(); 146 break; 147 148 case MachineOperand::MO_JumpTableIndex: 149 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 150 break; 151 152 case MachineOperand::MO_ConstantPoolIndex: 153 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 154 Offset += MO.getOffset(); 155 break; 156 157 default: 158 llvm_unreachable("<unknown operand type>"); 159 } 160 161 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); 162 163 if (Offset) { 164 // Assume offset is never negative. 165 assert(Offset > 0); 166 167 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), 168 *Ctx); 169 } 170 171 if (IsGpOff) 172 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); 173 else if (TargetKind != MipsMCExpr::MEK_None) 174 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); 175 176 return MCOperand::createExpr(Expr); 177 } 178 179 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, 180 unsigned offset) const { 181 MachineOperandType MOTy = MO.getType(); 182 183 switch (MOTy) { 184 default: llvm_unreachable("unknown operand type"); 185 case MachineOperand::MO_Register: 186 // Ignore all implicit register operands. 187 if (MO.isImplicit()) break; 188 return MCOperand::createReg(MO.getReg()); 189 case MachineOperand::MO_Immediate: 190 return MCOperand::createImm(MO.getImm() + offset); 191 case MachineOperand::MO_MachineBasicBlock: 192 case MachineOperand::MO_GlobalAddress: 193 case MachineOperand::MO_ExternalSymbol: 194 case MachineOperand::MO_MCSymbol: 195 case MachineOperand::MO_JumpTableIndex: 196 case MachineOperand::MO_ConstantPoolIndex: 197 case MachineOperand::MO_BlockAddress: 198 return LowerSymbolOperand(MO, MOTy, offset); 199 case MachineOperand::MO_RegisterMask: 200 break; 201 } 202 203 return MCOperand(); 204 } 205 206 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, 207 MachineBasicBlock *BB2, 208 MipsMCExpr::MipsExprKind Kind) const { 209 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); 210 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); 211 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); 212 213 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); 214 } 215 216 void MipsMCInstLower:: 217 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { 218 OutMI.setOpcode(Mips::LUi); 219 220 // Lower register operand. 221 OutMI.addOperand(LowerOperand(MI->getOperand(0))); 222 223 MipsMCExpr::MipsExprKind Kind; 224 unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); 225 switch (TargetFlags) { 226 case MipsII::MO_HIGHEST: 227 Kind = MipsMCExpr::MEK_HIGHEST; 228 break; 229 case MipsII::MO_HIGHER: 230 Kind = MipsMCExpr::MEK_HIGHER; 231 break; 232 case MipsII::MO_ABS_HI: 233 Kind = MipsMCExpr::MEK_HI; 234 break; 235 case MipsII::MO_ABS_LO: 236 Kind = MipsMCExpr::MEK_LO; 237 break; 238 default: 239 report_fatal_error("Unexpected flags for lowerLongBranchLUi"); 240 } 241 242 if (MI->getNumOperands() == 2) { 243 const MCExpr *Expr = 244 MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); 245 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 246 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 247 } else if (MI->getNumOperands() == 3) { 248 // Create %hi($tgt-$baltgt). 249 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 250 MI->getOperand(2).getMBB(), Kind)); 251 } 252 } 253 254 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, 255 MCInst &OutMI, int Opcode) const { 256 OutMI.setOpcode(Opcode); 257 258 MipsMCExpr::MipsExprKind Kind; 259 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 260 switch (TargetFlags) { 261 case MipsII::MO_HIGHEST: 262 Kind = MipsMCExpr::MEK_HIGHEST; 263 break; 264 case MipsII::MO_HIGHER: 265 Kind = MipsMCExpr::MEK_HIGHER; 266 break; 267 case MipsII::MO_ABS_HI: 268 Kind = MipsMCExpr::MEK_HI; 269 break; 270 case MipsII::MO_ABS_LO: 271 Kind = MipsMCExpr::MEK_LO; 272 break; 273 default: 274 report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); 275 } 276 277 // Lower two register operands. 278 for (unsigned I = 0, E = 2; I != E; ++I) { 279 const MachineOperand &MO = MI->getOperand(I); 280 OutMI.addOperand(LowerOperand(MO)); 281 } 282 283 if (MI->getNumOperands() == 3) { 284 // Lower register operand. 285 const MCExpr *Expr = 286 MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); 287 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 288 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 289 } else if (MI->getNumOperands() == 4) { 290 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 291 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 292 MI->getOperand(3).getMBB(), Kind)); 293 } 294 } 295 296 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 297 MCInst &OutMI) const { 298 switch (MI->getOpcode()) { 299 default: 300 return false; 301 case Mips::LONG_BRANCH_LUi: 302 case Mips::LONG_BRANCH_LUi2Op: 303 case Mips::LONG_BRANCH_LUi2Op_64: 304 lowerLongBranchLUi(MI, OutMI); 305 return true; 306 case Mips::LONG_BRANCH_ADDiu: 307 case Mips::LONG_BRANCH_ADDiu2Op: 308 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); 309 return true; 310 case Mips::LONG_BRANCH_DADDiu: 311 case Mips::LONG_BRANCH_DADDiu2Op: 312 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); 313 return true; 314 } 315 } 316 317 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 318 if (lowerLongBranch(MI, OutMI)) 319 return; 320 321 OutMI.setOpcode(MI->getOpcode()); 322 323 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 324 const MachineOperand &MO = MI->getOperand(i); 325 MCOperand MCOp = LowerOperand(MO); 326 327 if (MCOp.isValid()) 328 OutMI.addOperand(MCOp); 329 } 330 } 331