193 lines · cpp
1//=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an 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 LoongArch MachineInstrs to their10// corresponding MCInst records.11//12//===----------------------------------------------------------------------===//13 14#include "LoongArch.h"15#include "MCTargetDesc/LoongArchBaseInfo.h"16#include "MCTargetDesc/LoongArchMCAsmInfo.h"17#include "llvm/BinaryFormat/ELF.h"18#include "llvm/CodeGen/AsmPrinter.h"19#include "llvm/CodeGen/MachineBasicBlock.h"20#include "llvm/CodeGen/MachineInstr.h"21#include "llvm/MC/MCAsmInfo.h"22#include "llvm/MC/MCContext.h"23 24using namespace llvm;25 26static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,27 const AsmPrinter &AP) {28 MCContext &Ctx = AP.OutContext;29 uint16_t Kind = 0;30 31 switch (LoongArchII::getDirectFlags(MO)) {32 default:33 llvm_unreachable("Unknown target flag on GV operand");34 case LoongArchII::MO_None:35 Kind = LoongArchMCExpr::VK_None;36 break;37 case LoongArchII::MO_CALL:38 case LoongArchII::MO_CALL_PLT:39 Kind = ELF::R_LARCH_B26;40 break;41 case LoongArchII::MO_PCREL_HI:42 Kind = ELF::R_LARCH_PCALA_HI20;43 break;44 case LoongArchII::MO_PCREL_LO:45 Kind = ELF::R_LARCH_PCALA_LO12;46 break;47 case LoongArchII::MO_PCREL64_LO:48 Kind = ELF::R_LARCH_PCALA64_LO20;49 break;50 case LoongArchII::MO_PCREL64_HI:51 Kind = ELF::R_LARCH_PCALA64_HI12;52 break;53 case LoongArchII::MO_GOT_PC_HI:54 Kind = ELF::R_LARCH_GOT_PC_HI20;55 break;56 case LoongArchII::MO_GOT_PC_LO:57 Kind = ELF::R_LARCH_GOT_PC_LO12;58 break;59 case LoongArchII::MO_GOT_PC64_LO:60 Kind = ELF::R_LARCH_GOT64_PC_LO20;61 break;62 case LoongArchII::MO_GOT_PC64_HI:63 Kind = ELF::R_LARCH_GOT64_PC_HI12;64 break;65 case LoongArchII::MO_LE_HI:66 Kind = ELF::R_LARCH_TLS_LE_HI20;67 break;68 case LoongArchII::MO_LE_LO:69 Kind = ELF::R_LARCH_TLS_LE_LO12;70 break;71 case LoongArchII::MO_LE64_LO:72 Kind = ELF::R_LARCH_TLS_LE64_LO20;73 break;74 case LoongArchII::MO_LE64_HI:75 Kind = ELF::R_LARCH_TLS_LE64_HI12;76 break;77 case LoongArchII::MO_IE_PC_HI:78 Kind = ELF::R_LARCH_TLS_IE_PC_HI20;79 break;80 case LoongArchII::MO_IE_PC_LO:81 Kind = ELF::R_LARCH_TLS_IE_PC_LO12;82 break;83 case LoongArchII::MO_IE_PC64_LO:84 Kind = ELF::R_LARCH_TLS_IE64_PC_LO20;85 break;86 case LoongArchII::MO_IE_PC64_HI:87 Kind = ELF::R_LARCH_TLS_IE64_PC_HI12;88 break;89 case LoongArchII::MO_LD_PC_HI:90 Kind = ELF::R_LARCH_TLS_LD_PC_HI20;91 break;92 case LoongArchII::MO_GD_PC_HI:93 Kind = ELF::R_LARCH_TLS_GD_PC_HI20;94 break;95 case LoongArchII::MO_CALL36:96 Kind = ELF::R_LARCH_CALL36;97 break;98 case LoongArchII::MO_DESC_PC_HI:99 Kind = ELF::R_LARCH_TLS_DESC_PC_HI20;100 break;101 case LoongArchII::MO_DESC_PC_LO:102 Kind = ELF::R_LARCH_TLS_DESC_PC_LO12;103 break;104 case LoongArchII::MO_DESC64_PC_LO:105 Kind = ELF::R_LARCH_TLS_DESC64_PC_LO20;106 break;107 case LoongArchII::MO_DESC64_PC_HI:108 Kind = ELF::R_LARCH_TLS_DESC64_PC_HI12;109 break;110 case LoongArchII::MO_DESC_LD:111 Kind = ELF::R_LARCH_TLS_DESC_LD;112 break;113 case LoongArchII::MO_DESC_CALL:114 Kind = ELF::R_LARCH_TLS_DESC_CALL;115 break;116 case LoongArchII::MO_LE_HI_R:117 Kind = ELF::R_LARCH_TLS_LE_HI20_R;118 break;119 case LoongArchII::MO_LE_ADD_R:120 Kind = ELF::R_LARCH_TLS_LE_ADD_R;121 break;122 case LoongArchII::MO_LE_LO_R:123 Kind = ELF::R_LARCH_TLS_LE_LO12_R;124 break;125 // TODO: Handle more target-flags.126 }127 128 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);129 130 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())131 ME = MCBinaryExpr::createAdd(132 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);133 134 if (Kind != LoongArchMCExpr::VK_None)135 ME = LoongArchMCExpr::create(ME, Kind, Ctx, LoongArchII::hasRelaxFlag(MO));136 return MCOperand::createExpr(ME);137}138 139bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,140 MCOperand &MCOp,141 const AsmPrinter &AP) {142 switch (MO.getType()) {143 default:144 report_fatal_error(145 "lowerLoongArchMachineOperandToMCOperand: unknown operand type");146 case MachineOperand::MO_Register:147 // Ignore all implicit register operands.148 if (MO.isImplicit())149 return false;150 MCOp = MCOperand::createReg(MO.getReg());151 break;152 case MachineOperand::MO_RegisterMask:153 // Regmasks are like implicit defs.154 return false;155 case MachineOperand::MO_Immediate:156 MCOp = MCOperand::createImm(MO.getImm());157 break;158 case MachineOperand::MO_ConstantPoolIndex:159 MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);160 break;161 case MachineOperand::MO_GlobalAddress:162 MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);163 break;164 case MachineOperand::MO_MachineBasicBlock:165 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);166 break;167 case MachineOperand::MO_ExternalSymbol:168 MCOp = lowerSymbolOperand(169 MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);170 break;171 case MachineOperand::MO_BlockAddress:172 MCOp = lowerSymbolOperand(173 MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);174 break;175 case MachineOperand::MO_JumpTableIndex:176 MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);177 break;178 }179 return true;180}181 182bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,183 MCInst &OutMI, AsmPrinter &AP) {184 OutMI.setOpcode(MI->getOpcode());185 186 for (const MachineOperand &MO : MI->operands()) {187 MCOperand MCOp;188 if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))189 OutMI.addOperand(MCOp);190 }191 return false;192}193