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 // TODO: Handle more target-flags. 99 } 100 101 const MCExpr *ME = 102 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 103 104 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 105 ME = MCBinaryExpr::createAdd( 106 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 107 108 if (Kind != LoongArchMCExpr::VK_LoongArch_None) 109 ME = LoongArchMCExpr::create(ME, Kind, Ctx); 110 return MCOperand::createExpr(ME); 111 } 112 113 bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, 114 MCOperand &MCOp, 115 const AsmPrinter &AP) { 116 switch (MO.getType()) { 117 default: 118 report_fatal_error( 119 "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); 120 case MachineOperand::MO_Register: 121 // Ignore all implicit register operands. 122 if (MO.isImplicit()) 123 return false; 124 MCOp = MCOperand::createReg(MO.getReg()); 125 break; 126 case MachineOperand::MO_RegisterMask: 127 // Regmasks are like implicit defs. 128 return false; 129 case MachineOperand::MO_Immediate: 130 MCOp = MCOperand::createImm(MO.getImm()); 131 break; 132 case MachineOperand::MO_ConstantPoolIndex: 133 MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); 134 break; 135 case MachineOperand::MO_GlobalAddress: 136 MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); 137 break; 138 case MachineOperand::MO_MachineBasicBlock: 139 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); 140 break; 141 case MachineOperand::MO_ExternalSymbol: 142 MCOp = lowerSymbolOperand( 143 MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); 144 break; 145 case MachineOperand::MO_BlockAddress: 146 MCOp = lowerSymbolOperand( 147 MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 148 break; 149 case MachineOperand::MO_JumpTableIndex: 150 MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP); 151 break; 152 } 153 return true; 154 } 155 156 bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, 157 MCInst &OutMI, AsmPrinter &AP) { 158 OutMI.setOpcode(MI->getOpcode()); 159 160 for (const MachineOperand &MO : MI->operands()) { 161 MCOperand MCOp; 162 if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) 163 OutMI.addOperand(MCOp); 164 } 165 return false; 166 } 167