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
lowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym,const AsmPrinter & AP)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
lowerLoongArchMachineOperandToMCOperand(const MachineOperand & MO,MCOperand & MCOp,const AsmPrinter & AP)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
lowerLoongArchMachineInstrToMCInst(const MachineInstr * MI,MCInst & OutMI,AsmPrinter & AP)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