xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1 //===-- RISCVELFObjectWriter.cpp - RISCV ELF Writer -----------------------===//
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 #include "MCTargetDesc/RISCVFixupKinds.h"
10 #include "MCTargetDesc/RISCVMCExpr.h"
11 #include "MCTargetDesc/RISCVMCTargetDesc.h"
12 #include "llvm/MC/MCELFObjectWriter.h"
13 #include "llvm/MC/MCFixup.h"
14 #include "llvm/MC/MCObjectWriter.h"
15 #include "llvm/Support/ErrorHandling.h"
16 
17 using namespace llvm;
18 
19 namespace {
20 class RISCVELFObjectWriter : public MCELFObjectTargetWriter {
21 public:
22   RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit);
23 
24   ~RISCVELFObjectWriter() override;
25 
26   // Return true if the given relocation must be with a symbol rather than
27   // section plus offset.
28   bool needsRelocateWithSymbol(const MCSymbol &Sym,
29                                unsigned Type) const override {
30     // TODO: this is very conservative, update once RISC-V psABI requirements
31     //       are clarified.
32     return true;
33   }
34 
35 protected:
36   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
37                         const MCFixup &Fixup, bool IsPCRel) const override;
38 };
39 }
40 
41 RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)
42     : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,
43                               /*HasRelocationAddend*/ true) {}
44 
45 RISCVELFObjectWriter::~RISCVELFObjectWriter() {}
46 
47 unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
48                                             const MCValue &Target,
49                                             const MCFixup &Fixup,
50                                             bool IsPCRel) const {
51   const MCExpr *Expr = Fixup.getValue();
52   // Determine the type of the relocation
53   unsigned Kind = Fixup.getTargetKind();
54   if (IsPCRel) {
55     switch (Kind) {
56     default:
57       llvm_unreachable("invalid fixup kind!");
58     case FK_Data_4:
59     case FK_PCRel_4:
60       return ELF::R_RISCV_32_PCREL;
61     case RISCV::fixup_riscv_pcrel_hi20:
62       return ELF::R_RISCV_PCREL_HI20;
63     case RISCV::fixup_riscv_pcrel_lo12_i:
64       return ELF::R_RISCV_PCREL_LO12_I;
65     case RISCV::fixup_riscv_pcrel_lo12_s:
66       return ELF::R_RISCV_PCREL_LO12_S;
67     case RISCV::fixup_riscv_got_hi20:
68       return ELF::R_RISCV_GOT_HI20;
69     case RISCV::fixup_riscv_tls_got_hi20:
70       return ELF::R_RISCV_TLS_GOT_HI20;
71     case RISCV::fixup_riscv_tls_gd_hi20:
72       return ELF::R_RISCV_TLS_GD_HI20;
73     case RISCV::fixup_riscv_jal:
74       return ELF::R_RISCV_JAL;
75     case RISCV::fixup_riscv_branch:
76       return ELF::R_RISCV_BRANCH;
77     case RISCV::fixup_riscv_rvc_jump:
78       return ELF::R_RISCV_RVC_JUMP;
79     case RISCV::fixup_riscv_rvc_branch:
80       return ELF::R_RISCV_RVC_BRANCH;
81     case RISCV::fixup_riscv_call:
82       return ELF::R_RISCV_CALL;
83     case RISCV::fixup_riscv_call_plt:
84       return ELF::R_RISCV_CALL_PLT;
85     }
86   }
87 
88   switch (Kind) {
89   default:
90     llvm_unreachable("invalid fixup kind!");
91   case FK_Data_4:
92     if (Expr->getKind() == MCExpr::Target &&
93         cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL)
94       return ELF::R_RISCV_32_PCREL;
95     return ELF::R_RISCV_32;
96   case FK_Data_8:
97     return ELF::R_RISCV_64;
98   case FK_Data_Add_1:
99     return ELF::R_RISCV_ADD8;
100   case FK_Data_Add_2:
101     return ELF::R_RISCV_ADD16;
102   case FK_Data_Add_4:
103     return ELF::R_RISCV_ADD32;
104   case FK_Data_Add_8:
105     return ELF::R_RISCV_ADD64;
106   case FK_Data_Add_6b:
107     return ELF::R_RISCV_SET6;
108   case FK_Data_Sub_1:
109     return ELF::R_RISCV_SUB8;
110   case FK_Data_Sub_2:
111     return ELF::R_RISCV_SUB16;
112   case FK_Data_Sub_4:
113     return ELF::R_RISCV_SUB32;
114   case FK_Data_Sub_8:
115     return ELF::R_RISCV_SUB64;
116   case FK_Data_Sub_6b:
117     return ELF::R_RISCV_SUB6;
118   case RISCV::fixup_riscv_hi20:
119     return ELF::R_RISCV_HI20;
120   case RISCV::fixup_riscv_lo12_i:
121     return ELF::R_RISCV_LO12_I;
122   case RISCV::fixup_riscv_lo12_s:
123     return ELF::R_RISCV_LO12_S;
124   case RISCV::fixup_riscv_tprel_hi20:
125     return ELF::R_RISCV_TPREL_HI20;
126   case RISCV::fixup_riscv_tprel_lo12_i:
127     return ELF::R_RISCV_TPREL_LO12_I;
128   case RISCV::fixup_riscv_tprel_lo12_s:
129     return ELF::R_RISCV_TPREL_LO12_S;
130   case RISCV::fixup_riscv_tprel_add:
131     return ELF::R_RISCV_TPREL_ADD;
132   case RISCV::fixup_riscv_relax:
133     return ELF::R_RISCV_RELAX;
134   case RISCV::fixup_riscv_align:
135     return ELF::R_RISCV_ALIGN;
136   }
137 }
138 
139 std::unique_ptr<MCObjectTargetWriter>
140 llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
141   return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit);
142 }
143