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/Debug.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/raw_ostream.h"
24 #define DEBUG_TYPE "mcplus"
31 class RISCVMCPlusBuilder
: public MCPlusBuilder
{
33 using MCPlusBuilder::MCPlusBuilder
;
35 bool equals(const MCTargetExpr
&A
, const MCTargetExpr
&B
,
36 CompFuncTy Comp
) const override
{
37 const auto &RISCVExprA
= cast
<RISCVMCExpr
>(A
);
38 const auto &RISCVExprB
= cast
<RISCVMCExpr
>(B
);
39 if (RISCVExprA
.getKind() != RISCVExprB
.getKind())
42 return MCPlusBuilder::equals(*RISCVExprA
.getSubExpr(),
43 *RISCVExprB
.getSubExpr(), Comp
);
46 void getCalleeSavedRegs(BitVector
&Regs
) const override
{
47 Regs
|= getAliases(RISCV::X2
);
48 Regs
|= getAliases(RISCV::X8
);
49 Regs
|= getAliases(RISCV::X9
);
50 Regs
|= getAliases(RISCV::X18
);
51 Regs
|= getAliases(RISCV::X19
);
52 Regs
|= getAliases(RISCV::X20
);
53 Regs
|= getAliases(RISCV::X21
);
54 Regs
|= getAliases(RISCV::X22
);
55 Regs
|= getAliases(RISCV::X23
);
56 Regs
|= getAliases(RISCV::X24
);
57 Regs
|= getAliases(RISCV::X25
);
58 Regs
|= getAliases(RISCV::X26
);
59 Regs
|= getAliases(RISCV::X27
);
62 bool shouldRecordCodeRelocation(uint64_t RelType
) const override
{
64 case ELF::R_RISCV_JAL
:
65 case ELF::R_RISCV_CALL
:
66 case ELF::R_RISCV_CALL_PLT
:
67 case ELF::R_RISCV_BRANCH
:
68 case ELF::R_RISCV_RVC_BRANCH
:
69 case ELF::R_RISCV_RVC_JUMP
:
70 case ELF::R_RISCV_GOT_HI20
:
71 case ELF::R_RISCV_PCREL_HI20
:
72 case ELF::R_RISCV_PCREL_LO12_I
:
73 case ELF::R_RISCV_PCREL_LO12_S
:
74 case ELF::R_RISCV_HI20
:
75 case ELF::R_RISCV_LO12_I
:
76 case ELF::R_RISCV_LO12_S
:
77 case ELF::R_RISCV_TLS_GOT_HI20
:
80 llvm_unreachable("Unexpected RISCV relocation type in code");
84 bool isNop(const MCInst
&Inst
) const {
85 return Inst
.getOpcode() == RISCV::ADDI
&&
86 Inst
.getOperand(0).getReg() == RISCV::X0
&&
87 Inst
.getOperand(1).getReg() == RISCV::X0
&&
88 Inst
.getOperand(2).getImm() == 0;
91 bool isCNop(const MCInst
&Inst
) const {
92 return Inst
.getOpcode() == RISCV::C_NOP
;
95 bool isNoop(const MCInst
&Inst
) const override
{
96 return isNop(Inst
) || isCNop(Inst
);
99 bool isPseudo(const MCInst
&Inst
) const override
{
100 switch (Inst
.getOpcode()) {
102 return MCPlusBuilder::isPseudo(Inst
);
103 case RISCV::PseudoCALL
:
104 case RISCV::PseudoTAIL
:
109 bool isIndirectCall(const MCInst
&Inst
) const override
{
113 switch (Inst
.getOpcode()) {
123 bool hasPCRelOperand(const MCInst
&Inst
) const override
{
124 switch (Inst
.getOpcode()) {
133 unsigned getInvertedBranchOpcode(unsigned Opcode
) const {
136 llvm_unreachable("Failed to invert branch opcode");
151 return RISCV::C_BNEZ
;
153 return RISCV::C_BEQZ
;
157 bool reverseBranchCondition(MCInst
&Inst
, const MCSymbol
*TBB
,
158 MCContext
*Ctx
) const override
{
159 auto Opcode
= getInvertedBranchOpcode(Inst
.getOpcode());
160 Inst
.setOpcode(Opcode
);
161 return replaceBranchTarget(Inst
, TBB
, Ctx
);
164 bool replaceBranchTarget(MCInst
&Inst
, const MCSymbol
*TBB
,
165 MCContext
*Ctx
) const override
{
166 assert((isCall(Inst
) || isBranch(Inst
)) && !isIndirectBranch(Inst
) &&
167 "Invalid instruction");
170 auto Result
= getSymbolRefOperandNum(Inst
, SymOpIndex
);
172 assert(Result
&& "unimplemented branch");
174 Inst
.getOperand(SymOpIndex
) = MCOperand::createExpr(
175 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
));
179 IndirectBranchType
analyzeIndirectBranch(
180 MCInst
&Instruction
, InstructionIterator Begin
, InstructionIterator End
,
181 const unsigned PtrSize
, MCInst
*&MemLocInstr
, unsigned &BaseRegNum
,
182 unsigned &IndexRegNum
, int64_t &DispValue
, const MCExpr
*&DispExpr
,
183 MCInst
*&PCRelBaseOut
) const override
{
184 MemLocInstr
= nullptr;
189 PCRelBaseOut
= nullptr;
191 // Check for the following long tail call sequence:
192 // 1: auipc xi, %pcrel_hi(sym)
193 // jalr zero, %pcrel_lo(1b)(xi)
194 if (Instruction
.getOpcode() == RISCV::JALR
&& Begin
!= End
) {
195 MCInst
&PrevInst
= *std::prev(End
);
196 if (isRISCVCall(PrevInst
, Instruction
) &&
197 Instruction
.getOperand(0).getReg() == RISCV::X0
)
198 return IndirectBranchType::POSSIBLE_TAIL_CALL
;
201 return IndirectBranchType::UNKNOWN
;
204 bool convertJmpToTailCall(MCInst
&Inst
) override
{
205 if (isTailCall(Inst
))
208 switch (Inst
.getOpcode()) {
210 llvm_unreachable("unsupported tail call opcode");
222 bool createReturn(MCInst
&Inst
) const override
{
223 // TODO "c.jr ra" when RVC is enabled
224 Inst
.setOpcode(RISCV::JALR
);
226 Inst
.addOperand(MCOperand::createReg(RISCV::X0
));
227 Inst
.addOperand(MCOperand::createReg(RISCV::X1
));
228 Inst
.addOperand(MCOperand::createImm(0));
232 bool createUncondBranch(MCInst
&Inst
, const MCSymbol
*TBB
,
233 MCContext
*Ctx
) const override
{
234 Inst
.setOpcode(RISCV::JAL
);
236 Inst
.addOperand(MCOperand::createReg(RISCV::X0
));
237 Inst
.addOperand(MCOperand::createExpr(
238 MCSymbolRefExpr::create(TBB
, MCSymbolRefExpr::VK_None
, *Ctx
)));
242 StringRef
getTrapFillValue() const override
{
243 return StringRef("\0\0\0\0", 4);
246 bool createCall(unsigned Opcode
, MCInst
&Inst
, const MCSymbol
*Target
,
248 Inst
.setOpcode(Opcode
);
250 Inst
.addOperand(MCOperand::createExpr(RISCVMCExpr::create(
251 MCSymbolRefExpr::create(Target
, MCSymbolRefExpr::VK_None
, *Ctx
),
252 RISCVMCExpr::VK_RISCV_CALL
, *Ctx
)));
256 bool createCall(MCInst
&Inst
, const MCSymbol
*Target
,
257 MCContext
*Ctx
) override
{
258 return createCall(RISCV::PseudoCALL
, Inst
, Target
, Ctx
);
261 bool createTailCall(MCInst
&Inst
, const MCSymbol
*Target
,
262 MCContext
*Ctx
) override
{
263 return createCall(RISCV::PseudoTAIL
, Inst
, Target
, Ctx
);
266 bool analyzeBranch(InstructionIterator Begin
, InstructionIterator End
,
267 const MCSymbol
*&TBB
, const MCSymbol
*&FBB
,
269 MCInst
*&UncondBranch
) const override
{
275 // Ignore nops and CFIs
276 if (isPseudo(*I
) || isNoop(*I
))
279 // Stop when we find the first non-terminator
280 if (!isTerminator(*I
) || isTailCall(*I
) || !isBranch(*I
))
283 // Handle unconditional branches.
284 if (isUnconditionalBranch(*I
)) {
285 // If any code was seen after this unconditional branch, we've seen
286 // unreachable code. Ignore them.
287 CondBranch
= nullptr;
289 const MCSymbol
*Sym
= getTargetSymbol(*I
);
290 assert(Sym
!= nullptr &&
291 "Couldn't extract BB symbol from jump operand");
296 // Handle conditional branches and ignore indirect branches
297 if (isIndirectBranch(*I
))
300 if (CondBranch
== nullptr) {
301 const MCSymbol
*TargetBB
= getTargetSymbol(*I
);
302 if (TargetBB
== nullptr) {
303 // Unrecognized branch target
312 llvm_unreachable("multiple conditional branches in one BB");
318 bool getSymbolRefOperandNum(const MCInst
&Inst
, unsigned &OpNum
) const {
319 switch (Inst
.getOpcode()) {
323 case TargetOpcode::EH_LABEL
:
343 const MCSymbol
*getTargetSymbol(const MCExpr
*Expr
) const override
{
344 auto *RISCVExpr
= dyn_cast
<RISCVMCExpr
>(Expr
);
345 if (RISCVExpr
&& RISCVExpr
->getSubExpr())
346 return getTargetSymbol(RISCVExpr
->getSubExpr());
348 auto *BinExpr
= dyn_cast
<MCBinaryExpr
>(Expr
);
350 return getTargetSymbol(BinExpr
->getLHS());
352 auto *SymExpr
= dyn_cast
<MCSymbolRefExpr
>(Expr
);
353 if (SymExpr
&& SymExpr
->getKind() == MCSymbolRefExpr::VK_None
)
354 return &SymExpr
->getSymbol();
359 const MCSymbol
*getTargetSymbol(const MCInst
&Inst
,
360 unsigned OpNum
= 0) const override
{
361 if (!OpNum
&& !getSymbolRefOperandNum(Inst
, OpNum
))
364 const MCOperand
&Op
= Inst
.getOperand(OpNum
);
368 return getTargetSymbol(Op
.getExpr());
371 bool lowerTailCall(MCInst
&Inst
) override
{
372 removeAnnotation(Inst
, MCPlus::MCAnnotation::kTailCall
);
373 if (getConditionalTailCall(Inst
))
374 unsetConditionalTailCall(Inst
);
378 uint64_t analyzePLTEntry(MCInst
&Instruction
, InstructionIterator Begin
,
379 InstructionIterator End
,
380 uint64_t BeginPC
) const override
{
385 assert(AUIPC
.getOpcode() == RISCV::AUIPC
);
386 assert(AUIPC
.getOperand(0).getReg() == RISCV::X28
);
390 assert(LD
.getOpcode() == RISCV::LD
);
391 assert(LD
.getOperand(0).getReg() == RISCV::X28
);
392 assert(LD
.getOperand(1).getReg() == RISCV::X28
);
397 assert(JALR
.getOpcode() == RISCV::JALR
);
398 assert(JALR
.getOperand(0).getReg() == RISCV::X6
);
399 assert(JALR
.getOperand(1).getReg() == RISCV::X28
);
408 auto AUIPCOffset
= AUIPC
.getOperand(1).getImm() << 12;
409 auto LDOffset
= LD
.getOperand(2).getImm();
410 return BeginPC
+ AUIPCOffset
+ LDOffset
;
413 bool replaceImmWithSymbolRef(MCInst
&Inst
, const MCSymbol
*Symbol
,
414 int64_t Addend
, MCContext
*Ctx
, int64_t &Value
,
415 uint64_t RelType
) const override
{
416 unsigned ImmOpNo
= -1U;
418 for (unsigned Index
= 0; Index
< MCPlus::getNumPrimeOperands(Inst
);
420 if (Inst
.getOperand(Index
).isImm()) {
429 Value
= Inst
.getOperand(ImmOpNo
).getImm();
430 setOperandToSymbolRef(Inst
, ImmOpNo
, Symbol
, Addend
, Ctx
, RelType
);
434 const MCExpr
*getTargetExprFor(MCInst
&Inst
, const MCExpr
*Expr
,
436 uint64_t RelType
) const override
{
440 case ELF::R_RISCV_GOT_HI20
:
441 case ELF::R_RISCV_TLS_GOT_HI20
:
442 // The GOT is reused so no need to create GOT relocations
443 case ELF::R_RISCV_PCREL_HI20
:
444 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_PCREL_HI
, Ctx
);
445 case ELF::R_RISCV_PCREL_LO12_I
:
446 case ELF::R_RISCV_PCREL_LO12_S
:
447 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_PCREL_LO
, Ctx
);
448 case ELF::R_RISCV_HI20
:
449 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_HI
, Ctx
);
450 case ELF::R_RISCV_LO12_I
:
451 case ELF::R_RISCV_LO12_S
:
452 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_LO
, Ctx
);
453 case ELF::R_RISCV_CALL
:
454 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_CALL
, Ctx
);
455 case ELF::R_RISCV_CALL_PLT
:
456 return RISCVMCExpr::create(Expr
, RISCVMCExpr::VK_RISCV_CALL_PLT
, Ctx
);
460 bool evaluateMemOperandTarget(const MCInst
&Inst
, uint64_t &Target
,
462 uint64_t Size
) const override
{
466 bool isCallAuipc(const MCInst
&Inst
) const {
467 if (Inst
.getOpcode() != RISCV::AUIPC
)
470 const auto &ImmOp
= Inst
.getOperand(1);
474 const auto *ImmExpr
= ImmOp
.getExpr();
475 if (!isa
<RISCVMCExpr
>(ImmExpr
))
478 switch (cast
<RISCVMCExpr
>(ImmExpr
)->getKind()) {
481 case RISCVMCExpr::VK_RISCV_CALL
:
482 case RISCVMCExpr::VK_RISCV_CALL_PLT
:
487 bool isRISCVCall(const MCInst
&First
, const MCInst
&Second
) const override
{
488 if (!isCallAuipc(First
))
491 assert(Second
.getOpcode() == RISCV::JALR
);
495 uint16_t getMinFunctionAlignment() const override
{
496 if (STI
->hasFeature(RISCV::FeatureStdExtC
) ||
497 STI
->hasFeature(RISCV::FeatureStdExtZca
))
503 } // end anonymous namespace
508 MCPlusBuilder
*createRISCVMCPlusBuilder(const MCInstrAnalysis
*Analysis
,
509 const MCInstrInfo
*Info
,
510 const MCRegisterInfo
*RegInfo
,
511 const MCSubtargetInfo
*STI
) {
512 return new RISCVMCPlusBuilder(Analysis
, Info
, RegInfo
, STI
);