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