xref: /llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp (revision 0288d065eecb1208971dc4cdcc71731e34c6fca0)
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 "MCTargetDesc/LoongArchBaseInfo.h"
16 #include "MCTargetDesc/LoongArchMCExpr.h"
17 #include "llvm/CodeGen/AsmPrinter.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCContext.h"
22 
23 using namespace llvm;
24 
25 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
26                                     const AsmPrinter &AP) {
27   MCContext &Ctx = AP.OutContext;
28   LoongArchMCExpr::VariantKind Kind;
29 
30   switch (LoongArchII::getDirectFlags(MO)) {
31   default:
32     llvm_unreachable("Unknown target flag on GV operand");
33   case LoongArchII::MO_None:
34     Kind = LoongArchMCExpr::VK_LoongArch_None;
35     break;
36   case LoongArchII::MO_CALL:
37     Kind = LoongArchMCExpr::VK_LoongArch_CALL;
38     break;
39   case LoongArchII::MO_CALL_PLT:
40     Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT;
41     break;
42   case LoongArchII::MO_PCREL_HI:
43     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20;
44     break;
45   case LoongArchII::MO_PCREL_LO:
46     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
47     break;
48   case LoongArchII::MO_PCREL64_LO:
49     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_LO20;
50     break;
51   case LoongArchII::MO_PCREL64_HI:
52     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_HI12;
53     break;
54   case LoongArchII::MO_GOT_PC_HI:
55     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20;
56     break;
57   case LoongArchII::MO_GOT_PC_LO:
58     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12;
59     break;
60   case LoongArchII::MO_GOT_PC64_LO:
61     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20;
62     break;
63   case LoongArchII::MO_GOT_PC64_HI:
64     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12;
65     break;
66   case LoongArchII::MO_LE_HI:
67     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
68     break;
69   case LoongArchII::MO_LE_LO:
70     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
71     break;
72   case LoongArchII::MO_LE64_LO:
73     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
74     break;
75   case LoongArchII::MO_LE64_HI:
76     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12;
77     break;
78   case LoongArchII::MO_IE_PC_HI:
79     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
80     break;
81   case LoongArchII::MO_IE_PC_LO:
82     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
83     break;
84   case LoongArchII::MO_IE_PC64_LO:
85     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20;
86     break;
87   case LoongArchII::MO_IE_PC64_HI:
88     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
89     break;
90   case LoongArchII::MO_LD_PC_HI:
91     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
92     break;
93   case LoongArchII::MO_GD_PC_HI:
94     Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
95     break;
96   case LoongArchII::MO_CALL36:
97     Kind = LoongArchMCExpr::VK_LoongArch_CALL36;
98     break;
99   case LoongArchII::MO_DESC_PC_HI:
100     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
101     break;
102   case LoongArchII::MO_DESC_PC_LO:
103     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12;
104     break;
105   case LoongArchII::MO_DESC64_PC_LO:
106     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20;
107     break;
108   case LoongArchII::MO_DESC64_PC_HI:
109     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
110     break;
111   case LoongArchII::MO_DESC_LD:
112     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
113     break;
114   case LoongArchII::MO_DESC_CALL:
115     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
116     break;
117   case LoongArchII::MO_LE_HI_R:
118     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R;
119     break;
120   case LoongArchII::MO_LE_ADD_R:
121     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R;
122     break;
123   case LoongArchII::MO_LE_LO_R:
124     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R;
125     break;
126     // TODO: Handle more target-flags.
127   }
128 
129   const MCExpr *ME =
130       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
131 
132   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
133     ME = MCBinaryExpr::createAdd(
134         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
135 
136   if (Kind != LoongArchMCExpr::VK_LoongArch_None)
137     ME = LoongArchMCExpr::create(ME, Kind, Ctx, LoongArchII::hasRelaxFlag(MO));
138   return MCOperand::createExpr(ME);
139 }
140 
141 bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
142                                                    MCOperand &MCOp,
143                                                    const AsmPrinter &AP) {
144   switch (MO.getType()) {
145   default:
146     report_fatal_error(
147         "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
148   case MachineOperand::MO_Register:
149     // Ignore all implicit register operands.
150     if (MO.isImplicit())
151       return false;
152     MCOp = MCOperand::createReg(MO.getReg());
153     break;
154   case MachineOperand::MO_RegisterMask:
155     // Regmasks are like implicit defs.
156     return false;
157   case MachineOperand::MO_Immediate:
158     MCOp = MCOperand::createImm(MO.getImm());
159     break;
160   case MachineOperand::MO_ConstantPoolIndex:
161     MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
162     break;
163   case MachineOperand::MO_GlobalAddress:
164     MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
165     break;
166   case MachineOperand::MO_MachineBasicBlock:
167     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
168     break;
169   case MachineOperand::MO_ExternalSymbol:
170     MCOp = lowerSymbolOperand(
171         MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
172     break;
173   case MachineOperand::MO_BlockAddress:
174     MCOp = lowerSymbolOperand(
175         MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
176     break;
177   case MachineOperand::MO_JumpTableIndex:
178     MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
179     break;
180   }
181   return true;
182 }
183 
184 bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
185                                               MCInst &OutMI, AsmPrinter &AP) {
186   OutMI.setOpcode(MI->getOpcode());
187 
188   for (const MachineOperand &MO : MI->operands()) {
189     MCOperand MCOp;
190     if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
191       OutMI.addOperand(MCOp);
192   }
193   return false;
194 }
195