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 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 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 // Note: Offset can also be negative 165 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), 166 *Ctx); 167 } 168 169 if (IsGpOff) 170 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); 171 else if (TargetKind != MipsMCExpr::MEK_None) 172 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); 173 174 return MCOperand::createExpr(Expr); 175 } 176 177 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, 178 int64_t offset) const { 179 MachineOperandType MOTy = MO.getType(); 180 181 switch (MOTy) { 182 default: llvm_unreachable("unknown operand type"); 183 case MachineOperand::MO_Register: 184 // Ignore all implicit register operands. 185 if (MO.isImplicit()) break; 186 return MCOperand::createReg(MO.getReg()); 187 case MachineOperand::MO_Immediate: 188 return MCOperand::createImm(MO.getImm() + offset); 189 case MachineOperand::MO_MachineBasicBlock: 190 case MachineOperand::MO_GlobalAddress: 191 case MachineOperand::MO_ExternalSymbol: 192 case MachineOperand::MO_MCSymbol: 193 case MachineOperand::MO_JumpTableIndex: 194 case MachineOperand::MO_ConstantPoolIndex: 195 case MachineOperand::MO_BlockAddress: 196 return LowerSymbolOperand(MO, MOTy, offset); 197 case MachineOperand::MO_RegisterMask: 198 break; 199 } 200 201 return MCOperand(); 202 } 203 204 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, 205 MachineBasicBlock *BB2, 206 MipsMCExpr::MipsExprKind Kind) const { 207 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); 208 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); 209 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); 210 211 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); 212 } 213 214 void MipsMCInstLower:: 215 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { 216 OutMI.setOpcode(Mips::LUi); 217 218 // Lower register operand. 219 OutMI.addOperand(LowerOperand(MI->getOperand(0))); 220 221 MipsMCExpr::MipsExprKind Kind; 222 unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); 223 switch (TargetFlags) { 224 case MipsII::MO_HIGHEST: 225 Kind = MipsMCExpr::MEK_HIGHEST; 226 break; 227 case MipsII::MO_HIGHER: 228 Kind = MipsMCExpr::MEK_HIGHER; 229 break; 230 case MipsII::MO_ABS_HI: 231 Kind = MipsMCExpr::MEK_HI; 232 break; 233 case MipsII::MO_ABS_LO: 234 Kind = MipsMCExpr::MEK_LO; 235 break; 236 default: 237 report_fatal_error("Unexpected flags for lowerLongBranchLUi"); 238 } 239 240 if (MI->getNumOperands() == 2) { 241 const MCExpr *Expr = 242 MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); 243 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 244 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 245 } else if (MI->getNumOperands() == 3) { 246 // Create %hi($tgt-$baltgt). 247 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), 248 MI->getOperand(2).getMBB(), Kind)); 249 } 250 } 251 252 void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, 253 MCInst &OutMI, int Opcode) const { 254 OutMI.setOpcode(Opcode); 255 256 MipsMCExpr::MipsExprKind Kind; 257 unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); 258 switch (TargetFlags) { 259 case MipsII::MO_HIGHEST: 260 Kind = MipsMCExpr::MEK_HIGHEST; 261 break; 262 case MipsII::MO_HIGHER: 263 Kind = MipsMCExpr::MEK_HIGHER; 264 break; 265 case MipsII::MO_ABS_HI: 266 Kind = MipsMCExpr::MEK_HI; 267 break; 268 case MipsII::MO_ABS_LO: 269 Kind = MipsMCExpr::MEK_LO; 270 break; 271 default: 272 report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); 273 } 274 275 // Lower two register operands. 276 for (unsigned I = 0, E = 2; I != E; ++I) { 277 const MachineOperand &MO = MI->getOperand(I); 278 OutMI.addOperand(LowerOperand(MO)); 279 } 280 281 if (MI->getNumOperands() == 3) { 282 // Lower register operand. 283 const MCExpr *Expr = 284 MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); 285 const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); 286 OutMI.addOperand(MCOperand::createExpr(MipsExpr)); 287 } else if (MI->getNumOperands() == 4) { 288 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). 289 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), 290 MI->getOperand(3).getMBB(), Kind)); 291 } 292 } 293 294 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, 295 MCInst &OutMI) const { 296 switch (MI->getOpcode()) { 297 default: 298 return false; 299 case Mips::LONG_BRANCH_LUi: 300 case Mips::LONG_BRANCH_LUi2Op: 301 case Mips::LONG_BRANCH_LUi2Op_64: 302 lowerLongBranchLUi(MI, OutMI); 303 return true; 304 case Mips::LONG_BRANCH_ADDiu: 305 case Mips::LONG_BRANCH_ADDiu2Op: 306 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); 307 return true; 308 case Mips::LONG_BRANCH_DADDiu: 309 case Mips::LONG_BRANCH_DADDiu2Op: 310 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); 311 return true; 312 } 313 } 314 315 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 316 if (lowerLongBranch(MI, OutMI)) 317 return; 318 319 OutMI.setOpcode(MI->getOpcode()); 320 321 for (const MachineOperand &MO : MI->operands()) { 322 MCOperand MCOp = LowerOperand(MO); 323 324 if (MCOp.isValid()) 325 OutMI.addOperand(MCOp); 326 } 327 } 328