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