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