1 | //===-- VEELFObjectWriter.cpp - VE 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 "VEFixupKinds.h" |
10 | #include "VEMCExpr.h" |
11 | #include "VEMCTargetDesc.h" |
12 | #include "llvm/MC/MCContext.h" |
13 | #include "llvm/MC/MCELFObjectWriter.h" |
14 | #include "llvm/MC/MCExpr.h" |
15 | #include "llvm/MC/MCObjectWriter.h" |
16 | #include "llvm/MC/MCValue.h" |
17 | #include "llvm/Support/ErrorHandling.h" |
18 | |
19 | using namespace llvm; |
20 | |
21 | namespace { |
22 | class VEELFObjectWriter : public MCELFObjectTargetWriter { |
23 | public: |
24 | VEELFObjectWriter(uint8_t OSABI) |
25 | : MCELFObjectTargetWriter(/* Is64Bit */ true, OSABI, ELF::EM_VE, |
26 | /* HasRelocationAddend */ true) {} |
27 | |
28 | ~VEELFObjectWriter() override = default; |
29 | |
30 | protected: |
31 | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
32 | const MCFixup &Fixup, bool IsPCRel) const override; |
33 | |
34 | bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, |
35 | unsigned Type) const override; |
36 | }; |
37 | } // namespace |
38 | |
39 | unsigned VEELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, |
40 | const MCFixup &Fixup, |
41 | bool IsPCRel) const { |
42 | if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Val: Fixup.getValue())) { |
43 | if (SExpr->getKind() == VEMCExpr::VK_VE_PC_LO32) |
44 | return ELF::R_VE_PC_LO32; |
45 | } |
46 | |
47 | if (IsPCRel) { |
48 | switch (Fixup.getTargetKind()) { |
49 | default: |
50 | Ctx.reportError(L: Fixup.getLoc(), Msg: "Unsupported pc-relative fixup kind" ); |
51 | return ELF::R_VE_NONE; |
52 | case FK_Data_1: |
53 | case FK_PCRel_1: |
54 | Ctx.reportError(L: Fixup.getLoc(), |
55 | Msg: "1-byte pc-relative data relocation is not supported" ); |
56 | return ELF::R_VE_NONE; |
57 | case FK_Data_2: |
58 | case FK_PCRel_2: |
59 | Ctx.reportError(L: Fixup.getLoc(), |
60 | Msg: "2-byte pc-relative data relocation is not supported" ); |
61 | return ELF::R_VE_NONE; |
62 | case FK_Data_4: |
63 | case FK_PCRel_4: |
64 | return ELF::R_VE_SREL32; |
65 | case FK_Data_8: |
66 | case FK_PCRel_8: |
67 | Ctx.reportError(L: Fixup.getLoc(), |
68 | Msg: "8-byte pc-relative data relocation is not supported" ); |
69 | return ELF::R_VE_NONE; |
70 | case VE::fixup_ve_reflong: |
71 | case VE::fixup_ve_srel32: |
72 | return ELF::R_VE_SREL32; |
73 | case VE::fixup_ve_pc_hi32: |
74 | return ELF::R_VE_PC_HI32; |
75 | case VE::fixup_ve_pc_lo32: |
76 | return ELF::R_VE_PC_LO32; |
77 | } |
78 | } |
79 | |
80 | switch (Fixup.getTargetKind()) { |
81 | default: |
82 | Ctx.reportError(L: Fixup.getLoc(), Msg: "Unknown ELF relocation type" ); |
83 | return ELF::R_VE_NONE; |
84 | case FK_Data_1: |
85 | Ctx.reportError(L: Fixup.getLoc(), Msg: "1-byte data relocation is not supported" ); |
86 | return ELF::R_VE_NONE; |
87 | case FK_Data_2: |
88 | Ctx.reportError(L: Fixup.getLoc(), Msg: "2-byte data relocation is not supported" ); |
89 | return ELF::R_VE_NONE; |
90 | case FK_Data_4: |
91 | return ELF::R_VE_REFLONG; |
92 | case FK_Data_8: |
93 | return ELF::R_VE_REFQUAD; |
94 | case VE::fixup_ve_reflong: |
95 | return ELF::R_VE_REFLONG; |
96 | case VE::fixup_ve_srel32: |
97 | Ctx.reportError(L: Fixup.getLoc(), |
98 | Msg: "A non pc-relative srel32 relocation is not supported" ); |
99 | return ELF::R_VE_NONE; |
100 | case VE::fixup_ve_hi32: |
101 | return ELF::R_VE_HI32; |
102 | case VE::fixup_ve_lo32: |
103 | return ELF::R_VE_LO32; |
104 | case VE::fixup_ve_pc_hi32: |
105 | Ctx.reportError(L: Fixup.getLoc(), |
106 | Msg: "A non pc-relative pc_hi32 relocation is not supported" ); |
107 | return ELF::R_VE_NONE; |
108 | case VE::fixup_ve_pc_lo32: |
109 | Ctx.reportError(L: Fixup.getLoc(), |
110 | Msg: "A non pc-relative pc_lo32 relocation is not supported" ); |
111 | return ELF::R_VE_NONE; |
112 | case VE::fixup_ve_got_hi32: |
113 | return ELF::R_VE_GOT_HI32; |
114 | case VE::fixup_ve_got_lo32: |
115 | return ELF::R_VE_GOT_LO32; |
116 | case VE::fixup_ve_gotoff_hi32: |
117 | return ELF::R_VE_GOTOFF_HI32; |
118 | case VE::fixup_ve_gotoff_lo32: |
119 | return ELF::R_VE_GOTOFF_LO32; |
120 | case VE::fixup_ve_plt_hi32: |
121 | return ELF::R_VE_PLT_HI32; |
122 | case VE::fixup_ve_plt_lo32: |
123 | return ELF::R_VE_PLT_LO32; |
124 | case VE::fixup_ve_tls_gd_hi32: |
125 | return ELF::R_VE_TLS_GD_HI32; |
126 | case VE::fixup_ve_tls_gd_lo32: |
127 | return ELF::R_VE_TLS_GD_LO32; |
128 | case VE::fixup_ve_tpoff_hi32: |
129 | return ELF::R_VE_TPOFF_HI32; |
130 | case VE::fixup_ve_tpoff_lo32: |
131 | return ELF::R_VE_TPOFF_LO32; |
132 | } |
133 | |
134 | return ELF::R_VE_NONE; |
135 | } |
136 | |
137 | bool VEELFObjectWriter::needsRelocateWithSymbol(const MCValue &, |
138 | const MCSymbol &, |
139 | unsigned Type) const { |
140 | switch (Type) { |
141 | default: |
142 | return false; |
143 | |
144 | // All relocations that use a GOT need a symbol, not an offset, as |
145 | // the offset of the symbol within the section is irrelevant to |
146 | // where the GOT entry is. Don't need to list all the TLS entries, |
147 | // as they're all marked as requiring a symbol anyways. |
148 | case ELF::R_VE_GOT_HI32: |
149 | case ELF::R_VE_GOT_LO32: |
150 | case ELF::R_VE_GOTOFF_HI32: |
151 | case ELF::R_VE_GOTOFF_LO32: |
152 | case ELF::R_VE_TLS_GD_HI32: |
153 | case ELF::R_VE_TLS_GD_LO32: |
154 | return true; |
155 | } |
156 | } |
157 | |
158 | std::unique_ptr<MCObjectTargetWriter> |
159 | llvm::createVEELFObjectWriter(uint8_t OSABI) { |
160 | return std::make_unique<VEELFObjectWriter>(args&: OSABI); |
161 | } |
162 | |