181ad6265SDimitry Andric //=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file contains code to lower LoongArch MachineInstrs to their 1081ad6265SDimitry Andric // corresponding MCInst records. 1181ad6265SDimitry Andric // 1281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1381ad6265SDimitry Andric 1481ad6265SDimitry Andric #include "LoongArch.h" 1581ad6265SDimitry Andric #include "LoongArchSubtarget.h" 16*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h" 17*bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchMCExpr.h" 1881ad6265SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 2181ad6265SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 2281ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 2381ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric using namespace llvm; 2681ad6265SDimitry Andric 27753f127fSDimitry Andric static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, 28753f127fSDimitry Andric const AsmPrinter &AP) { 29753f127fSDimitry Andric MCContext &Ctx = AP.OutContext; 30*bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind Kind; 31753f127fSDimitry Andric 32*bdd1243dSDimitry Andric switch (MO.getTargetFlags()) { 33*bdd1243dSDimitry Andric default: 34*bdd1243dSDimitry Andric llvm_unreachable("Unknown target flag on GV operand"); 35*bdd1243dSDimitry Andric case LoongArchII::MO_None: 36*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_None; 37*bdd1243dSDimitry Andric break; 38*bdd1243dSDimitry Andric case LoongArchII::MO_CALL: 39*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_CALL; 40*bdd1243dSDimitry Andric break; 41*bdd1243dSDimitry Andric case LoongArchII::MO_CALL_PLT: 42*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT; 43*bdd1243dSDimitry Andric break; 44*bdd1243dSDimitry Andric case LoongArchII::MO_PCREL_HI: 45*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20; 46*bdd1243dSDimitry Andric break; 47*bdd1243dSDimitry Andric case LoongArchII::MO_PCREL_LO: 48*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12; 49*bdd1243dSDimitry Andric break; 50*bdd1243dSDimitry Andric case LoongArchII::MO_GOT_PC_HI: 51*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20; 52*bdd1243dSDimitry Andric break; 53*bdd1243dSDimitry Andric case LoongArchII::MO_GOT_PC_LO: 54*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12; 55*bdd1243dSDimitry Andric break; 56*bdd1243dSDimitry Andric case LoongArchII::MO_LE_HI: 57*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20; 58*bdd1243dSDimitry Andric break; 59*bdd1243dSDimitry Andric case LoongArchII::MO_LE_LO: 60*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12; 61*bdd1243dSDimitry Andric break; 62*bdd1243dSDimitry Andric case LoongArchII::MO_IE_PC_HI: 63*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20; 64*bdd1243dSDimitry Andric break; 65*bdd1243dSDimitry Andric case LoongArchII::MO_IE_PC_LO: 66*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12; 67*bdd1243dSDimitry Andric break; 68*bdd1243dSDimitry Andric case LoongArchII::MO_LD_PC_HI: 69*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20; 70*bdd1243dSDimitry Andric break; 71*bdd1243dSDimitry Andric case LoongArchII::MO_GD_PC_HI: 72*bdd1243dSDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20; 73*bdd1243dSDimitry Andric break; 74*bdd1243dSDimitry Andric // TODO: Handle more target-flags. 75*bdd1243dSDimitry Andric } 76753f127fSDimitry Andric 77753f127fSDimitry Andric const MCExpr *ME = 78753f127fSDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 79753f127fSDimitry Andric 80753f127fSDimitry Andric if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 81753f127fSDimitry Andric ME = MCBinaryExpr::createAdd( 82753f127fSDimitry Andric ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 83753f127fSDimitry Andric 84*bdd1243dSDimitry Andric if (Kind != LoongArchMCExpr::VK_LoongArch_None) 85*bdd1243dSDimitry Andric ME = LoongArchMCExpr::create(ME, Kind, Ctx); 86753f127fSDimitry Andric return MCOperand::createExpr(ME); 87753f127fSDimitry Andric } 88753f127fSDimitry Andric 8981ad6265SDimitry Andric bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, 9081ad6265SDimitry Andric MCOperand &MCOp, 9181ad6265SDimitry Andric const AsmPrinter &AP) { 9281ad6265SDimitry Andric switch (MO.getType()) { 9381ad6265SDimitry Andric default: 9481ad6265SDimitry Andric report_fatal_error( 9581ad6265SDimitry Andric "lowerLoongArchMachineOperandToMCOperand: unknown operand type"); 9681ad6265SDimitry Andric case MachineOperand::MO_Register: 9781ad6265SDimitry Andric // Ignore all implicit register operands. 9881ad6265SDimitry Andric if (MO.isImplicit()) 9981ad6265SDimitry Andric return false; 10081ad6265SDimitry Andric MCOp = MCOperand::createReg(MO.getReg()); 10181ad6265SDimitry Andric break; 10281ad6265SDimitry Andric case MachineOperand::MO_RegisterMask: 10381ad6265SDimitry Andric // Regmasks are like implicit defs. 10481ad6265SDimitry Andric return false; 10581ad6265SDimitry Andric case MachineOperand::MO_Immediate: 10681ad6265SDimitry Andric MCOp = MCOperand::createImm(MO.getImm()); 10781ad6265SDimitry Andric break; 10881ad6265SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 109753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); 110753f127fSDimitry Andric break; 111753f127fSDimitry Andric case MachineOperand::MO_GlobalAddress: 112753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); 113753f127fSDimitry Andric break; 114753f127fSDimitry Andric case MachineOperand::MO_MachineBasicBlock: 115753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP); 116753f127fSDimitry Andric break; 117753f127fSDimitry Andric case MachineOperand::MO_ExternalSymbol: 118753f127fSDimitry Andric MCOp = lowerSymbolOperand( 119753f127fSDimitry Andric MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); 120753f127fSDimitry Andric break; 121753f127fSDimitry Andric case MachineOperand::MO_BlockAddress: 122*bdd1243dSDimitry Andric MCOp = lowerSymbolOperand( 123*bdd1243dSDimitry Andric MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP); 124*bdd1243dSDimitry Andric break; 12581ad6265SDimitry Andric case MachineOperand::MO_JumpTableIndex: 126*bdd1243dSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP); 12781ad6265SDimitry Andric break; 12881ad6265SDimitry Andric } 12981ad6265SDimitry Andric return true; 13081ad6265SDimitry Andric } 13181ad6265SDimitry Andric 13281ad6265SDimitry Andric bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, 13381ad6265SDimitry Andric MCInst &OutMI, AsmPrinter &AP) { 13481ad6265SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 13581ad6265SDimitry Andric 13681ad6265SDimitry Andric for (const MachineOperand &MO : MI->operands()) { 13781ad6265SDimitry Andric MCOperand MCOp; 13881ad6265SDimitry Andric if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP)) 13981ad6265SDimitry Andric OutMI.addOperand(MCOp); 14081ad6265SDimitry Andric } 14181ad6265SDimitry Andric return false; 14281ad6265SDimitry Andric } 143