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