xref: /freebsd/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp (revision 0e8011faf58b743cc652e3b2ad0f7671227610df)
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 
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_PCREL64_LO:
51     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_LO20;
52     break;
53   case LoongArchII::MO_PCREL64_HI:
54     Kind = LoongArchMCExpr::VK_LoongArch_PCALA64_HI12;
55     break;
56   case LoongArchII::MO_GOT_PC_HI:
57     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20;
58     break;
59   case LoongArchII::MO_GOT_PC_LO:
60     Kind = LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12;
61     break;
62   case LoongArchII::MO_GOT_PC64_LO:
63     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20;
64     break;
65   case LoongArchII::MO_GOT_PC64_HI:
66     Kind = LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12;
67     break;
68   case LoongArchII::MO_LE_HI:
69     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
70     break;
71   case LoongArchII::MO_LE_LO:
72     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12;
73     break;
74   case LoongArchII::MO_LE64_LO:
75     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
76     break;
77   case LoongArchII::MO_LE64_HI:
78     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12;
79     break;
80   case LoongArchII::MO_IE_PC_HI:
81     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20;
82     break;
83   case LoongArchII::MO_IE_PC_LO:
84     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
85     break;
86   case LoongArchII::MO_IE_PC64_LO:
87     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20;
88     break;
89   case LoongArchII::MO_IE_PC64_HI:
90     Kind = LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
91     break;
92   case LoongArchII::MO_LD_PC_HI:
93     Kind = LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20;
94     break;
95   case LoongArchII::MO_GD_PC_HI:
96     Kind = LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
97     break;
98   case LoongArchII::MO_CALL36:
99     Kind = LoongArchMCExpr::VK_LoongArch_CALL36;
100     break;
101   case LoongArchII::MO_DESC_PC_HI:
102     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_HI20;
103     break;
104   case LoongArchII::MO_DESC_PC_LO:
105     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_PC_LO12;
106     break;
107   case LoongArchII::MO_DESC64_PC_LO:
108     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_LO20;
109     break;
110   case LoongArchII::MO_DESC64_PC_HI:
111     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC64_PC_HI12;
112     break;
113   case LoongArchII::MO_DESC_LD:
114     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_LD;
115     break;
116   case LoongArchII::MO_DESC_CALL:
117     Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL;
118     break;
119     // TODO: Handle more target-flags.
120   }
121 
122   const MCExpr *ME =
123       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
124 
125   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
126     ME = MCBinaryExpr::createAdd(
127         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
128 
129   if (Kind != LoongArchMCExpr::VK_LoongArch_None)
130     ME = LoongArchMCExpr::create(ME, Kind, Ctx);
131   return MCOperand::createExpr(ME);
132 }
133 
134 bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
135                                                    MCOperand &MCOp,
136                                                    const AsmPrinter &AP) {
137   switch (MO.getType()) {
138   default:
139     report_fatal_error(
140         "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
141   case MachineOperand::MO_Register:
142     // Ignore all implicit register operands.
143     if (MO.isImplicit())
144       return false;
145     MCOp = MCOperand::createReg(MO.getReg());
146     break;
147   case MachineOperand::MO_RegisterMask:
148     // Regmasks are like implicit defs.
149     return false;
150   case MachineOperand::MO_Immediate:
151     MCOp = MCOperand::createImm(MO.getImm());
152     break;
153   case MachineOperand::MO_ConstantPoolIndex:
154     MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP);
155     break;
156   case MachineOperand::MO_GlobalAddress:
157     MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
158     break;
159   case MachineOperand::MO_MachineBasicBlock:
160     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), AP);
161     break;
162   case MachineOperand::MO_ExternalSymbol:
163     MCOp = lowerSymbolOperand(
164         MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
165     break;
166   case MachineOperand::MO_BlockAddress:
167     MCOp = lowerSymbolOperand(
168         MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
169     break;
170   case MachineOperand::MO_JumpTableIndex:
171     MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
172     break;
173   }
174   return true;
175 }
176 
177 bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
178                                               MCInst &OutMI, AsmPrinter &AP) {
179   OutMI.setOpcode(MI->getOpcode());
180 
181   for (const MachineOperand &MO : MI->operands()) {
182     MCOperand MCOp;
183     if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
184       OutMI.addOperand(MCOp);
185   }
186   return false;
187 }
188