1 //===- bolt/Target/RISCV/RISCVMCPlusBuilder.cpp -----------------------===//
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 provides RISCV-specific MCPlus builder.
11 //===----------------------------------------------------------------------===//
13 #include "MCTargetDesc/RISCVMCExpr.h"
14 #include "MCTargetDesc/RISCVMCTargetDesc.h"
15 #include "bolt/Core/MCPlusBuilder.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCSubtargetInfo.h"
19 #include "llvm/Support/ErrorHandling.h"
21 #define DEBUG_TYPE "mcplus"
28 class RISCVMCPlusBuilder
: public MCPlusBuilder
{
30 using MCPlusBuilder::MCPlusBuilder
;
32 bool equals(const MCTargetExpr
&A
, const MCTargetExpr
&B
,
33 CompFuncTy Comp
) const override
{
34 const auto &RISCVExprA
= cast
<RISCVMCExpr
>(A
);
35 const auto &RISCVExprB
= cast
<RISCVMCExpr
>(B
);
36 if (RISCVExprA
.getKind() != RISCVExprB
.getKind())
39 return MCPlusBuilder::equals(*RISCVExprA
.getSubExpr(),
40 *RISCVExprB
.getSubExpr(), Comp
);
43 void getCalleeSavedRegs(BitVector
&Regs
) const override
{
44 Regs
|= getAliases(RISCV::X2
);
45 Regs
|= getAliases(RISCV::X8
);
46 Regs
|= getAliases(RISCV::X9
);
47 Regs
|= getAliases(RISCV::X18
);
48 Regs
|= getAliases(RISCV::X19
);
49 Regs
|= getAliases(RISCV::X20
);
50 Regs
|= getAliases(RISCV::X21
);
51 Regs
|= getAliases(RISCV::X22
);
52 Regs
|= getAliases(RISCV::X23
);
53 Regs
|= getAliases(RISCV::X24
);
54 Regs
|= getAliases(RISCV::X25
);
55 Regs
|= getAliases(RISCV::X26
);
56 Regs
|= getAliases(RISCV::X27
);
59 bool shouldRecordCodeRelocation(uint64_t RelType
) const override
{
61 case ELF::R_RISCV_JAL
:
62 case ELF::R_RISCV_CALL
:
63 case ELF::R_RISCV_CALL_PLT
:
64 case ELF::R_RISCV_BRANCH
:
65 case ELF::R_RISCV_RVC_BRANCH
:
66 case ELF::R_RISCV_RVC_JUMP
:
67 case ELF::R_RISCV_GOT_HI20
:
68 case ELF::R_RISCV_PCREL_HI20
:
69 case ELF::R_RISCV_PCREL_LO12_I
:
70 case ELF::R_RISCV_PCREL_LO12_S
:
71 case ELF::R_RISCV_HI20
:
72 case ELF::R_RISCV_LO12_I
:
73 case ELF::R_RISCV_LO12_S
:
74 case ELF::R_RISCV_TLS_GOT_HI20
:
77 llvm_unreachable("Unexpected RISCV relocation type in code");
81 bool isNop(const MCInst
&Inst
) const {
82 return Inst
.getOpcode() == RISCV::ADDI
&&
83 Inst
.getOperand(0).getReg() == RISCV::X0
&&
84 Inst
.getOperand(1).getReg() == RISCV::X0
&&
85 Inst
.getOperand(2).getImm() == 0;
88 bool isCNop(const MCInst
&Inst
) const {
89 return Inst
.getOpcode() == RISCV::C_NOP
;
92 bool isNoop(const MCInst
&Inst
) const override
{
93 return isNop(Inst
) || isCNop(Inst
);
96 bool isPseudo(const MCInst
&Inst
) const override
{
97 switch (Inst
.getOpcode()) {
99 return MCPlusBuilder::isPseudo(Inst
);
100 case RISCV::PseudoCALL
:
101 case RISCV::PseudoTAIL
:
106 bool isIndirectCall(const MCInst
&Inst
) const override
{
110 switch (Inst
.getOpcode()) {
120 bool hasPCRelOperand(const MCInst
&Inst
) const override
{
121 switch (Inst
.getOpcode()) {
130 unsigned getInvertedBranchOpcode(unsigned Opcode
) const {
133 llvm_unreachable("Failed to invert branch opcode");
148 return RISCV::C_BNEZ
;
150 return RISCV::C_BEQZ
;
154 void reverseBranchCondition(MCInst
&Inst
, const MCSymbol
*TBB
,
155 MCContext
*Ctx
) const override
{
156 auto Opcode
= getInvertedBranchOpcode(Inst
.getOpcode());
157 Inst
.setOpcode(Opcode
);
158 replaceBranchTarget(Inst
, TBB
, Ctx
);
161 void replaceBranchTarget(MCInst
&Inst
, const MCSymbol
*TBB
,
162 MCContext
*Ctx
) const override
{
163 assert((isCall(Inst
) || isBranch(Inst
)) && !isIndirectBranch(Inst
) &&
164 "Invalid instruction");
167 auto Result
= getSymbolRefOperandNum(Inst
, SymOpIndex
);
169 assert(Result
&& "unimplemented branch");
171 Inst
.getOperand(SymOpIndex
) = MCOperand::createExpr(
172 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
));
175 IndirectBranchType
analyzeIndirectBranch(
176 MCInst
&Instruction
, InstructionIterator Begin
, InstructionIterator End
,
177 const unsigned PtrSize
, MCInst
*&MemLocInstr
, unsigned &BaseRegNum
,
178 unsigned &IndexRegNum
, int64_t &DispValue
, const MCExpr
*&DispExpr
,
179 MCInst
*&PCRelBaseOut
, MCInst
*&FixedEntryLoadInst
) const override
{
180 MemLocInstr
= nullptr;
185 PCRelBaseOut
= nullptr;
186 FixedEntryLoadInst
= nullptr;
188 // Check for the following long tail call sequence:
189 // 1: auipc xi, %pcrel_hi(sym)
190 // jalr zero, %pcrel_lo(1b)(xi)
191 if (Instruction
.getOpcode() == RISCV::JALR
&& Begin
!= End
) {
192 MCInst
&PrevInst
= *std::prev(End
);
193 if (isRISCVCall(PrevInst
, Instruction
) &&
194 Instruction
.getOperand(0).getReg() == RISCV::X0
)
195 return IndirectBranchType::POSSIBLE_TAIL_CALL
;
198 return IndirectBranchType::UNKNOWN
;
201 bool convertJmpToTailCall(MCInst
&Inst
) override
{
202 if (isTailCall(Inst
))
205 switch (Inst
.getOpcode()) {
207 llvm_unreachable("unsupported tail call opcode");
219 void createReturn(MCInst
&Inst
) const override
{
220 // TODO "c.jr ra" when RVC is enabled
221 Inst
.setOpcode(RISCV::JALR
);
223 Inst
.addOperand(MCOperand::createReg(RISCV::X0
));
224 Inst
.addOperand(MCOperand::createReg(RISCV::X1
));
225 Inst
.addOperand(MCOperand::createImm(0));
228 void createUncondBranch(MCInst
&Inst
, const MCSymbol
*TBB
,
229 MCContext
*Ctx
) const override
{
230 Inst
.setOpcode(RISCV::JAL
);
232 Inst
.addOperand(MCOperand::createReg(RISCV::X0
));
233 Inst
.addOperand(MCOperand::createExpr(
234 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
)));
237 StringRef
getTrapFillValue() const override
{
238 return StringRef("\0\0\0\0", 4);
241 void createCall(unsigned Opcode
, MCInst
&Inst
, const MCSymbol
*Target
,
243 Inst
.setOpcode(Opcode
);
245 Inst
.addOperand(MCOperand::createExpr(RISCVMCExpr::create(
246 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
, *Ctx
),
247 RISCVMCExpr::VK_RISCV_CALL
, *Ctx
)));
250 void createCall(MCInst
&Inst
, const MCSymbol
*Target
,
251 MCContext
*Ctx
) override
{
252 return createCall(RISCV::PseudoCALL
, Inst
, Target
, Ctx
);
255 void createTailCall(MCInst
&Inst
, const MCSymbol
*Target
,
256 MCContext
*Ctx
) override
{
257 return createCall(RISCV::PseudoTAIL
, Inst
, Target
, Ctx
);
260 bool analyzeBranch(InstructionIterator Begin
, InstructionIterator End
,
261 const MCSymbol
*&TBB
, const MCSymbol
*&FBB
,
263 MCInst
*&UncondBranch
) const override
{
269 // Ignore nops and CFIs
270 if (isPseudo(*I
) || isNoop(*I
))
273 // Stop when we find the first non-terminator
274 if (!isTerminator(*I
) || isTailCall(*I
) || !isBranch(*I
))
277 // Handle unconditional branches.
278 if (isUnconditionalBranch(*I
)) {
279 // If any code was seen after this unconditional branch, we've seen
280 // unreachable code. Ignore them.
281 CondBranch
= nullptr;
283 const MCSymbol
*Sym
= getTargetSymbol(*I
);
284 assert(Sym
!= nullptr &&
285 "Couldn't extract BB symbol from jump operand");
290 // Handle conditional branches and ignore indirect branches
291 if (isIndirectBranch(*I
))
294 if (CondBranch
== nullptr) {
295 const MCSymbol
*TargetBB
= getTargetSymbol(*I
);
296 if (TargetBB
== nullptr) {
297 // Unrecognized branch target
306 llvm_unreachable("multiple conditional branches in one BB");
312 bool getSymbolRefOperandNum(const MCInst
&Inst
, unsigned &OpNum
) const {
313 switch (Inst
.getOpcode()) {
336 const MCSymbol
*getTargetSymbol(const MCExpr
*Expr
) const override
{
337 auto *RISCVExpr
= dyn_cast
<RISCVMCExpr
>(Expr
);
338 if (RISCVExpr
&& RISCVExpr
->getSubExpr())
339 return getTargetSymbol(RISCVExpr
->getSubExpr());
341 auto *BinExpr
= dyn_cast
<MCBinaryExpr
>(Expr
);
343 return getTargetSymbol(BinExpr
->getLHS());
345 auto *SymExpr
= dyn_cast
<MCSymbolRefExpr
>(Expr
);
346 if (SymExpr
&& SymExpr
->getKind() == MCSymbolRefExpr::VK_None
)
347 return &SymExpr
->getSymbol();
352 const MCSymbol
*getTargetSymbol(const MCInst
&Inst
,
353 unsigned OpNum
= 0) const override
{
354 if (!OpNum
&& !getSymbolRefOperandNum(Inst
, OpNum
))
357 const MCOperand
&Op
= Inst
.getOperand(OpNum
);
361 return getTargetSymbol(Op
.getExpr());
364 bool lowerTailCall(MCInst
&Inst
) override
{
365 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
366 if (getConditionalTailCall(Inst
))
367 unsetConditionalTailCall(Inst
);
371 uint64_t analyzePLTEntry(MCInst
&Instruction
, InstructionIterator Begin
,
372 InstructionIterator End
,
373 uint64_t BeginPC
) const override
{
378 assert(AUIPC
.getOpcode() == RISCV::AUIPC
);
379 assert(AUIPC
.getOperand(0).getReg() == RISCV::X28
);
383 assert(LD
.getOpcode() == RISCV::LD
);
384 assert(LD
.getOperand(0).getReg() == RISCV::X28
);
385 assert(LD
.getOperand(1).getReg() == RISCV::X28
);
390 assert(JALR
.getOpcode() == RISCV::JALR
);
391 assert(JALR
.getOperand(0).getReg() == RISCV::X6
);
392 assert(JALR
.getOperand(1).getReg() == RISCV::X28
);
401 auto AUIPCOffset
= AUIPC
.getOperand(1).getImm() << 12;
402 auto LDOffset
= LD
.getOperand(2).getImm();
403 return BeginPC
+ AUIPCOffset
+ LDOffset
;
406 bool replaceImmWithSymbolRef(MCInst
&Inst
, const MCSymbol
*Symbol
,
407 int64_t Addend
, MCContext
*Ctx
, int64_t &Value
,
408 uint64_t RelType
) const override
{
409 unsigned ImmOpNo
= -1U;
411 for (unsigned Index
= 0; Index
< MCPlus::getNumPrimeOperands(Inst
);
413 if (Inst
.getOperand(Index
).isImm()) {
422 Value
= Inst
.getOperand(ImmOpNo
).getImm();
423 setOperandToSymbolRef(Inst
, ImmOpNo
, Symbol
, Addend
, Ctx
, RelType
);
427 const MCExpr
*getTargetExprFor(MCInst
&Inst
, const MCExpr
*Expr
,
429 uint64_t RelType
) const override
{
433 case ELF::R_RISCV_GOT_HI20
:
434 case ELF::R_RISCV_TLS_GOT_HI20
:
435 // The GOT is reused so no need to create GOT relocations
436 case ELF::R_RISCV_PCREL_HI20
:
437 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_PCREL_HI
, Ctx
);
438 case ELF::R_RISCV_PCREL_LO12_I
:
439 case ELF::R_RISCV_PCREL_LO12_S
:
440 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_PCREL_LO
, Ctx
);
441 case ELF::R_RISCV_HI20
:
442 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_HI
, Ctx
);
443 case ELF::R_RISCV_LO12_I
:
444 case ELF::R_RISCV_LO12_S
:
445 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_LO
, Ctx
);
446 case ELF::R_RISCV_CALL
:
447 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_CALL
, Ctx
);
448 case ELF::R_RISCV_CALL_PLT
:
449 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_CALL_PLT
, Ctx
);
453 bool evaluateMemOperandTarget(const MCInst
&Inst
, uint64_t &Target
,
455 uint64_t Size
) const override
{
459 bool isCallAuipc(const MCInst
&Inst
) const {
460 if (Inst
.getOpcode() != RISCV::AUIPC
)
463 const auto &ImmOp
= Inst
.getOperand(1);
467 const auto *ImmExpr
= ImmOp
.getExpr();
468 if (!isa
<RISCVMCExpr
>(ImmExpr
))
471 switch (cast
<RISCVMCExpr
>(ImmExpr
)->getKind()) {
474 case RISCVMCExpr::VK_RISCV_CALL
:
475 case RISCVMCExpr::VK_RISCV_CALL_PLT
:
480 bool isRISCVCall(const MCInst
&First
, const MCInst
&Second
) const override
{
481 if (!isCallAuipc(First
))
484 assert(Second
.getOpcode() == RISCV::JALR
);
488 uint16_t getMinFunctionAlignment() const override
{
489 if (STI
->hasFeature(RISCV::FeatureStdExtC
) ||
490 STI
->hasFeature(RISCV::FeatureStdExtZca
))
496 } // end anonymous namespace
501 MCPlusBuilder
*createRISCVMCPlusBuilder(const MCInstrAnalysis
*Analysis
,
502 const MCInstrInfo
*Info
,
503 const MCRegisterInfo
*RegInfo
,
504 const MCSubtargetInfo
*STI
) {
505 return new RISCVMCPlusBuilder(Analysis
, Info
, RegInfo
, STI
);