xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
16bdd1243dSDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h"
17bdd1243dSDimitry 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;
30bdd1243dSDimitry Andric   LoongArchMCExpr::VariantKind Kind;
31753f127fSDimitry Andric 
32bdd1243dSDimitry Andric   switch (MO.getTargetFlags()) {
33bdd1243dSDimitry Andric   default:
34bdd1243dSDimitry Andric     llvm_unreachable("Unknown target flag on GV operand");
35bdd1243dSDimitry Andric   case LoongArchII::MO_None:
36bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_None;
37bdd1243dSDimitry Andric     break;
38bdd1243dSDimitry Andric   case LoongArchII::MO_CALL:
39bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_CALL;
40bdd1243dSDimitry Andric     break;
41bdd1243dSDimitry Andric   case LoongArchII::MO_CALL_PLT:
42bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT;
43bdd1243dSDimitry Andric     break;
44bdd1243dSDimitry Andric   case LoongArchII::MO_PCREL_HI:
45bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20;
46bdd1243dSDimitry Andric     break;
47bdd1243dSDimitry Andric   case LoongArchII::MO_PCREL_LO:
48bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
49bdd1243dSDimitry Andric     break;
50*06c3fb27SDimitry Andric   case LoongArchII::MO_PCREL64_LO:
51*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_LO20;
52*06c3fb27SDimitry Andric     break;
53*06c3fb27SDimitry Andric   case LoongArchII::MO_PCREL64_HI:
54*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_HI12;
55*06c3fb27SDimitry Andric     break;
56bdd1243dSDimitry Andric   case LoongArchII::MO_GOT_PC_HI:
57bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20;
58bdd1243dSDimitry Andric     break;
59bdd1243dSDimitry Andric   case LoongArchII::MO_GOT_PC_LO:
60bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12;
61bdd1243dSDimitry Andric     break;
62*06c3fb27SDimitry Andric   case LoongArchII::MO_GOT_PC64_LO:
63*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20;
64*06c3fb27SDimitry Andric     break;
65*06c3fb27SDimitry Andric   case LoongArchII::MO_GOT_PC64_HI:
66*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12;
67*06c3fb27SDimitry Andric     break;
68bdd1243dSDimitry Andric   case LoongArchII::MO_LE_HI:
69bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
70bdd1243dSDimitry Andric     break;
71bdd1243dSDimitry Andric   case LoongArchII::MO_LE_LO:
72bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
73bdd1243dSDimitry Andric     break;
74*06c3fb27SDimitry Andric   case LoongArchII::MO_LE64_LO:
75*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
76*06c3fb27SDimitry Andric     break;
77*06c3fb27SDimitry Andric   case LoongArchII::MO_LE64_HI:
78*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12;
79*06c3fb27SDimitry Andric     break;
80bdd1243dSDimitry Andric   case LoongArchII::MO_IE_PC_HI:
81bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
82bdd1243dSDimitry Andric     break;
83bdd1243dSDimitry Andric   case LoongArchII::MO_IE_PC_LO:
84bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
85bdd1243dSDimitry Andric     break;
86*06c3fb27SDimitry Andric   case LoongArchII::MO_IE_PC64_LO:
87*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20;
88*06c3fb27SDimitry Andric     break;
89*06c3fb27SDimitry Andric   case LoongArchII::MO_IE_PC64_HI:
90*06c3fb27SDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
91*06c3fb27SDimitry Andric     break;
92bdd1243dSDimitry Andric   case LoongArchII::MO_LD_PC_HI:
93bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
94bdd1243dSDimitry Andric     break;
95bdd1243dSDimitry Andric   case LoongArchII::MO_GD_PC_HI:
96bdd1243dSDimitry Andric     Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
97bdd1243dSDimitry Andric     break;
98bdd1243dSDimitry Andric     // TODO: Handle more target-flags.
99bdd1243dSDimitry Andric   }
100753f127fSDimitry Andric 
101753f127fSDimitry Andric   const MCExpr *ME =
102753f127fSDimitry Andric       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
103753f127fSDimitry Andric 
104753f127fSDimitry Andric   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
105753f127fSDimitry Andric     ME = MCBinaryExpr::createAdd(
106753f127fSDimitry Andric         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
107753f127fSDimitry Andric 
108bdd1243dSDimitry Andric   if (Kind != LoongArchMCExpr::VK_LoongArch_None)
109bdd1243dSDimitry Andric     ME = LoongArchMCExpr::create(ME, Kind, Ctx);
110753f127fSDimitry Andric   return MCOperand::createExpr(ME);
111753f127fSDimitry Andric }
112753f127fSDimitry Andric 
11381ad6265SDimitry Andric bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
11481ad6265SDimitry Andric                                                    MCOperand &MCOp,
11581ad6265SDimitry Andric                                                    const AsmPrinter &AP) {
11681ad6265SDimitry Andric   switch (MO.getType()) {
11781ad6265SDimitry Andric   default:
11881ad6265SDimitry Andric     report_fatal_error(
11981ad6265SDimitry Andric         "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
12081ad6265SDimitry Andric   case MachineOperand::MO_Register:
12181ad6265SDimitry Andric     // Ignore all implicit register operands.
12281ad6265SDimitry Andric     if (MO.isImplicit())
12381ad6265SDimitry Andric       return false;
12481ad6265SDimitry Andric     MCOp = MCOperand::createReg(MO.getReg());
12581ad6265SDimitry Andric     break;
12681ad6265SDimitry Andric   case MachineOperand::MO_RegisterMask:
12781ad6265SDimitry Andric     // Regmasks are like implicit defs.
12881ad6265SDimitry Andric     return false;
12981ad6265SDimitry Andric   case MachineOperand::MO_Immediate:
13081ad6265SDimitry Andric     MCOp = MCOperand::createImm(MO.getImm());
13181ad6265SDimitry Andric     break;
13281ad6265SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
133753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
134753f127fSDimitry Andric     break;
135753f127fSDimitry Andric   case MachineOperand::MO_GlobalAddress:
136753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
137753f127fSDimitry Andric     break;
138753f127fSDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
139753f127fSDimitry Andric     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
140753f127fSDimitry Andric     break;
141753f127fSDimitry Andric   case MachineOperand::MO_ExternalSymbol:
142753f127fSDimitry Andric     MCOp = lowerSymbolOperand(
143753f127fSDimitry Andric         MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
144753f127fSDimitry Andric     break;
145753f127fSDimitry Andric   case MachineOperand::MO_BlockAddress:
146bdd1243dSDimitry Andric     MCOp = lowerSymbolOperand(
147bdd1243dSDimitry Andric         MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
148bdd1243dSDimitry Andric     break;
14981ad6265SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
150bdd1243dSDimitry Andric     MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
15181ad6265SDimitry Andric     break;
15281ad6265SDimitry Andric   }
15381ad6265SDimitry Andric   return true;
15481ad6265SDimitry Andric }
15581ad6265SDimitry Andric 
15681ad6265SDimitry Andric bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
15781ad6265SDimitry Andric                                               MCInst &OutMI, AsmPrinter &AP) {
15881ad6265SDimitry Andric   OutMI.setOpcode(MI->getOpcode());
15981ad6265SDimitry Andric 
16081ad6265SDimitry Andric   for (const MachineOperand &MO : MI->operands()) {
16181ad6265SDimitry Andric     MCOperand MCOp;
16281ad6265SDimitry Andric     if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
16381ad6265SDimitry Andric       OutMI.addOperand(MCOp);
16481ad6265SDimitry Andric   }
16581ad6265SDimitry Andric   return false;
16681ad6265SDimitry Andric }
167