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_GOT_PC_HI: 51 Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20; 52 break; 53 case LoongArchII::MO_GOT_PC_LO: 54 Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12; 55 break; 56 case LoongArchII::MO_LE_HI: 57 Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 58 break; 59 case LoongArchII::MO_LE_LO: 60 Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12; 61 break; 62 case LoongArchII::MO_IE_PC_HI: 63 Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20; 64 break; 65 case LoongArchII::MO_IE_PC_LO: 66 Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 67 break; 68 case LoongArchII::MO_LD_PC_HI: 69 Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20; 70 break; 71 case LoongArchII::MO_GD_PC_HI: 72 Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 73 break; 74 // TODO: Handle more target-flags. 75 } 76 77 const MCExpr *ME = 78 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 79 80 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 81 ME = MCBinaryExpr::createAdd( 82 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 83 84 if (Kind != LoongArchMCExpr::VK_LoongArch_None) 85 ME = LoongArchMCExpr::create(ME, Kind, Ctx); 86 return MCOperand::createExpr(ME); 87 } 88 89 bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, 90 MCOperand &MCOp, 91 const AsmPrinter &AP) { 92 switch (MO.getType()) { 93 default: 94 report_fatal_error( 95 "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); 96 case MachineOperand::MO_Register: 97 // Ignore all implicit register operands. 98 if (MO.isImplicit()) 99 return false; 100 MCOp = MCOperand::createReg(MO.getReg()); 101 break; 102 case MachineOperand::MO_RegisterMask: 103 // Regmasks are like implicit defs. 104 return false; 105 case MachineOperand::MO_Immediate: 106 MCOp = MCOperand::createImm(MO.getImm()); 107 break; 108 case MachineOperand::MO_ConstantPoolIndex: 109 MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); 110 break; 111 case MachineOperand::MO_GlobalAddress: 112 MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); 113 break; 114 case MachineOperand::MO_MachineBasicBlock: 115 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); 116 break; 117 case MachineOperand::MO_ExternalSymbol: 118 MCOp = lowerSymbolOperand( 119 MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); 120 break; 121 case MachineOperand::MO_BlockAddress: 122 MCOp = lowerSymbolOperand( 123 MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 124 break; 125 case MachineOperand::MO_JumpTableIndex: 126 MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP); 127 break; 128 } 129 return true; 130 } 131 132 bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, 133 MCInst &OutMI, AsmPrinter &AP) { 134 OutMI.setOpcode(MI->getOpcode()); 135 136 for (const MachineOperand &MO : MI->operands()) { 137 MCOperand MCOp; 138 if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) 139 OutMI.addOperand(MCOp); 140 } 141 return false; 142 } 143