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