1 //===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer ---*- C++ -*---===//
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/LoongArchFixupKinds.h"
10 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
11 #include "llvm/BinaryFormat/ELF.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
18 using namespace llvm;
19
20 namespace {
21 class LoongArchELFObjectWriter : public MCELFObjectTargetWriter {
22 public:
23 LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool EnableRelax);
24
25 ~LoongArchELFObjectWriter() override;
26
needsRelocateWithSymbol(const MCValue & Val,const MCSymbol & Sym,unsigned Type) const27 bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
28 unsigned Type) const override {
29 return EnableRelax;
30 }
31
32 protected:
33 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
34 const MCFixup &Fixup, bool IsPCRel) const override;
35 bool EnableRelax;
36 };
37 } // end namespace
38
LoongArchELFObjectWriter(uint8_t OSABI,bool Is64Bit,bool EnableRelax)39 LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit,
40 bool EnableRelax)
41 : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH,
42 /*HasRelocationAddend=*/true),
43 EnableRelax(EnableRelax) {}
44
~LoongArchELFObjectWriter()45 LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {}
46
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const47 unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx,
48 const MCValue &Target,
49 const MCFixup &Fixup,
50 bool IsPCRel) const {
51 // Determine the type of the relocation
52 unsigned Kind = Fixup.getTargetKind();
53
54 if (Kind >= FirstLiteralRelocationKind)
55 return Kind - FirstLiteralRelocationKind;
56
57 switch (Kind) {
58 default:
59 Ctx.reportError(Fixup.getLoc(), "Unsupported relocation type");
60 return ELF::R_LARCH_NONE;
61 case FK_Data_1:
62 Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
63 return ELF::R_LARCH_NONE;
64 case FK_Data_2:
65 Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
66 return ELF::R_LARCH_NONE;
67 case FK_Data_4:
68 return IsPCRel ? ELF::R_LARCH_32_PCREL : ELF::R_LARCH_32;
69 case FK_Data_8:
70 return IsPCRel ? ELF::R_LARCH_64_PCREL : ELF::R_LARCH_64;
71 case LoongArch::fixup_loongarch_b16:
72 return ELF::R_LARCH_B16;
73 case LoongArch::fixup_loongarch_b21:
74 return ELF::R_LARCH_B21;
75 case LoongArch::fixup_loongarch_b26:
76 return ELF::R_LARCH_B26;
77 case LoongArch::fixup_loongarch_abs_hi20:
78 return ELF::R_LARCH_ABS_HI20;
79 case LoongArch::fixup_loongarch_abs_lo12:
80 return ELF::R_LARCH_ABS_LO12;
81 case LoongArch::fixup_loongarch_abs64_lo20:
82 return ELF::R_LARCH_ABS64_LO20;
83 case LoongArch::fixup_loongarch_abs64_hi12:
84 return ELF::R_LARCH_ABS64_HI12;
85 case LoongArch::fixup_loongarch_tls_le_hi20:
86 return ELF::R_LARCH_TLS_LE_HI20;
87 case LoongArch::fixup_loongarch_tls_le_lo12:
88 return ELF::R_LARCH_TLS_LE_LO12;
89 case LoongArch::fixup_loongarch_tls_le64_lo20:
90 return ELF::R_LARCH_TLS_LE64_LO20;
91 case LoongArch::fixup_loongarch_tls_le64_hi12:
92 return ELF::R_LARCH_TLS_LE64_HI12;
93 case LoongArch::fixup_loongarch_call36:
94 return ELF::R_LARCH_CALL36;
95 // TODO: Handle more fixup-kinds.
96 }
97 }
98
99 std::unique_ptr<MCObjectTargetWriter>
createLoongArchELFObjectWriter(uint8_t OSABI,bool Is64Bit,bool Relax)100 llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit, bool Relax) {
101 return std::make_unique<LoongArchELFObjectWriter>(OSABI, Is64Bit, Relax);
102 }
103