1//===-- HexagonAsmBackend.cpp - Hexagon Assembler Backend -----------------===//
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 "HexagonFixupKinds.h"
10#include "MCTargetDesc/HexagonBaseInfo.h"
11#include "MCTargetDesc/HexagonMCChecker.h"
12#include "MCTargetDesc/HexagonMCCodeEmitter.h"
13#include "MCTargetDesc/HexagonMCInstrInfo.h"
14#include "MCTargetDesc/HexagonMCShuffler.h"
15#include "MCTargetDesc/HexagonMCTargetDesc.h"
16#include "llvm/ADT/StringSwitch.h"
17#include "llvm/MC/MCAsmBackend.h"
18#include "llvm/MC/MCAssembler.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCELFObjectWriter.h"
21#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCObjectWriter.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/TargetRegistry.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/EndianStream.h"
27
28#include <sstream>
29
30using namespace llvm;
31using namespace Hexagon;
32
33#define DEBUG_TYPE "hexagon-asm-backend"
34
35static cl::opt<bool> DisableFixup
36 ("mno-fixup", cl::desc("Disable fixing up resolved relocations for Hexagon"));
37
38namespace {
39
40class HexagonAsmBackend : public MCAsmBackend {
41 uint8_t OSABI;
42 StringRef CPU;
43 mutable uint64_t relaxedCnt;
44 mutable MCInst RelaxedMCB;
45 std::unique_ptr <MCInstrInfo> MCII;
46 std::unique_ptr <MCInst *> RelaxTarget;
47 MCInst * Extender;
48 unsigned MaxPacketSize;
49
50 void ReplaceInstruction(MCCodeEmitter &E, MCFragment &RF, MCInst &HMB) const {
51 SmallVector<MCFixup, 4> Fixups;
52 SmallString<256> Code;
53 E.encodeInstruction(Inst: HMB, CB&: Code, Fixups, STI: *RF.getSubtargetInfo());
54
55 // Update the fragment.
56 RF.setInst(HMB);
57 RF.setVarContents(Code);
58 RF.setVarFixups(Fixups);
59 }
60
61public:
62 HexagonAsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
63 StringRef CPU)
64 : MCAsmBackend(llvm::endianness::little), OSABI(OSABI), CPU(CPU),
65 relaxedCnt(0), MCII(T.createMCInstrInfo()), RelaxTarget(new MCInst *),
66 Extender(nullptr), MaxPacketSize(HexagonMCInstrInfo::packetSize(CPU)) {}
67
68 std::unique_ptr<MCObjectTargetWriter>
69 createObjectTargetWriter() const override {
70 return createHexagonELFObjectWriter(OSABI, CPU);
71 }
72
73 void setExtender(MCContext &Context) const {
74 if (Extender == nullptr)
75 const_cast<HexagonAsmBackend *>(this)->Extender = Context.createMCInst();
76 }
77
78 MCInst *takeExtender() const {
79 assert(Extender != nullptr);
80 MCInst * Result = Extender;
81 const_cast<HexagonAsmBackend *>(this)->Extender = nullptr;
82 return Result;
83 }
84
85 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override {
86 unsigned Type = llvm::StringSwitch<unsigned>(Name)
87#define ELF_RELOC(X, Y) .Case(#X, Y)
88#include "llvm/BinaryFormat/ELFRelocs/Hexagon.def"
89#undef ELF_RELOC
90 .Case(S: "BFD_RELOC_NONE", Value: ELF::R_HEX_NONE)
91 .Case(S: "BFD_RELOC_8", Value: ELF::R_HEX_8)
92 .Case(S: "BFD_RELOC_16", Value: ELF::R_HEX_16)
93 .Case(S: "BFD_RELOC_32", Value: ELF::R_HEX_32)
94 .Default(Value: -1u);
95 if (Type == -1u)
96 return std::nullopt;
97 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
98 }
99
100 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override {
101 // clang-format off
102 const static MCFixupKindInfo Infos[Hexagon::NumTargetFixupKinds] = {
103 // This table *must* be in same the order of fixup_* kinds in
104 // HexagonFixupKinds.h.
105 //
106 // namei offset bits flags
107 { .Name: "fixup_Hexagon_B22_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
108 { .Name: "fixup_Hexagon_B15_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
109 { .Name: "fixup_Hexagon_B7_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
110 { .Name: "fixup_Hexagon_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
111 { .Name: "fixup_Hexagon_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
112 { .Name: "fixup_Hexagon_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
113 { .Name: "fixup_Hexagon_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
114 { .Name: "fixup_Hexagon_8", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
115 { .Name: "fixup_Hexagon_GPREL16_0", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
116 { .Name: "fixup_Hexagon_GPREL16_1", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
117 { .Name: "fixup_Hexagon_GPREL16_2", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
118 { .Name: "fixup_Hexagon_GPREL16_3", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
119 { .Name: "fixup_Hexagon_HL16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
120 { .Name: "fixup_Hexagon_B13_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
121 { .Name: "fixup_Hexagon_B9_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
122 { .Name: "fixup_Hexagon_B32_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
123 { .Name: "fixup_Hexagon_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
124 { .Name: "fixup_Hexagon_B22_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
125 { .Name: "fixup_Hexagon_B15_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
126 { .Name: "fixup_Hexagon_B13_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
127 { .Name: "fixup_Hexagon_B9_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
128 { .Name: "fixup_Hexagon_B7_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
129 { .Name: "fixup_Hexagon_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
130 { .Name: "fixup_Hexagon_12_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
131 { .Name: "fixup_Hexagon_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
132 { .Name: "fixup_Hexagon_10_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
133 { .Name: "fixup_Hexagon_9_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
134 { .Name: "fixup_Hexagon_8_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
135 { .Name: "fixup_Hexagon_7_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
136 { .Name: "fixup_Hexagon_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
137 { .Name: "fixup_Hexagon_32_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
138 { .Name: "fixup_Hexagon_COPY", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
139 { .Name: "fixup_Hexagon_GLOB_DAT", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
140 { .Name: "fixup_Hexagon_JMP_SLOT", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
141 { .Name: "fixup_Hexagon_RELATIVE", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
142 { .Name: "fixup_Hexagon_PLT_B22_PCREL", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
143 { .Name: "fixup_Hexagon_GOTREL_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
144 { .Name: "fixup_Hexagon_GOTREL_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
145 { .Name: "fixup_Hexagon_GOTREL_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
146 { .Name: "fixup_Hexagon_GOT_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
147 { .Name: "fixup_Hexagon_GOT_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
148 { .Name: "fixup_Hexagon_GOT_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
149 { .Name: "fixup_Hexagon_GOT_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
150 { .Name: "fixup_Hexagon_DTPMOD_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
151 { .Name: "fixup_Hexagon_DTPREL_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
152 { .Name: "fixup_Hexagon_DTPREL_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
153 { .Name: "fixup_Hexagon_DTPREL_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
154 { .Name: "fixup_Hexagon_DTPREL_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
155 { .Name: "fixup_Hexagon_GD_PLT_B22_PCREL",.TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
156 { .Name: "fixup_Hexagon_LD_PLT_B22_PCREL",.TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
157 { .Name: "fixup_Hexagon_GD_GOT_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
158 { .Name: "fixup_Hexagon_GD_GOT_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
159 { .Name: "fixup_Hexagon_GD_GOT_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
160 { .Name: "fixup_Hexagon_GD_GOT_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
161 { .Name: "fixup_Hexagon_LD_GOT_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
162 { .Name: "fixup_Hexagon_LD_GOT_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
163 { .Name: "fixup_Hexagon_LD_GOT_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
164 { .Name: "fixup_Hexagon_LD_GOT_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
165 { .Name: "fixup_Hexagon_IE_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
166 { .Name: "fixup_Hexagon_IE_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
167 { .Name: "fixup_Hexagon_IE_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
168 { .Name: "fixup_Hexagon_IE_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
169 { .Name: "fixup_Hexagon_IE_GOT_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
170 { .Name: "fixup_Hexagon_IE_GOT_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
171 { .Name: "fixup_Hexagon_IE_GOT_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
172 { .Name: "fixup_Hexagon_IE_GOT_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
173 { .Name: "fixup_Hexagon_TPREL_LO16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
174 { .Name: "fixup_Hexagon_TPREL_HI16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
175 { .Name: "fixup_Hexagon_TPREL_32", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
176 { .Name: "fixup_Hexagon_TPREL_16", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
177 { .Name: "fixup_Hexagon_6_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
178 { .Name: "fixup_Hexagon_GOTREL_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
179 { .Name: "fixup_Hexagon_GOTREL_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
180 { .Name: "fixup_Hexagon_GOTREL_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
181 { .Name: "fixup_Hexagon_GOT_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
182 { .Name: "fixup_Hexagon_GOT_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
183 { .Name: "fixup_Hexagon_GOT_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
184 { .Name: "fixup_Hexagon_DTPREL_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
185 { .Name: "fixup_Hexagon_DTPREL_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
186 { .Name: "fixup_Hexagon_DTPREL_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
187 { .Name: "fixup_Hexagon_GD_GOT_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
188 { .Name: "fixup_Hexagon_GD_GOT_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
189 { .Name: "fixup_Hexagon_GD_GOT_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
190 { .Name: "fixup_Hexagon_LD_GOT_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
191 { .Name: "fixup_Hexagon_LD_GOT_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
192 { .Name: "fixup_Hexagon_LD_GOT_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
193 { .Name: "fixup_Hexagon_IE_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
194 { .Name: "fixup_Hexagon_IE_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
195 { .Name: "fixup_Hexagon_IE_GOT_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
196 { .Name: "fixup_Hexagon_IE_GOT_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
197 { .Name: "fixup_Hexagon_IE_GOT_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
198 { .Name: "fixup_Hexagon_TPREL_32_6_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
199 { .Name: "fixup_Hexagon_TPREL_16_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
200 { .Name: "fixup_Hexagon_TPREL_11_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
201 { .Name: "fixup_Hexagon_GD_PLT_B22_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
202 { .Name: "fixup_Hexagon_GD_PLT_B32_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
203 { .Name: "fixup_Hexagon_LD_PLT_B22_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
204 { .Name: "fixup_Hexagon_LD_PLT_B32_PCREL_X", .TargetOffset: 0, .TargetSize: 32, .Flags: 0 },
205 };
206 // clang-format on
207
208 if (Kind < FirstTargetFixupKind)
209 return MCAsmBackend::getFixupKindInfo(Kind);
210
211 assert(unsigned(Kind - FirstTargetFixupKind) <
212 Hexagon::NumTargetFixupKinds &&
213 "Invalid kind!");
214 return Infos[Kind - FirstTargetFixupKind];
215 }
216
217 bool shouldForceRelocation(const MCFixup &Fixup) {
218 switch(Fixup.getKind()) {
219 default:
220 llvm_unreachable("Unknown Fixup Kind!");
221
222 case fixup_Hexagon_LO16:
223 case fixup_Hexagon_HI16:
224 case fixup_Hexagon_16:
225 case fixup_Hexagon_8:
226 case fixup_Hexagon_GPREL16_0:
227 case fixup_Hexagon_GPREL16_1:
228 case fixup_Hexagon_GPREL16_2:
229 case fixup_Hexagon_GPREL16_3:
230 case fixup_Hexagon_HL16:
231 case fixup_Hexagon_32_6_X:
232 case fixup_Hexagon_16_X:
233 case fixup_Hexagon_12_X:
234 case fixup_Hexagon_11_X:
235 case fixup_Hexagon_10_X:
236 case fixup_Hexagon_9_X:
237 case fixup_Hexagon_8_X:
238 case fixup_Hexagon_7_X:
239 case fixup_Hexagon_6_X:
240 case fixup_Hexagon_COPY:
241 case fixup_Hexagon_GLOB_DAT:
242 case fixup_Hexagon_JMP_SLOT:
243 case fixup_Hexagon_RELATIVE:
244 case fixup_Hexagon_PLT_B22_PCREL:
245 case fixup_Hexagon_GOTREL_LO16:
246 case fixup_Hexagon_GOTREL_HI16:
247 case fixup_Hexagon_GOTREL_32:
248 case fixup_Hexagon_GOT_LO16:
249 case fixup_Hexagon_GOT_HI16:
250 case fixup_Hexagon_GOT_32:
251 case fixup_Hexagon_GOT_16:
252 case fixup_Hexagon_DTPMOD_32:
253 case fixup_Hexagon_DTPREL_LO16:
254 case fixup_Hexagon_DTPREL_HI16:
255 case fixup_Hexagon_DTPREL_32:
256 case fixup_Hexagon_DTPREL_16:
257 case fixup_Hexagon_GD_PLT_B22_PCREL:
258 case fixup_Hexagon_LD_PLT_B22_PCREL:
259 case fixup_Hexagon_GD_GOT_LO16:
260 case fixup_Hexagon_GD_GOT_HI16:
261 case fixup_Hexagon_GD_GOT_32:
262 case fixup_Hexagon_GD_GOT_16:
263 case fixup_Hexagon_LD_GOT_LO16:
264 case fixup_Hexagon_LD_GOT_HI16:
265 case fixup_Hexagon_LD_GOT_32:
266 case fixup_Hexagon_LD_GOT_16:
267 case fixup_Hexagon_IE_LO16:
268 case fixup_Hexagon_IE_HI16:
269 case fixup_Hexagon_IE_32:
270 case fixup_Hexagon_IE_16:
271 case fixup_Hexagon_IE_GOT_LO16:
272 case fixup_Hexagon_IE_GOT_HI16:
273 case fixup_Hexagon_IE_GOT_32:
274 case fixup_Hexagon_IE_GOT_16:
275 case fixup_Hexagon_TPREL_LO16:
276 case fixup_Hexagon_TPREL_HI16:
277 case fixup_Hexagon_TPREL_32:
278 case fixup_Hexagon_TPREL_16:
279 case fixup_Hexagon_GOTREL_32_6_X:
280 case fixup_Hexagon_GOTREL_16_X:
281 case fixup_Hexagon_GOTREL_11_X:
282 case fixup_Hexagon_GOT_32_6_X:
283 case fixup_Hexagon_GOT_16_X:
284 case fixup_Hexagon_GOT_11_X:
285 case fixup_Hexagon_DTPREL_32_6_X:
286 case fixup_Hexagon_DTPREL_16_X:
287 case fixup_Hexagon_DTPREL_11_X:
288 case fixup_Hexagon_GD_GOT_32_6_X:
289 case fixup_Hexagon_GD_GOT_16_X:
290 case fixup_Hexagon_GD_GOT_11_X:
291 case fixup_Hexagon_LD_GOT_32_6_X:
292 case fixup_Hexagon_LD_GOT_16_X:
293 case fixup_Hexagon_LD_GOT_11_X:
294 case fixup_Hexagon_IE_32_6_X:
295 case fixup_Hexagon_IE_16_X:
296 case fixup_Hexagon_IE_GOT_32_6_X:
297 case fixup_Hexagon_IE_GOT_16_X:
298 case fixup_Hexagon_IE_GOT_11_X:
299 case fixup_Hexagon_TPREL_32_6_X:
300 case fixup_Hexagon_TPREL_16_X:
301 case fixup_Hexagon_TPREL_11_X:
302 case fixup_Hexagon_32_PCREL:
303 case fixup_Hexagon_6_PCREL_X:
304 case fixup_Hexagon_23_REG:
305 case fixup_Hexagon_27_REG:
306 case fixup_Hexagon_GD_PLT_B22_PCREL_X:
307 case fixup_Hexagon_GD_PLT_B32_PCREL_X:
308 case fixup_Hexagon_LD_PLT_B22_PCREL_X:
309 case fixup_Hexagon_LD_PLT_B32_PCREL_X:
310 // These relocations should always have a relocation recorded
311 return true;
312
313 case fixup_Hexagon_B22_PCREL:
314 //IsResolved = false;
315 break;
316
317 case fixup_Hexagon_B13_PCREL:
318 case fixup_Hexagon_B13_PCREL_X:
319 case fixup_Hexagon_B32_PCREL_X:
320 case fixup_Hexagon_B22_PCREL_X:
321 case fixup_Hexagon_B15_PCREL:
322 case fixup_Hexagon_B15_PCREL_X:
323 case fixup_Hexagon_B9_PCREL:
324 case fixup_Hexagon_B9_PCREL_X:
325 case fixup_Hexagon_B7_PCREL:
326 case fixup_Hexagon_B7_PCREL_X:
327 if (DisableFixup)
328 return true;
329 break;
330
331 case FK_Data_1:
332 case FK_Data_2:
333 case FK_Data_4:
334 case fixup_Hexagon_32:
335 // Leave these relocations alone as they are used for EH.
336 return false;
337 }
338 return false;
339 }
340
341 /// getFixupKindNumBytes - The number of bytes the fixup may change.
342 static unsigned getFixupKindNumBytes(unsigned Kind) {
343 switch (Kind) {
344 default:
345 return 0;
346
347 case FK_Data_1:
348 return 1;
349 case FK_Data_2:
350 return 2;
351 case FK_Data_4: // this later gets mapped to R_HEX_32 or R_HEX_32_PCREL
352 case fixup_Hexagon_32:
353 case fixup_Hexagon_B32_PCREL_X:
354 case fixup_Hexagon_B22_PCREL:
355 case fixup_Hexagon_B22_PCREL_X:
356 case fixup_Hexagon_B15_PCREL:
357 case fixup_Hexagon_B15_PCREL_X:
358 case fixup_Hexagon_B13_PCREL:
359 case fixup_Hexagon_B13_PCREL_X:
360 case fixup_Hexagon_B9_PCREL:
361 case fixup_Hexagon_B9_PCREL_X:
362 case fixup_Hexagon_B7_PCREL:
363 case fixup_Hexagon_B7_PCREL_X:
364 case fixup_Hexagon_GD_PLT_B32_PCREL_X:
365 case fixup_Hexagon_LD_PLT_B32_PCREL_X:
366 return 4;
367 }
368 }
369
370 // Make up for left shift when encoding the operand.
371 static uint64_t adjustFixupValue(MCFixupKind Kind, uint64_t Value) {
372 switch((unsigned)Kind) {
373 default:
374 break;
375
376 case fixup_Hexagon_B7_PCREL:
377 case fixup_Hexagon_B9_PCREL:
378 case fixup_Hexagon_B13_PCREL:
379 case fixup_Hexagon_B15_PCREL:
380 case fixup_Hexagon_B22_PCREL:
381 Value >>= 2;
382 break;
383
384 case fixup_Hexagon_B7_PCREL_X:
385 case fixup_Hexagon_B9_PCREL_X:
386 case fixup_Hexagon_B13_PCREL_X:
387 case fixup_Hexagon_B15_PCREL_X:
388 case fixup_Hexagon_B22_PCREL_X:
389 Value &= 0x3f;
390 break;
391
392 case fixup_Hexagon_B32_PCREL_X:
393 case fixup_Hexagon_GD_PLT_B32_PCREL_X:
394 case fixup_Hexagon_LD_PLT_B32_PCREL_X:
395 Value >>= 6;
396 break;
397 }
398 return (Value);
399 }
400
401 void HandleFixupError(const int bits, const int align_bits,
402 const int64_t FixupValue, const char *fixupStr) const {
403 // Error: value 1124 out of range: -1024-1023 when resolving
404 // symbol in file xprtsock.S
405 const APInt IntMin = APInt::getSignedMinValue(numBits: bits+align_bits);
406 const APInt IntMax = APInt::getSignedMaxValue(numBits: bits+align_bits);
407 std::stringstream errStr;
408 errStr << "\nError: value " <<
409 FixupValue <<
410 " out of range: " <<
411 IntMin.getSExtValue() <<
412 "-" <<
413 IntMax.getSExtValue() <<
414 " when resolving " <<
415 fixupStr <<
416 " fixup\n";
417 llvm_unreachable(errStr.str().c_str());
418 }
419
420 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &,
421 uint8_t *Data, uint64_t FixupValue, bool IsResolved) override;
422
423 bool isInstRelaxable(MCInst const &HMI) const {
424 const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII: *MCII, MCI: HMI);
425 bool Relaxable = false;
426 // Branches and loop-setup insns are handled as necessary by relaxation.
427 if (llvm::HexagonMCInstrInfo::getType(MCII: *MCII, MCI: HMI) == HexagonII::TypeJ ||
428 (llvm::HexagonMCInstrInfo::getType(MCII: *MCII, MCI: HMI) == HexagonII::TypeCJ &&
429 MCID.isBranch()) ||
430 (llvm::HexagonMCInstrInfo::getType(MCII: *MCII, MCI: HMI) == HexagonII::TypeNCJ &&
431 MCID.isBranch()) ||
432 (llvm::HexagonMCInstrInfo::getType(MCII: *MCII, MCI: HMI) == HexagonII::TypeCR &&
433 HMI.getOpcode() != Hexagon::C4_addipc))
434 if (HexagonMCInstrInfo::isExtendable(MCII: *MCII, MCI: HMI)) {
435 Relaxable = true;
436 MCOperand const &Operand =
437 HMI.getOperand(i: HexagonMCInstrInfo::getExtendableOp(MCII: *MCII, MCI: HMI));
438 if (HexagonMCInstrInfo::mustNotExtend(Expr: *Operand.getExpr()))
439 Relaxable = false;
440 }
441
442 return Relaxable;
443 }
444
445 bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,
446 const MCSubtargetInfo &STI) const override {
447 RelaxedMCB.clear();
448 RelaxedMCB.setOpcode(Opcode);
449 RelaxedMCB.setOperands(Operands);
450 return true;
451 }
452
453 /// fixupNeedsRelaxation - Target specific predicate for whether a given
454 /// fixup requires the associated instruction to be relaxed.
455 bool fixupNeedsRelaxationAdvanced(const MCFragment &F, const MCFixup &Fixup,
456 const MCValue &, uint64_t Value,
457 bool Resolved) const override {
458 MCInst const &MCB = RelaxedMCB;
459 assert(HexagonMCInstrInfo::isBundle(MCB));
460
461 *RelaxTarget = nullptr;
462 MCInst &MCI = const_cast<MCInst &>(HexagonMCInstrInfo::instruction(
463 MCB, Index: (Fixup.getOffset() - F.getFixedSize()) / HEXAGON_INSTR_SIZE));
464 bool Relaxable = isInstRelaxable(HMI: MCI);
465 if (Relaxable == false)
466 return false;
467 // If we cannot resolve the fixup value, it requires relaxation.
468 if (!Resolved) {
469 switch (Fixup.getKind()) {
470 case fixup_Hexagon_B22_PCREL:
471 // GetFixupCount assumes B22 won't relax
472 [[fallthrough]];
473 default:
474 return false;
475 break;
476 case fixup_Hexagon_B13_PCREL:
477 case fixup_Hexagon_B15_PCREL:
478 case fixup_Hexagon_B9_PCREL:
479 case fixup_Hexagon_B7_PCREL: {
480 if (HexagonMCInstrInfo::bundleSize(MCI: MCB) < HEXAGON_PACKET_SIZE) {
481 ++relaxedCnt;
482 *RelaxTarget = &MCI;
483 setExtender(getContext());
484 return true;
485 } else {
486 return false;
487 }
488 break;
489 }
490 }
491 }
492
493 MCFixupKind Kind = Fixup.getKind();
494 int64_t sValue = Value;
495 int64_t maxValue;
496
497 switch ((unsigned)Kind) {
498 case fixup_Hexagon_B7_PCREL:
499 maxValue = 1 << 8;
500 break;
501 case fixup_Hexagon_B9_PCREL:
502 maxValue = 1 << 10;
503 break;
504 case fixup_Hexagon_B15_PCREL:
505 maxValue = 1 << 16;
506 break;
507 case fixup_Hexagon_B22_PCREL:
508 maxValue = 1 << 23;
509 break;
510 default:
511 maxValue = INT64_MAX;
512 break;
513 }
514
515 bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;
516
517 if (isFarAway) {
518 if (HexagonMCInstrInfo::bundleSize(MCI: MCB) < HEXAGON_PACKET_SIZE) {
519 ++relaxedCnt;
520 *RelaxTarget = &MCI;
521 setExtender(getContext());
522 return true;
523 }
524 }
525
526 return false;
527 }
528
529 void relaxInstruction(MCInst &Inst,
530 const MCSubtargetInfo &STI) const override {
531 assert(HexagonMCInstrInfo::isBundle(Inst) &&
532 "Hexagon relaxInstruction only works on bundles");
533
534 MCInst Res;
535 Res.setOpcode(Hexagon::BUNDLE);
536 Res.addOperand(Op: MCOperand::createImm(Val: Inst.getOperand(i: 0).getImm()));
537 // Copy the results into the bundle.
538 bool Update = false;
539 for (auto &I : HexagonMCInstrInfo::bundleInstructions(MCI: Inst)) {
540 MCInst &CrntHMI = const_cast<MCInst &>(*I.getInst());
541
542 // if immediate extender needed, add it in
543 if (*RelaxTarget == &CrntHMI) {
544 Update = true;
545 assert((HexagonMCInstrInfo::bundleSize(Res) < HEXAGON_PACKET_SIZE) &&
546 "No room to insert extender for relaxation");
547
548 MCInst *HMIx = takeExtender();
549 *HMIx = HexagonMCInstrInfo::deriveExtender(
550 MCII: *MCII, Inst: CrntHMI,
551 MO: HexagonMCInstrInfo::getExtendableOperand(MCII: *MCII, MCI: CrntHMI));
552 Res.addOperand(Op: MCOperand::createInst(Val: HMIx));
553 *RelaxTarget = nullptr;
554 }
555 // now copy over the original instruction(the one we may have extended)
556 Res.addOperand(Op: MCOperand::createInst(Val: I.getInst()));
557 }
558
559 Inst = std::move(Res);
560 (void)Update;
561 assert(Update && "Didn't find relaxation target");
562 }
563
564 bool writeNopData(raw_ostream &OS, uint64_t Count,
565 const MCSubtargetInfo *STI) const override {
566 static const uint32_t Nopcode = 0x7f000000, // Hard-coded NOP.
567 ParseIn = 0x00004000, // In packet parse-bits.
568 ParseEnd = 0x0000c000; // End of packet parse-bits.
569
570 while (Count % HEXAGON_INSTR_SIZE) {
571 LLVM_DEBUG(dbgs() << "Alignment not a multiple of the instruction size:"
572 << Count % HEXAGON_INSTR_SIZE << "/"
573 << HEXAGON_INSTR_SIZE << "\n");
574 --Count;
575 OS << '\0';
576 }
577
578 while (Count) {
579 Count -= HEXAGON_INSTR_SIZE;
580 // Close the packet whenever a multiple of the maximum packet size remains
581 uint32_t ParseBits = (Count % (MaxPacketSize * HEXAGON_INSTR_SIZE)) ?
582 ParseIn : ParseEnd;
583 support::endian::write<uint32_t>(os&: OS, value: Nopcode | ParseBits, endian: Endian);
584 }
585 return true;
586 }
587
588 bool finishLayout() const override {
589 SmallVector<MCFragment *> Frags;
590 for (MCSection &Sec : *Asm) {
591 Frags.clear();
592 for (MCFragment &F : Sec)
593 Frags.push_back(Elt: &F);
594 for (size_t J = 0, E = Frags.size(); J != E; ++J) {
595 switch (Frags[J]->getKind()) {
596 default:
597 break;
598 case MCFragment::FT_Align: {
599 auto Size = Asm->computeFragmentSize(F: *Frags[J]);
600 for (auto K = J; K != 0 && Size >= HEXAGON_PACKET_SIZE;) {
601 --K;
602 switch (Frags[K]->getKind()) {
603 default:
604 break;
605 case MCFragment::FT_Align: {
606 // Don't pad before other alignments
607 Size = 0;
608 break;
609 }
610 case MCFragment::FT_Relaxable: {
611 MCContext &Context = getContext();
612 auto &RF = *Frags[K];
613 MCInst Inst = RF.getInst();
614
615 // Don't add nops to packets that have fixups, as reshuffling can
616 // invalidate fixup offsets.
617 if (!RF.getVarFixups().empty()) {
618 Size = 0;
619 break;
620 }
621
622 const bool WouldTraverseLabel = llvm::any_of(
623 Range: Asm->symbols(), P: [&RF, &Inst, Asm = Asm](MCSymbol const &sym) {
624 uint64_t Offset = 0;
625 const bool HasOffset = Asm->getSymbolOffset(S: sym, Val&: Offset);
626 const unsigned PacketSizeBytes =
627 HexagonMCInstrInfo::bundleSize(MCI: Inst) *
628 HEXAGON_INSTR_SIZE;
629 const bool OffsetPastSym =
630 Offset <= Asm->getFragmentOffset(F: RF) + PacketSizeBytes;
631 return !sym.isVariable() && Offset != 0 && HasOffset &&
632 OffsetPastSym;
633 });
634 if (WouldTraverseLabel) {
635 Size = 0;
636 break;
637 }
638
639 while (Size > 0 &&
640 HexagonMCInstrInfo::bundleSize(MCI: Inst) < MaxPacketSize) {
641 MCInst *Nop = Context.createMCInst();
642 Nop->setOpcode(Hexagon::A2_nop);
643 Inst.addOperand(Op: MCOperand::createInst(Val: Nop));
644 Size -= 4;
645 if (!HexagonMCChecker(
646 Context, *MCII, *RF.getSubtargetInfo(), Inst,
647 *Context.getRegisterInfo(), false)
648 .check()) {
649 Inst.erase(I: Inst.end() - 1);
650 Size = 0;
651 }
652 }
653 bool Error = HexagonMCShuffle(Context, ReportErrors: true, MCII: *MCII,
654 STI: *RF.getSubtargetInfo(), MCB&: Inst);
655 //assert(!Error);
656 (void)Error;
657 ReplaceInstruction(E&: Asm->getEmitter(), RF, HMB&: Inst);
658 Size = 0; // Only look back one instruction
659 break;
660 }
661 }
662 }
663 }
664 }
665 }
666 }
667 return true;
668 }
669}; // class HexagonAsmBackend
670
671} // namespace
672
673void HexagonAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
674 const MCValue &Target, uint8_t *InstAddr,
675 uint64_t FixupValue, bool IsResolved) {
676 if (IsResolved && shouldForceRelocation(Fixup))
677 IsResolved = false;
678 maybeAddReloc(F, Fixup, Target, Value&: FixupValue, IsResolved);
679 // When FixupValue is 0 the relocation is external and there
680 // is nothing for us to do.
681 if (!FixupValue)
682 return;
683
684 MCFixupKind Kind = Fixup.getKind();
685 uint64_t Value;
686 uint32_t InstMask;
687 uint32_t Reloc;
688
689 // LLVM gives us an encoded value, we have to convert it back
690 // to a real offset before we can use it.
691 unsigned NumBytes = getFixupKindNumBytes(Kind);
692 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
693 "Invalid fixup offset!");
694
695 Value = adjustFixupValue(Kind, Value: FixupValue);
696 if (!Value)
697 return;
698 int sValue = (int)Value;
699
700 switch ((unsigned)Kind) {
701 default:
702 return;
703
704 case fixup_Hexagon_B7_PCREL:
705 if (!(isIntN(N: 7, x: sValue)))
706 HandleFixupError(bits: 7, align_bits: 2, FixupValue: (int64_t)FixupValue, fixupStr: "B7_PCREL");
707 [[fallthrough]];
708 case fixup_Hexagon_B7_PCREL_X:
709 InstMask = 0x00001f18; // Word32_B7
710 Reloc = (((Value >> 2) & 0x1f) << 8) | // Value 6-2 = Target 12-8
711 ((Value & 0x3) << 3); // Value 1-0 = Target 4-3
712 break;
713
714 case fixup_Hexagon_B9_PCREL:
715 if (!(isIntN(N: 9, x: sValue)))
716 HandleFixupError(bits: 9, align_bits: 2, FixupValue: (int64_t)FixupValue, fixupStr: "B9_PCREL");
717 [[fallthrough]];
718 case fixup_Hexagon_B9_PCREL_X:
719 InstMask = 0x003000fe; // Word32_B9
720 Reloc = (((Value >> 7) & 0x3) << 20) | // Value 8-7 = Target 21-20
721 ((Value & 0x7f) << 1); // Value 6-0 = Target 7-1
722 break;
723
724 // Since the existing branches that use this relocation cannot be
725 // extended, they should only be fixed up if the target is within range.
726 case fixup_Hexagon_B13_PCREL:
727 if (!(isIntN(N: 13, x: sValue)))
728 HandleFixupError(bits: 13, align_bits: 2, FixupValue: (int64_t)FixupValue, fixupStr: "B13_PCREL");
729 [[fallthrough]];
730 case fixup_Hexagon_B13_PCREL_X:
731 InstMask = 0x00202ffe; // Word32_B13
732 Reloc = (((Value >> 12) & 0x1) << 21) | // Value 12 = Target 21
733 (((Value >> 11) & 0x1) << 13) | // Value 11 = Target 13
734 ((Value & 0x7ff) << 1); // Value 10-0 = Target 11-1
735 break;
736
737 case fixup_Hexagon_B15_PCREL:
738 if (!(isIntN(N: 15, x: sValue)))
739 HandleFixupError(bits: 15, align_bits: 2, FixupValue: (int64_t)FixupValue, fixupStr: "B15_PCREL");
740 [[fallthrough]];
741 case fixup_Hexagon_B15_PCREL_X:
742 InstMask = 0x00df20fe; // Word32_B15
743 Reloc = (((Value >> 13) & 0x3) << 22) | // Value 14-13 = Target 23-22
744 (((Value >> 8) & 0x1f) << 16) | // Value 12-8 = Target 20-16
745 (((Value >> 7) & 0x1) << 13) | // Value 7 = Target 13
746 ((Value & 0x7f) << 1); // Value 6-0 = Target 7-1
747 break;
748
749 case fixup_Hexagon_B22_PCREL:
750 if (!(isIntN(N: 22, x: sValue)))
751 HandleFixupError(bits: 22, align_bits: 2, FixupValue: (int64_t)FixupValue, fixupStr: "B22_PCREL");
752 [[fallthrough]];
753 case fixup_Hexagon_B22_PCREL_X:
754 InstMask = 0x01ff3ffe; // Word32_B22
755 Reloc = (((Value >> 13) & 0x1ff) << 16) | // Value 21-13 = Target 24-16
756 ((Value & 0x1fff) << 1); // Value 12-0 = Target 13-1
757 break;
758
759 case fixup_Hexagon_B32_PCREL_X:
760 InstMask = 0x0fff3fff; // Word32_X26
761 Reloc = (((Value >> 14) & 0xfff) << 16) | // Value 25-14 = Target 27-16
762 (Value & 0x3fff); // Value 13-0 = Target 13-0
763 break;
764
765 case FK_Data_1:
766 case FK_Data_2:
767 case FK_Data_4:
768 case fixup_Hexagon_32:
769 InstMask = 0xffffffff; // Word32
770 Reloc = Value;
771 break;
772 }
773
774 LLVM_DEBUG(dbgs() << "Name=" << getFixupKindInfo(Kind).Name << "("
775 << (unsigned)Kind << ")\n");
776 LLVM_DEBUG(
777 uint32_t OldData = 0; for (unsigned i = 0; i < NumBytes; i++) OldData |=
778 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));
779 dbgs() << "\tBValue=0x"; dbgs().write_hex(Value) << ": AValue=0x";
780 dbgs().write_hex(FixupValue) << ": Offset=" << Fixup.getOffset()
781 << ": Size=" << F.getSize() << ": OInst=0x";
782 dbgs().write_hex(OldData) << ": Reloc=0x"; dbgs().write_hex(Reloc););
783
784 // For each byte of the fragment that the fixup touches, mask in the
785 // bits from the fixup value. The Value has been "split up" into the
786 // appropriate bitfields above.
787 for (unsigned i = 0; i < NumBytes; i++) {
788 InstAddr[i] &= uint8_t(~InstMask >> (i * 8)) & 0xff; // Clear reloc bits
789 InstAddr[i] |= uint8_t(Reloc >> (i * 8)) & 0xff; // Apply new reloc
790 }
791
792 LLVM_DEBUG(uint32_t NewData = 0;
793 for (unsigned i = 0; i < NumBytes; i++) NewData |=
794 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));
795 dbgs() << ": NInst=0x"; dbgs().write_hex(NewData) << "\n";);
796}
797
798// MCAsmBackend
799MCAsmBackend *llvm::createHexagonAsmBackend(Target const &T,
800 const MCSubtargetInfo &STI,
801 MCRegisterInfo const & /*MRI*/,
802 const MCTargetOptions &Options) {
803 const Triple &TT = STI.getTargetTriple();
804 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType: TT.getOS());
805
806 StringRef CPUString = Hexagon_MC::selectHexagonCPU(CPU: STI.getCPU());
807 return new HexagonAsmBackend(T, TT, OSABI, CPUString);
808}
809