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
lowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym,const AsmPrinter & AP)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;
5006c3fb27SDimitry Andric case LoongArchII::MO_PCREL64_LO:
5106c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_LO20;
5206c3fb27SDimitry Andric break;
5306c3fb27SDimitry Andric case LoongArchII::MO_PCREL64_HI:
5406c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_HI12;
5506c3fb27SDimitry 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;
6206c3fb27SDimitry Andric case LoongArchII::MO_GOT_PC64_LO:
6306c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20;
6406c3fb27SDimitry Andric break;
6506c3fb27SDimitry Andric case LoongArchII::MO_GOT_PC64_HI:
6606c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12;
6706c3fb27SDimitry 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;
7406c3fb27SDimitry Andric case LoongArchII::MO_LE64_LO:
7506c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
7606c3fb27SDimitry Andric break;
7706c3fb27SDimitry Andric case LoongArchII::MO_LE64_HI:
7806c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12;
7906c3fb27SDimitry 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;
8606c3fb27SDimitry Andric case LoongArchII::MO_IE_PC64_LO:
8706c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20;
8806c3fb27SDimitry Andric break;
8906c3fb27SDimitry Andric case LoongArchII::MO_IE_PC64_HI:
9006c3fb27SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
9106c3fb27SDimitry 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;
981db9f3b2SDimitry Andric case LoongArchII::MO_CALL36:
991db9f3b2SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_CALL36;
1001db9f3b2SDimitry Andric break;
101*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC_PC_HI:
102*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
103*0fca6ea1SDimitry Andric break;
104*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC_PC_LO:
105*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12;
106*0fca6ea1SDimitry Andric break;
107*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC64_PC_LO:
108*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20;
109*0fca6ea1SDimitry Andric break;
110*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC64_PC_HI:
111*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
112*0fca6ea1SDimitry Andric break;
113*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC_LD:
114*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
115*0fca6ea1SDimitry Andric break;
116*0fca6ea1SDimitry Andric case LoongArchII::MO_DESC_CALL:
117*0fca6ea1SDimitry Andric Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
118*0fca6ea1SDimitry Andric break;
119bdd1243dSDimitry Andric // TODO: Handle more target-flags.
120bdd1243dSDimitry Andric }
121753f127fSDimitry Andric
122753f127fSDimitry Andric const MCExpr *ME =
123753f127fSDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
124753f127fSDimitry Andric
125753f127fSDimitry Andric if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
126753f127fSDimitry Andric ME = MCBinaryExpr::createAdd(
127753f127fSDimitry Andric ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
128753f127fSDimitry Andric
129bdd1243dSDimitry Andric if (Kind != LoongArchMCExpr::VK_LoongArch_None)
130bdd1243dSDimitry Andric ME = LoongArchMCExpr::create(ME, Kind, Ctx);
131753f127fSDimitry Andric return MCOperand::createExpr(ME);
132753f127fSDimitry Andric }
133753f127fSDimitry Andric
lowerLoongArchMachineOperandToMCOperand(const MachineOperand & MO,MCOperand & MCOp,const AsmPrinter & AP)13481ad6265SDimitry Andric bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
13581ad6265SDimitry Andric MCOperand &MCOp,
13681ad6265SDimitry Andric const AsmPrinter &AP) {
13781ad6265SDimitry Andric switch (MO.getType()) {
13881ad6265SDimitry Andric default:
13981ad6265SDimitry Andric report_fatal_error(
14081ad6265SDimitry Andric "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
14181ad6265SDimitry Andric case MachineOperand::MO_Register:
14281ad6265SDimitry Andric // Ignore all implicit register operands.
14381ad6265SDimitry Andric if (MO.isImplicit())
14481ad6265SDimitry Andric return false;
14581ad6265SDimitry Andric MCOp = MCOperand::createReg(MO.getReg());
14681ad6265SDimitry Andric break;
14781ad6265SDimitry Andric case MachineOperand::MO_RegisterMask:
14881ad6265SDimitry Andric // Regmasks are like implicit defs.
14981ad6265SDimitry Andric return false;
15081ad6265SDimitry Andric case MachineOperand::MO_Immediate:
15181ad6265SDimitry Andric MCOp = MCOperand::createImm(MO.getImm());
15281ad6265SDimitry Andric break;
15381ad6265SDimitry Andric case MachineOperand::MO_ConstantPoolIndex:
154753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
155753f127fSDimitry Andric break;
156753f127fSDimitry Andric case MachineOperand::MO_GlobalAddress:
157753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
158753f127fSDimitry Andric break;
159753f127fSDimitry Andric case MachineOperand::MO_MachineBasicBlock:
160753f127fSDimitry Andric MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
161753f127fSDimitry Andric break;
162753f127fSDimitry Andric case MachineOperand::MO_ExternalSymbol:
163753f127fSDimitry Andric MCOp = lowerSymbolOperand(
164753f127fSDimitry Andric MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
165753f127fSDimitry Andric break;
166753f127fSDimitry Andric case MachineOperand::MO_BlockAddress:
167bdd1243dSDimitry Andric MCOp = lowerSymbolOperand(
168bdd1243dSDimitry Andric MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
169bdd1243dSDimitry Andric break;
17081ad6265SDimitry Andric case MachineOperand::MO_JumpTableIndex:
171bdd1243dSDimitry Andric MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
17281ad6265SDimitry Andric break;
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric return true;
17581ad6265SDimitry Andric }
17681ad6265SDimitry Andric
lowerLoongArchMachineInstrToMCInst(const MachineInstr * MI,MCInst & OutMI,AsmPrinter & AP)17781ad6265SDimitry Andric bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
17881ad6265SDimitry Andric MCInst &OutMI, AsmPrinter &AP) {
17981ad6265SDimitry Andric OutMI.setOpcode(MI->getOpcode());
18081ad6265SDimitry Andric
18181ad6265SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
18281ad6265SDimitry Andric MCOperand MCOp;
18381ad6265SDimitry Andric if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
18481ad6265SDimitry Andric OutMI.addOperand(MCOp);
18581ad6265SDimitry Andric }
18681ad6265SDimitry Andric return false;
18781ad6265SDimitry Andric }
188