[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / bolt / lib / Target / RISCV / RISCVMCPlusBuilder.cpp
blobc2bc597950b859c3b15df5734ed119a531514a66
1 //===- bolt/Target/RISCV/RISCVMCPlusBuilder.cpp -----------------------===//
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 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"
26 using namespace llvm;
27 using namespace bolt;
29 namespace {
31 class RISCVMCPlusBuilder : public MCPlusBuilder {
32 public:
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())
40 return false;
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 {
63 switch (RelType) {
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:
78 return true;
79 default:
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()) {
101 default:
102 return MCPlusBuilder::isPseudo(Inst);
103 case RISCV::PseudoCALL:
104 case RISCV::PseudoTAIL:
105 return false;
109 bool isIndirectCall(const MCInst &Inst) const override {
110 if (!isCall(Inst))
111 return false;
113 switch (Inst.getOpcode()) {
114 default:
115 return false;
116 case RISCV::JALR:
117 case RISCV::C_JALR:
118 case RISCV::C_JR:
119 return true;
123 bool hasPCRelOperand(const MCInst &Inst) const override {
124 switch (Inst.getOpcode()) {
125 default:
126 return false;
127 case RISCV::JAL:
128 case RISCV::AUIPC:
129 return true;
133 unsigned getInvertedBranchOpcode(unsigned Opcode) const {
134 switch (Opcode) {
135 default:
136 llvm_unreachable("Failed to invert branch opcode");
137 return Opcode;
138 case RISCV::BEQ:
139 return RISCV::BNE;
140 case RISCV::BNE:
141 return RISCV::BEQ;
142 case RISCV::BLT:
143 return RISCV::BGE;
144 case RISCV::BGE:
145 return RISCV::BLT;
146 case RISCV::BLTU:
147 return RISCV::BGEU;
148 case RISCV::BGEU:
149 return RISCV::BLTU;
150 case RISCV::C_BEQZ:
151 return RISCV::C_BNEZ;
152 case 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");
169 unsigned SymOpIndex;
170 auto Result = getSymbolRefOperandNum(Inst, SymOpIndex);
171 (void)Result;
172 assert(Result && "unimplemented branch");
174 Inst.getOperand(SymOpIndex) = MCOperand::createExpr(
175 MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx));
176 return true;
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;
185 BaseRegNum = 0;
186 IndexRegNum = 0;
187 DispValue = 0;
188 DispExpr = 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))
206 return false;
208 switch (Inst.getOpcode()) {
209 default:
210 llvm_unreachable("unsupported tail call opcode");
211 case RISCV::JAL:
212 case RISCV::JALR:
213 case RISCV::C_J:
214 case RISCV::C_JR:
215 break;
218 setTailCall(Inst);
219 return true;
222 bool createReturn(MCInst &Inst) const override {
223 // TODO "c.jr ra" when RVC is enabled
224 Inst.setOpcode(RISCV::JALR);
225 Inst.clear();
226 Inst.addOperand(MCOperand::createReg(RISCV::X0));
227 Inst.addOperand(MCOperand::createReg(RISCV::X1));
228 Inst.addOperand(MCOperand::createImm(0));
229 return true;
232 bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
233 MCContext *Ctx) const override {
234 Inst.setOpcode(RISCV::JAL);
235 Inst.clear();
236 Inst.addOperand(MCOperand::createReg(RISCV::X0));
237 Inst.addOperand(MCOperand::createExpr(
238 MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx)));
239 return true;
242 StringRef getTrapFillValue() const override {
243 return StringRef("\0\0\0\0", 4);
246 bool createCall(unsigned Opcode, MCInst &Inst, const MCSymbol *Target,
247 MCContext *Ctx) {
248 Inst.setOpcode(Opcode);
249 Inst.clear();
250 Inst.addOperand(MCOperand::createExpr(RISCVMCExpr::create(
251 MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx),
252 RISCVMCExpr::VK_RISCV_CALL, *Ctx)));
253 return true;
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,
268 MCInst *&CondBranch,
269 MCInst *&UncondBranch) const override {
270 auto I = End;
272 while (I != Begin) {
273 --I;
275 // Ignore nops and CFIs
276 if (isPseudo(*I) || isNoop(*I))
277 continue;
279 // Stop when we find the first non-terminator
280 if (!isTerminator(*I) || isTailCall(*I) || !isBranch(*I))
281 break;
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;
288 UncondBranch = &*I;
289 const MCSymbol *Sym = getTargetSymbol(*I);
290 assert(Sym != nullptr &&
291 "Couldn't extract BB symbol from jump operand");
292 TBB = Sym;
293 continue;
296 // Handle conditional branches and ignore indirect branches
297 if (isIndirectBranch(*I))
298 return false;
300 if (CondBranch == nullptr) {
301 const MCSymbol *TargetBB = getTargetSymbol(*I);
302 if (TargetBB == nullptr) {
303 // Unrecognized branch target
304 return false;
306 FBB = TBB;
307 TBB = TargetBB;
308 CondBranch = &*I;
309 continue;
312 llvm_unreachable("multiple conditional branches in one BB");
315 return true;
318 bool getSymbolRefOperandNum(const MCInst &Inst, unsigned &OpNum) const {
319 switch (Inst.getOpcode()) {
320 default:
321 return false;
322 case RISCV::C_J:
323 case TargetOpcode::EH_LABEL:
324 OpNum = 0;
325 return true;
326 case RISCV::AUIPC:
327 case RISCV::JAL:
328 case RISCV::C_BEQZ:
329 case RISCV::C_BNEZ:
330 OpNum = 1;
331 return true;
332 case RISCV::BEQ:
333 case RISCV::BGE:
334 case RISCV::BGEU:
335 case RISCV::BNE:
336 case RISCV::BLT:
337 case RISCV::BLTU:
338 OpNum = 2;
339 return true;
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);
349 if (BinExpr)
350 return getTargetSymbol(BinExpr->getLHS());
352 auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr);
353 if (SymExpr && SymExpr->getKind() == MCSymbolRefExpr::VK_None)
354 return &SymExpr->getSymbol();
356 return nullptr;
359 const MCSymbol *getTargetSymbol(const MCInst &Inst,
360 unsigned OpNum = 0) const override {
361 if (!OpNum && !getSymbolRefOperandNum(Inst, OpNum))
362 return nullptr;
364 const MCOperand &Op = Inst.getOperand(OpNum);
365 if (!Op.isExpr())
366 return nullptr;
368 return getTargetSymbol(Op.getExpr());
371 bool lowerTailCall(MCInst &Inst) override {
372 removeAnnotation(Inst, MCPlus::MCAnnotation::kTailCall);
373 if (getConditionalTailCall(Inst))
374 unsetConditionalTailCall(Inst);
375 return true;
378 uint64_t analyzePLTEntry(MCInst &Instruction, InstructionIterator Begin,
379 InstructionIterator End,
380 uint64_t BeginPC) const override {
381 auto I = Begin;
383 assert(I != End);
384 auto &AUIPC = *I++;
385 assert(AUIPC.getOpcode() == RISCV::AUIPC);
386 assert(AUIPC.getOperand(0).getReg() == RISCV::X28);
388 assert(I != End);
389 auto &LD = *I++;
390 assert(LD.getOpcode() == RISCV::LD);
391 assert(LD.getOperand(0).getReg() == RISCV::X28);
392 assert(LD.getOperand(1).getReg() == RISCV::X28);
394 assert(I != End);
395 auto &JALR = *I++;
396 (void)JALR;
397 assert(JALR.getOpcode() == RISCV::JALR);
398 assert(JALR.getOperand(0).getReg() == RISCV::X6);
399 assert(JALR.getOperand(1).getReg() == RISCV::X28);
401 assert(I != End);
402 auto &NOP = *I++;
403 (void)NOP;
404 assert(isNoop(NOP));
406 assert(I == End);
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);
419 ++Index) {
420 if (Inst.getOperand(Index).isImm()) {
421 ImmOpNo = Index;
422 break;
426 if (ImmOpNo == -1U)
427 return false;
429 Value = Inst.getOperand(ImmOpNo).getImm();
430 setOperandToSymbolRef(Inst, ImmOpNo, Symbol, Addend, Ctx, RelType);
431 return true;
434 const MCExpr *getTargetExprFor(MCInst &Inst, const MCExpr *Expr,
435 MCContext &Ctx,
436 uint64_t RelType) const override {
437 switch (RelType) {
438 default:
439 return Expr;
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,
461 uint64_t Address,
462 uint64_t Size) const override {
463 return false;
466 bool isCallAuipc(const MCInst &Inst) const {
467 if (Inst.getOpcode() != RISCV::AUIPC)
468 return false;
470 const auto &ImmOp = Inst.getOperand(1);
471 if (!ImmOp.isExpr())
472 return false;
474 const auto *ImmExpr = ImmOp.getExpr();
475 if (!isa<RISCVMCExpr>(ImmExpr))
476 return false;
478 switch (cast<RISCVMCExpr>(ImmExpr)->getKind()) {
479 default:
480 return false;
481 case RISCVMCExpr::VK_RISCV_CALL:
482 case RISCVMCExpr::VK_RISCV_CALL_PLT:
483 return true;
487 bool isRISCVCall(const MCInst &First, const MCInst &Second) const override {
488 if (!isCallAuipc(First))
489 return false;
491 assert(Second.getOpcode() == RISCV::JALR);
492 return true;
495 uint16_t getMinFunctionAlignment() const override {
496 if (STI->hasFeature(RISCV::FeatureStdExtC) ||
497 STI->hasFeature(RISCV::FeatureStdExtZca))
498 return 2;
499 return 4;
503 } // end anonymous namespace
505 namespace llvm {
506 namespace bolt {
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);
515 } // namespace bolt
516 } // namespace llvm