1 //===-- RISCVMCInstLower.cpp - Convert RISCV MachineInstr to an MCInst ------=//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains code to lower RISCV MachineInstrs to their corresponding
12 //===----------------------------------------------------------------------===//
15 #include "RISCVSubtarget.h"
16 #include "MCTargetDesc/RISCVMCExpr.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 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/raw_ostream.h"
29 static MCOperand
lowerSymbolOperand(const MachineOperand
&MO
, MCSymbol
*Sym
,
30 const AsmPrinter
&AP
) {
31 MCContext
&Ctx
= AP
.OutContext
;
32 RISCVMCExpr::VariantKind Kind
;
34 switch (MO
.getTargetFlags()) {
36 llvm_unreachable("Unknown target flag on GV operand");
37 case RISCVII::MO_None
:
38 Kind
= RISCVMCExpr::VK_RISCV_None
;
40 case RISCVII::MO_CALL
:
41 Kind
= RISCVMCExpr::VK_RISCV_CALL
;
44 Kind
= RISCVMCExpr::VK_RISCV_CALL_PLT
;
47 Kind
= RISCVMCExpr::VK_RISCV_LO
;
50 Kind
= RISCVMCExpr::VK_RISCV_HI
;
52 case RISCVII::MO_PCREL_LO
:
53 Kind
= RISCVMCExpr::VK_RISCV_PCREL_LO
;
55 case RISCVII::MO_PCREL_HI
:
56 Kind
= RISCVMCExpr::VK_RISCV_PCREL_HI
;
58 case RISCVII::MO_GOT_HI
:
59 Kind
= RISCVMCExpr::VK_RISCV_GOT_HI
;
61 case RISCVII::MO_TPREL_LO
:
62 Kind
= RISCVMCExpr::VK_RISCV_TPREL_LO
;
64 case RISCVII::MO_TPREL_HI
:
65 Kind
= RISCVMCExpr::VK_RISCV_TPREL_HI
;
67 case RISCVII::MO_TPREL_ADD
:
68 Kind
= RISCVMCExpr::VK_RISCV_TPREL_ADD
;
70 case RISCVII::MO_TLS_GOT_HI
:
71 Kind
= RISCVMCExpr::VK_RISCV_TLS_GOT_HI
;
73 case RISCVII::MO_TLS_GD_HI
:
74 Kind
= RISCVMCExpr::VK_RISCV_TLS_GD_HI
;
79 MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, Ctx
);
81 if (!MO
.isJTI() && !MO
.isMBB() && MO
.getOffset())
82 ME
= MCBinaryExpr::createAdd(
83 ME
, MCConstantExpr::create(MO
.getOffset(), Ctx
), Ctx
);
85 if (Kind
!= RISCVMCExpr::VK_RISCV_None
)
86 ME
= RISCVMCExpr::create(ME
, Kind
, Ctx
);
87 return MCOperand::createExpr(ME
);
90 bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand
&MO
,
92 const AsmPrinter
&AP
) {
93 switch (MO
.getType()) {
95 report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type");
96 case MachineOperand::MO_Register
:
97 // Ignore all implicit register operands.
100 MCOp
= MCOperand::createReg(MO
.getReg());
102 case MachineOperand::MO_RegisterMask
:
103 // Regmasks are like implicit defs.
105 case MachineOperand::MO_Immediate
:
106 MCOp
= MCOperand::createImm(MO
.getImm());
108 case MachineOperand::MO_MachineBasicBlock
:
109 MCOp
= lowerSymbolOperand(MO
, MO
.getMBB()->getSymbol(), AP
);
111 case MachineOperand::MO_GlobalAddress
:
112 MCOp
= lowerSymbolOperand(MO
, AP
.getSymbolPreferLocal(*MO
.getGlobal()), AP
);
114 case MachineOperand::MO_BlockAddress
:
115 MCOp
= lowerSymbolOperand(
116 MO
, AP
.GetBlockAddressSymbol(MO
.getBlockAddress()), AP
);
118 case MachineOperand::MO_ExternalSymbol
:
119 MCOp
= lowerSymbolOperand(
120 MO
, AP
.GetExternalSymbolSymbol(MO
.getSymbolName()), AP
);
122 case MachineOperand::MO_ConstantPoolIndex
:
123 MCOp
= lowerSymbolOperand(MO
, AP
.GetCPISymbol(MO
.getIndex()), AP
);
125 case MachineOperand::MO_JumpTableIndex
:
126 MCOp
= lowerSymbolOperand(MO
, AP
.GetJTISymbol(MO
.getIndex()), AP
);
132 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr
*MI
,
134 const RISCVVPseudosTable::PseudoInfo
*RVV
=
135 RISCVVPseudosTable::getPseudoInfo(MI
->getOpcode());
139 OutMI
.setOpcode(RVV
->BaseInstr
);
141 const MachineBasicBlock
*MBB
= MI
->getParent();
142 assert(MBB
&& "MI expected to be in a basic block");
143 const MachineFunction
*MF
= MBB
->getParent();
144 assert(MF
&& "MBB expected to be in a machine function");
146 const TargetRegisterInfo
*TRI
=
147 MF
->getSubtarget
<RISCVSubtarget
>().getRegisterInfo();
148 assert(TRI
&& "TargetRegisterInfo expected");
150 uint64_t TSFlags
= MI
->getDesc().TSFlags
;
151 unsigned NumOps
= MI
->getNumExplicitOperands();
153 // Skip policy, VL and SEW operands which are the last operands if present.
154 if (RISCVII::hasVecPolicyOp(TSFlags
))
156 if (RISCVII::hasVLOp(TSFlags
))
158 if (RISCVII::hasSEWOp(TSFlags
))
161 for (unsigned OpNo
= 0; OpNo
!= NumOps
; ++OpNo
) {
162 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
164 // Skip merge op. It should be the first operand after the result.
165 if (RISCVII::hasMergeOp(TSFlags
) && OpNo
== 1) {
166 assert(MI
->getNumExplicitDefs() == 1);
171 switch (MO
.getType()) {
173 llvm_unreachable("Unknown operand type");
174 case MachineOperand::MO_Register
: {
175 unsigned Reg
= MO
.getReg();
177 if (RISCV::VRM2RegClass
.contains(Reg
) ||
178 RISCV::VRM4RegClass
.contains(Reg
) ||
179 RISCV::VRM8RegClass
.contains(Reg
)) {
180 Reg
= TRI
->getSubReg(Reg
, RISCV::sub_vrm1_0
);
181 assert(Reg
&& "Subregister does not exist");
182 } else if (RISCV::FPR16RegClass
.contains(Reg
)) {
183 Reg
= TRI
->getMatchingSuperReg(Reg
, RISCV::sub_16
, &RISCV::FPR32RegClass
);
184 assert(Reg
&& "Subregister does not exist");
185 } else if (RISCV::FPR64RegClass
.contains(Reg
)) {
186 Reg
= TRI
->getSubReg(Reg
, RISCV::sub_32
);
187 assert(Reg
&& "Superregister does not exist");
190 MCOp
= MCOperand::createReg(Reg
);
193 case MachineOperand::MO_Immediate
:
194 MCOp
= MCOperand::createImm(MO
.getImm());
197 OutMI
.addOperand(MCOp
);
200 // Unmasked pseudo instructions need to append dummy mask operand to
201 // V instructions. All V instructions are modeled as the masked version.
202 if (RISCVII::hasDummyMaskOp(TSFlags
))
203 OutMI
.addOperand(MCOperand::createReg(RISCV::NoRegister
));
208 bool llvm::lowerRISCVMachineInstrToMCInst(const MachineInstr
*MI
, MCInst
&OutMI
,
210 if (lowerRISCVVMachineInstrToMCInst(MI
, OutMI
))
213 OutMI
.setOpcode(MI
->getOpcode());
215 for (const MachineOperand
&MO
: MI
->operands()) {
217 if (LowerRISCVMachineOperandToMCOperand(MO
, MCOp
, AP
))
218 OutMI
.addOperand(MCOp
);
221 switch (OutMI
.getOpcode()) {
222 case TargetOpcode::PATCHABLE_FUNCTION_ENTER
: {
223 const Function
&F
= MI
->getParent()->getParent()->getFunction();
224 if (F
.hasFnAttribute("patchable-function-entry")) {
226 if (F
.getFnAttribute("patchable-function-entry")
228 .getAsInteger(10, Num
))
235 case RISCV::PseudoReadVLENB
:
236 OutMI
.setOpcode(RISCV::CSRRS
);
237 OutMI
.addOperand(MCOperand::createImm(
238 RISCVSysReg::lookupSysRegByName("VLENB")->Encoding
));
239 OutMI
.addOperand(MCOperand::createReg(RISCV::X0
));
241 case RISCV::PseudoReadVL
:
242 OutMI
.setOpcode(RISCV::CSRRS
);
244 MCOperand::createImm(RISCVSysReg::lookupSysRegByName("VL")->Encoding
));
245 OutMI
.addOperand(MCOperand::createReg(RISCV::X0
));