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