1 //===-- RISCVMCCodeEmitter.cpp - Convert RISCV code to machine code -------===//
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 implements the RISCVMCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/RISCVFixupKinds.h"
14 #include "MCTargetDesc/RISCVMCExpr.h"
15 #include "MCTargetDesc/RISCVMCTargetDesc.h"
16 #include "Utils/RISCVBaseInfo.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstBuilder.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/raw_ostream.h"
33 #define DEBUG_TYPE "mccodeemitter"
35 STATISTIC(MCNumEmitted
, "Number of MC instructions emitted");
36 STATISTIC(MCNumFixups
, "Number of MC fixups created");
39 class RISCVMCCodeEmitter
: public MCCodeEmitter
{
40 RISCVMCCodeEmitter(const RISCVMCCodeEmitter
&) = delete;
41 void operator=(const RISCVMCCodeEmitter
&) = delete;
43 MCInstrInfo
const &MCII
;
46 RISCVMCCodeEmitter(MCContext
&ctx
, MCInstrInfo
const &MCII
)
47 : Ctx(ctx
), MCII(MCII
) {}
49 ~RISCVMCCodeEmitter() override
{}
51 void encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
52 SmallVectorImpl
<MCFixup
> &Fixups
,
53 const MCSubtargetInfo
&STI
) const override
;
55 void expandFunctionCall(const MCInst
&MI
, raw_ostream
&OS
,
56 SmallVectorImpl
<MCFixup
> &Fixups
,
57 const MCSubtargetInfo
&STI
) const;
59 /// TableGen'erated function for getting the binary encoding for an
61 uint64_t getBinaryCodeForInstr(const MCInst
&MI
,
62 SmallVectorImpl
<MCFixup
> &Fixups
,
63 const MCSubtargetInfo
&STI
) const;
65 /// Return binary encoding of operand. If the machine operand requires
66 /// relocation, record the relocation and return zero.
67 unsigned getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
68 SmallVectorImpl
<MCFixup
> &Fixups
,
69 const MCSubtargetInfo
&STI
) const;
71 unsigned getImmOpValueAsr1(const MCInst
&MI
, unsigned OpNo
,
72 SmallVectorImpl
<MCFixup
> &Fixups
,
73 const MCSubtargetInfo
&STI
) const;
75 unsigned getImmOpValue(const MCInst
&MI
, unsigned OpNo
,
76 SmallVectorImpl
<MCFixup
> &Fixups
,
77 const MCSubtargetInfo
&STI
) const;
79 } // end anonymous namespace
81 MCCodeEmitter
*llvm::createRISCVMCCodeEmitter(const MCInstrInfo
&MCII
,
82 const MCRegisterInfo
&MRI
,
84 return new RISCVMCCodeEmitter(Ctx
, MCII
);
87 // Expand PseudoCALL and PseudoTAIL to AUIPC and JALR with relocation types.
88 // We expand PseudoCALL and PseudoTAIL while encoding, meaning AUIPC and JALR
89 // won't go through RISCV MC to MC compressed instruction transformation. This
90 // is acceptable because AUIPC has no 16-bit form and C_JALR have no immediate
91 // operand field. We let linker relaxation deal with it. When linker
92 // relaxation enabled, AUIPC and JALR have chance relax to JAL. If C extension
93 // is enabled, JAL has chance relax to C_JAL.
94 void RISCVMCCodeEmitter::expandFunctionCall(const MCInst
&MI
, raw_ostream
&OS
,
95 SmallVectorImpl
<MCFixup
> &Fixups
,
96 const MCSubtargetInfo
&STI
) const {
98 MCOperand Func
= MI
.getOperand(0);
99 unsigned Ra
= (MI
.getOpcode() == RISCV::PseudoTAIL
) ? RISCV::X6
: RISCV::X1
;
102 assert(Func
.isExpr() && "Expected expression");
104 const MCExpr
*Expr
= Func
.getExpr();
106 // Create function call expression CallExpr for AUIPC.
107 const MCExpr
*CallExpr
=
108 RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_CALL
, Ctx
);
110 // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.
111 TmpInst
= MCInstBuilder(RISCV::AUIPC
)
113 .addOperand(MCOperand::createExpr(CallExpr
));
114 Binary
= getBinaryCodeForInstr(TmpInst
, Fixups
, STI
);
115 support::endian::write(OS
, Binary
, support::little
);
117 if (MI
.getOpcode() == RISCV::PseudoTAIL
)
118 // Emit JALR X0, X6, 0
119 TmpInst
= MCInstBuilder(RISCV::JALR
).addReg(RISCV::X0
).addReg(Ra
).addImm(0);
121 // Emit JALR X1, X1, 0
122 TmpInst
= MCInstBuilder(RISCV::JALR
).addReg(Ra
).addReg(Ra
).addImm(0);
123 Binary
= getBinaryCodeForInstr(TmpInst
, Fixups
, STI
);
124 support::endian::write(OS
, Binary
, support::little
);
127 void RISCVMCCodeEmitter::encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
128 SmallVectorImpl
<MCFixup
> &Fixups
,
129 const MCSubtargetInfo
&STI
) const {
130 const MCInstrDesc
&Desc
= MCII
.get(MI
.getOpcode());
131 // Get byte count of instruction.
132 unsigned Size
= Desc
.getSize();
134 if (MI
.getOpcode() == RISCV::PseudoCALL
||
135 MI
.getOpcode() == RISCV::PseudoTAIL
) {
136 expandFunctionCall(MI
, OS
, Fixups
, STI
);
143 llvm_unreachable("Unhandled encodeInstruction length!");
145 uint16_t Bits
= getBinaryCodeForInstr(MI
, Fixups
, STI
);
146 support::endian::write
<uint16_t>(OS
, Bits
, support::little
);
150 uint32_t Bits
= getBinaryCodeForInstr(MI
, Fixups
, STI
);
151 support::endian::write(OS
, Bits
, support::little
);
156 ++MCNumEmitted
; // Keep track of the # of mi's emitted.
160 RISCVMCCodeEmitter::getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
161 SmallVectorImpl
<MCFixup
> &Fixups
,
162 const MCSubtargetInfo
&STI
) const {
165 return Ctx
.getRegisterInfo()->getEncodingValue(MO
.getReg());
168 return static_cast<unsigned>(MO
.getImm());
170 llvm_unreachable("Unhandled expression!");
175 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst
&MI
, unsigned OpNo
,
176 SmallVectorImpl
<MCFixup
> &Fixups
,
177 const MCSubtargetInfo
&STI
) const {
178 const MCOperand
&MO
= MI
.getOperand(OpNo
);
181 unsigned Res
= MO
.getImm();
182 assert((Res
& 1) == 0 && "LSB is non-zero");
186 return getImmOpValue(MI
, OpNo
, Fixups
, STI
);
189 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst
&MI
, unsigned OpNo
,
190 SmallVectorImpl
<MCFixup
> &Fixups
,
191 const MCSubtargetInfo
&STI
) const {
192 bool EnableRelax
= STI
.getFeatureBits()[RISCV::FeatureRelax
];
193 const MCOperand
&MO
= MI
.getOperand(OpNo
);
195 MCInstrDesc
const &Desc
= MCII
.get(MI
.getOpcode());
196 unsigned MIFrm
= Desc
.TSFlags
& RISCVII::InstFormatMask
;
198 // If the destination is an immediate, there is nothing to do.
202 assert(MO
.isExpr() &&
203 "getImmOpValue expects only expressions or immediates");
204 const MCExpr
*Expr
= MO
.getExpr();
205 MCExpr::ExprKind Kind
= Expr
->getKind();
206 RISCV::Fixups FixupKind
= RISCV::fixup_riscv_invalid
;
207 bool RelaxCandidate
= false;
208 if (Kind
== MCExpr::Target
) {
209 const RISCVMCExpr
*RVExpr
= cast
<RISCVMCExpr
>(Expr
);
211 switch (RVExpr
->getKind()) {
212 case RISCVMCExpr::VK_RISCV_None
:
213 case RISCVMCExpr::VK_RISCV_Invalid
:
214 llvm_unreachable("Unhandled fixup kind!");
215 case RISCVMCExpr::VK_RISCV_LO
:
216 if (MIFrm
== RISCVII::InstFormatI
)
217 FixupKind
= RISCV::fixup_riscv_lo12_i
;
218 else if (MIFrm
== RISCVII::InstFormatS
)
219 FixupKind
= RISCV::fixup_riscv_lo12_s
;
221 llvm_unreachable("VK_RISCV_LO used with unexpected instruction format");
222 RelaxCandidate
= true;
224 case RISCVMCExpr::VK_RISCV_HI
:
225 FixupKind
= RISCV::fixup_riscv_hi20
;
226 RelaxCandidate
= true;
228 case RISCVMCExpr::VK_RISCV_PCREL_LO
:
229 if (MIFrm
== RISCVII::InstFormatI
)
230 FixupKind
= RISCV::fixup_riscv_pcrel_lo12_i
;
231 else if (MIFrm
== RISCVII::InstFormatS
)
232 FixupKind
= RISCV::fixup_riscv_pcrel_lo12_s
;
235 "VK_RISCV_PCREL_LO used with unexpected instruction format");
236 RelaxCandidate
= true;
238 case RISCVMCExpr::VK_RISCV_PCREL_HI
:
239 FixupKind
= RISCV::fixup_riscv_pcrel_hi20
;
240 RelaxCandidate
= true;
242 case RISCVMCExpr::VK_RISCV_GOT_HI
:
243 FixupKind
= RISCV::fixup_riscv_got_hi20
;
245 case RISCVMCExpr::VK_RISCV_CALL
:
246 FixupKind
= RISCV::fixup_riscv_call
;
247 RelaxCandidate
= true;
250 } else if (Kind
== MCExpr::SymbolRef
&&
251 cast
<MCSymbolRefExpr
>(Expr
)->getKind() == MCSymbolRefExpr::VK_None
) {
252 if (Desc
.getOpcode() == RISCV::JAL
) {
253 FixupKind
= RISCV::fixup_riscv_jal
;
254 } else if (MIFrm
== RISCVII::InstFormatB
) {
255 FixupKind
= RISCV::fixup_riscv_branch
;
256 } else if (MIFrm
== RISCVII::InstFormatCJ
) {
257 FixupKind
= RISCV::fixup_riscv_rvc_jump
;
258 } else if (MIFrm
== RISCVII::InstFormatCB
) {
259 FixupKind
= RISCV::fixup_riscv_rvc_branch
;
263 assert(FixupKind
!= RISCV::fixup_riscv_invalid
&& "Unhandled expression!");
266 MCFixup::create(0, Expr
, MCFixupKind(FixupKind
), MI
.getLoc()));
269 // Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is
270 // enabled and the current fixup will result in a relocation that may be
272 if (EnableRelax
&& RelaxCandidate
) {
273 const MCConstantExpr
*Dummy
= MCConstantExpr::create(0, Ctx
);
275 MCFixup::create(0, Dummy
, MCFixupKind(RISCV::fixup_riscv_relax
),
283 #include "RISCVGenMCCodeEmitter.inc"