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