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