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