1 | //===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===// |
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 | // This file assembles .s files and emits ARM ELF .o object files. Different |
10 | // from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to |
11 | // delimit regions of data and code. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "ARMMCTargetDesc.h" |
16 | #include "ARMUnwindOpAsm.h" |
17 | #include "MCTargetDesc/ARMMCAsmInfo.h" |
18 | #include "Utils/ARMBaseInfo.h" |
19 | #include "llvm/ADT/DenseMap.h" |
20 | #include "llvm/ADT/SmallString.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/ADT/StringExtras.h" |
23 | #include "llvm/ADT/StringRef.h" |
24 | #include "llvm/ADT/Twine.h" |
25 | #include "llvm/BinaryFormat/ELF.h" |
26 | #include "llvm/MC/MCAsmBackend.h" |
27 | #include "llvm/MC/MCAsmInfo.h" |
28 | #include "llvm/MC/MCAssembler.h" |
29 | #include "llvm/MC/MCCodeEmitter.h" |
30 | #include "llvm/MC/MCContext.h" |
31 | #include "llvm/MC/MCELFObjectWriter.h" |
32 | #include "llvm/MC/MCELFStreamer.h" |
33 | #include "llvm/MC/MCExpr.h" |
34 | #include "llvm/MC/MCFixup.h" |
35 | #include "llvm/MC/MCInst.h" |
36 | #include "llvm/MC/MCInstPrinter.h" |
37 | #include "llvm/MC/MCObjectFileInfo.h" |
38 | #include "llvm/MC/MCObjectWriter.h" |
39 | #include "llvm/MC/MCRegisterInfo.h" |
40 | #include "llvm/MC/MCSection.h" |
41 | #include "llvm/MC/MCSectionELF.h" |
42 | #include "llvm/MC/MCStreamer.h" |
43 | #include "llvm/MC/MCSubtargetInfo.h" |
44 | #include "llvm/MC/MCSymbol.h" |
45 | #include "llvm/MC/MCSymbolELF.h" |
46 | #include "llvm/MC/SectionKind.h" |
47 | #include "llvm/Support/ARMBuildAttributes.h" |
48 | #include "llvm/Support/ARMEHABI.h" |
49 | #include "llvm/Support/Casting.h" |
50 | #include "llvm/Support/ErrorHandling.h" |
51 | #include "llvm/Support/FormattedStream.h" |
52 | #include "llvm/Support/raw_ostream.h" |
53 | #include <cassert> |
54 | #include <climits> |
55 | #include <cstdint> |
56 | #include <string> |
57 | |
58 | using namespace llvm; |
59 | |
60 | static std::string GetAEABIUnwindPersonalityName(unsigned Index) { |
61 | assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && |
62 | "Invalid personality index" ); |
63 | return (Twine("__aeabi_unwind_cpp_pr" ) + Twine(Index)).str(); |
64 | } |
65 | |
66 | namespace { |
67 | |
68 | class ARMELFStreamer; |
69 | |
70 | class ARMTargetAsmStreamer : public ARMTargetStreamer { |
71 | formatted_raw_ostream &OS; |
72 | MCInstPrinter &InstPrinter; |
73 | bool IsVerboseAsm; |
74 | |
75 | void emitFnStart() override; |
76 | void emitFnEnd() override; |
77 | void emitCantUnwind() override; |
78 | void emitPersonality(const MCSymbol *Personality) override; |
79 | void emitPersonalityIndex(unsigned Index) override; |
80 | void emitHandlerData() override; |
81 | void emitSetFP(MCRegister FpReg, MCRegister SpReg, |
82 | int64_t Offset = 0) override; |
83 | void emitMovSP(MCRegister Reg, int64_t Offset = 0) override; |
84 | void emitPad(int64_t Offset) override; |
85 | void emitRegSave(const SmallVectorImpl<MCRegister> &RegList, |
86 | bool isVector) override; |
87 | void emitUnwindRaw(int64_t Offset, |
88 | const SmallVectorImpl<uint8_t> &Opcodes) override; |
89 | |
90 | void switchVendor(StringRef Vendor) override; |
91 | void emitAttribute(unsigned Attribute, unsigned Value) override; |
92 | void emitTextAttribute(unsigned Attribute, StringRef String) override; |
93 | void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, |
94 | StringRef StringValue) override; |
95 | void emitArch(ARM::ArchKind Arch) override; |
96 | void emitArchExtension(uint64_t ArchExt) override; |
97 | void emitObjectArch(ARM::ArchKind Arch) override; |
98 | void emitFPU(ARM::FPUKind FPU) override; |
99 | void emitInst(uint32_t Inst, char Suffix = '\0') override; |
100 | void finishAttributeSection() override; |
101 | |
102 | void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; |
103 | void emitSyntaxUnified() override; |
104 | void emitCode16() override; |
105 | void emitCode32() override; |
106 | void emitThumbFunc(MCSymbol *Symbol) override; |
107 | void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override; |
108 | |
109 | void emitARMWinCFIAllocStack(unsigned Size, bool Wide) override; |
110 | void emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) override; |
111 | void emitARMWinCFISaveSP(unsigned Reg) override; |
112 | void emitARMWinCFISaveFRegs(unsigned First, unsigned Last) override; |
113 | void emitARMWinCFISaveLR(unsigned Offset) override; |
114 | void emitARMWinCFIPrologEnd(bool Fragment) override; |
115 | void emitARMWinCFINop(bool Wide) override; |
116 | void emitARMWinCFIEpilogStart(unsigned Condition) override; |
117 | void emitARMWinCFIEpilogEnd() override; |
118 | void emitARMWinCFICustom(unsigned Opcode) override; |
119 | |
120 | public: |
121 | ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, |
122 | MCInstPrinter &InstPrinter); |
123 | }; |
124 | |
125 | ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S, |
126 | formatted_raw_ostream &OS, |
127 | MCInstPrinter &InstPrinter) |
128 | : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter), |
129 | IsVerboseAsm(S.isVerboseAsm()) {} |
130 | |
131 | void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n" ; } |
132 | void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n" ; } |
133 | void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n" ; } |
134 | |
135 | void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) { |
136 | OS << "\t.personality " << Personality->getName() << '\n'; |
137 | } |
138 | |
139 | void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) { |
140 | OS << "\t.personalityindex " << Index << '\n'; |
141 | } |
142 | |
143 | void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n" ; } |
144 | |
145 | void ARMTargetAsmStreamer::emitSetFP(MCRegister FpReg, MCRegister SpReg, |
146 | int64_t Offset) { |
147 | OS << "\t.setfp\t" ; |
148 | InstPrinter.printRegName(OS, Reg: FpReg); |
149 | OS << ", " ; |
150 | InstPrinter.printRegName(OS, Reg: SpReg); |
151 | if (Offset) |
152 | OS << ", #" << Offset; |
153 | OS << '\n'; |
154 | } |
155 | |
156 | void ARMTargetAsmStreamer::emitMovSP(MCRegister Reg, int64_t Offset) { |
157 | assert((Reg != ARM::SP && Reg != ARM::PC) && |
158 | "the operand of .movsp cannot be either sp or pc" ); |
159 | |
160 | OS << "\t.movsp\t" ; |
161 | InstPrinter.printRegName(OS, Reg); |
162 | if (Offset) |
163 | OS << ", #" << Offset; |
164 | OS << '\n'; |
165 | } |
166 | |
167 | void ARMTargetAsmStreamer::emitPad(int64_t Offset) { |
168 | OS << "\t.pad\t#" << Offset << '\n'; |
169 | } |
170 | |
171 | void ARMTargetAsmStreamer::emitRegSave( |
172 | const SmallVectorImpl<MCRegister> &RegList, bool isVector) { |
173 | assert(RegList.size() && "RegList should not be empty" ); |
174 | if (isVector) |
175 | OS << "\t.vsave\t{" ; |
176 | else |
177 | OS << "\t.save\t{" ; |
178 | |
179 | InstPrinter.printRegName(OS, Reg: RegList[0]); |
180 | |
181 | for (unsigned i = 1, e = RegList.size(); i != e; ++i) { |
182 | OS << ", " ; |
183 | InstPrinter.printRegName(OS, Reg: RegList[i]); |
184 | } |
185 | |
186 | OS << "}\n" ; |
187 | } |
188 | |
189 | void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {} |
190 | |
191 | void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { |
192 | OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value); |
193 | if (IsVerboseAsm) { |
194 | StringRef Name = ELFAttrs::attrTypeAsString( |
195 | attr: Attribute, tagNameMap: ARMBuildAttrs::getARMAttributeTags()); |
196 | if (!Name.empty()) |
197 | OS << "\t@ " << Name; |
198 | } |
199 | OS << "\n" ; |
200 | } |
201 | |
202 | void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute, |
203 | StringRef String) { |
204 | switch (Attribute) { |
205 | case ARMBuildAttrs::CPU_name: |
206 | OS << "\t.cpu\t" << String.lower(); |
207 | break; |
208 | default: |
209 | OS << "\t.eabi_attribute\t" << Attribute << ", \"" ; |
210 | if (Attribute == ARMBuildAttrs::also_compatible_with) |
211 | OS.write_escaped(Str: String); |
212 | else |
213 | OS << String; |
214 | OS << "\"" ; |
215 | if (IsVerboseAsm) { |
216 | StringRef Name = ELFAttrs::attrTypeAsString( |
217 | attr: Attribute, tagNameMap: ARMBuildAttrs::getARMAttributeTags()); |
218 | if (!Name.empty()) |
219 | OS << "\t@ " << Name; |
220 | } |
221 | break; |
222 | } |
223 | OS << "\n" ; |
224 | } |
225 | |
226 | void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute, |
227 | unsigned IntValue, |
228 | StringRef StringValue) { |
229 | switch (Attribute) { |
230 | default: llvm_unreachable("unsupported multi-value attribute in asm mode" ); |
231 | case ARMBuildAttrs::compatibility: |
232 | OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue; |
233 | if (!StringValue.empty()) |
234 | OS << ", \"" << StringValue << "\"" ; |
235 | if (IsVerboseAsm) |
236 | OS << "\t@ " |
237 | << ELFAttrs::attrTypeAsString(attr: Attribute, |
238 | tagNameMap: ARMBuildAttrs::getARMAttributeTags()); |
239 | break; |
240 | } |
241 | OS << "\n" ; |
242 | } |
243 | |
244 | void ARMTargetAsmStreamer::emitArch(ARM::ArchKind Arch) { |
245 | OS << "\t.arch\t" << ARM::getArchName(AK: Arch) << "\n" ; |
246 | } |
247 | |
248 | void ARMTargetAsmStreamer::emitArchExtension(uint64_t ArchExt) { |
249 | OS << "\t.arch_extension\t" << ARM::getArchExtName(ArchExtKind: ArchExt) << "\n" ; |
250 | } |
251 | |
252 | void ARMTargetAsmStreamer::emitObjectArch(ARM::ArchKind Arch) { |
253 | OS << "\t.object_arch\t" << ARM::getArchName(AK: Arch) << '\n'; |
254 | } |
255 | |
256 | void ARMTargetAsmStreamer::emitFPU(ARM::FPUKind FPU) { |
257 | OS << "\t.fpu\t" << ARM::getFPUName(FPUKind: FPU) << "\n" ; |
258 | } |
259 | |
260 | void ARMTargetAsmStreamer::finishAttributeSection() {} |
261 | |
262 | void ARMTargetAsmStreamer::annotateTLSDescriptorSequence( |
263 | const MCSymbolRefExpr *S) { |
264 | OS << "\t.tlsdescseq\t" << S->getSymbol().getName() << "\n" ; |
265 | } |
266 | |
267 | void ARMTargetAsmStreamer::emitSyntaxUnified() { OS << "\t.syntax\tunified\n" ; } |
268 | |
269 | void ARMTargetAsmStreamer::emitCode16() { OS << "\t.code\t16\n" ; } |
270 | |
271 | void ARMTargetAsmStreamer::emitCode32() { OS << "\t.code\t32\n" ; } |
272 | |
273 | void ARMTargetAsmStreamer::emitThumbFunc(MCSymbol *Symbol) { |
274 | const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); |
275 | OS << "\t.thumb_func" ; |
276 | // Only Mach-O hasSubsectionsViaSymbols() |
277 | if (MAI->hasSubsectionsViaSymbols()) { |
278 | OS << '\t'; |
279 | Symbol->print(OS, MAI); |
280 | } |
281 | OS << '\n'; |
282 | } |
283 | |
284 | void ARMTargetAsmStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { |
285 | const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo(); |
286 | |
287 | OS << "\t.thumb_set\t" ; |
288 | Symbol->print(OS, MAI); |
289 | OS << ", " ; |
290 | MAI->printExpr(OS, *Value); |
291 | OS << '\n'; |
292 | } |
293 | |
294 | void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) { |
295 | OS << "\t.inst" ; |
296 | if (Suffix) |
297 | OS << "." << Suffix; |
298 | OS << "\t0x" << Twine::utohexstr(Val: Inst) << "\n" ; |
299 | } |
300 | |
301 | void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset, |
302 | const SmallVectorImpl<uint8_t> &Opcodes) { |
303 | OS << "\t.unwind_raw " << Offset; |
304 | for (uint8_t Opcode : Opcodes) |
305 | OS << ", 0x" << Twine::utohexstr(Val: Opcode); |
306 | OS << '\n'; |
307 | } |
308 | |
309 | void ARMTargetAsmStreamer::emitARMWinCFIAllocStack(unsigned Size, bool Wide) { |
310 | if (Wide) |
311 | OS << "\t.seh_stackalloc_w\t" << Size << "\n" ; |
312 | else |
313 | OS << "\t.seh_stackalloc\t" << Size << "\n" ; |
314 | } |
315 | |
316 | static void printRegs(formatted_raw_ostream &OS, ListSeparator &LS, int First, |
317 | int Last) { |
318 | if (First != Last) |
319 | OS << LS << "r" << First << "-r" << Last; |
320 | else |
321 | OS << LS << "r" << First; |
322 | } |
323 | |
324 | void ARMTargetAsmStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) { |
325 | if (Wide) |
326 | OS << "\t.seh_save_regs_w\t" ; |
327 | else |
328 | OS << "\t.seh_save_regs\t" ; |
329 | ListSeparator LS; |
330 | int First = -1; |
331 | OS << "{" ; |
332 | for (int I = 0; I <= 12; I++) { |
333 | if (Mask & (1 << I)) { |
334 | if (First < 0) |
335 | First = I; |
336 | } else { |
337 | if (First >= 0) { |
338 | printRegs(OS, LS, First, Last: I - 1); |
339 | First = -1; |
340 | } |
341 | } |
342 | } |
343 | if (First >= 0) |
344 | printRegs(OS, LS, First, Last: 12); |
345 | if (Mask & (1 << 14)) |
346 | OS << LS << "lr" ; |
347 | OS << "}\n" ; |
348 | } |
349 | |
350 | void ARMTargetAsmStreamer::emitARMWinCFISaveSP(unsigned Reg) { |
351 | OS << "\t.seh_save_sp\tr" << Reg << "\n" ; |
352 | } |
353 | |
354 | void ARMTargetAsmStreamer::emitARMWinCFISaveFRegs(unsigned First, |
355 | unsigned Last) { |
356 | if (First != Last) |
357 | OS << "\t.seh_save_fregs\t{d" << First << "-d" << Last << "}\n" ; |
358 | else |
359 | OS << "\t.seh_save_fregs\t{d" << First << "}\n" ; |
360 | } |
361 | |
362 | void ARMTargetAsmStreamer::emitARMWinCFISaveLR(unsigned Offset) { |
363 | OS << "\t.seh_save_lr\t" << Offset << "\n" ; |
364 | } |
365 | |
366 | void ARMTargetAsmStreamer::emitARMWinCFIPrologEnd(bool Fragment) { |
367 | if (Fragment) |
368 | OS << "\t.seh_endprologue_fragment\n" ; |
369 | else |
370 | OS << "\t.seh_endprologue\n" ; |
371 | } |
372 | |
373 | void ARMTargetAsmStreamer::emitARMWinCFINop(bool Wide) { |
374 | if (Wide) |
375 | OS << "\t.seh_nop_w\n" ; |
376 | else |
377 | OS << "\t.seh_nop\n" ; |
378 | } |
379 | |
380 | void ARMTargetAsmStreamer::emitARMWinCFIEpilogStart(unsigned Condition) { |
381 | if (Condition == ARMCC::AL) |
382 | OS << "\t.seh_startepilogue\n" ; |
383 | else |
384 | OS << "\t.seh_startepilogue_cond\t" |
385 | << ARMCondCodeToString(CC: static_cast<ARMCC::CondCodes>(Condition)) << "\n" ; |
386 | } |
387 | |
388 | void ARMTargetAsmStreamer::emitARMWinCFIEpilogEnd() { |
389 | OS << "\t.seh_endepilogue\n" ; |
390 | } |
391 | |
392 | void ARMTargetAsmStreamer::emitARMWinCFICustom(unsigned Opcode) { |
393 | int I; |
394 | for (I = 3; I > 0; I--) |
395 | if (Opcode & (0xffu << (8 * I))) |
396 | break; |
397 | ListSeparator LS; |
398 | OS << "\t.seh_custom\t" ; |
399 | for (; I >= 0; I--) |
400 | OS << LS << ((Opcode >> (8 * I)) & 0xff); |
401 | OS << "\n" ; |
402 | } |
403 | |
404 | class ARMTargetELFStreamer : public ARMTargetStreamer { |
405 | private: |
406 | StringRef CurrentVendor; |
407 | ARM::FPUKind FPU = ARM::FK_INVALID; |
408 | ARM::ArchKind Arch = ARM::ArchKind::INVALID; |
409 | ARM::ArchKind EmittedArch = ARM::ArchKind::INVALID; |
410 | |
411 | MCSection *AttributeSection = nullptr; |
412 | |
413 | void emitArchDefaultAttributes(); |
414 | void emitFPUDefaultAttributes(); |
415 | |
416 | ARMELFStreamer &getStreamer(); |
417 | |
418 | void emitFnStart() override; |
419 | void emitFnEnd() override; |
420 | void emitCantUnwind() override; |
421 | void emitPersonality(const MCSymbol *Personality) override; |
422 | void emitPersonalityIndex(unsigned Index) override; |
423 | void emitHandlerData() override; |
424 | void emitSetFP(MCRegister FpReg, MCRegister SpReg, |
425 | int64_t Offset = 0) override; |
426 | void emitMovSP(MCRegister Reg, int64_t Offset = 0) override; |
427 | void emitPad(int64_t Offset) override; |
428 | void emitRegSave(const SmallVectorImpl<MCRegister> &RegList, |
429 | bool isVector) override; |
430 | void emitUnwindRaw(int64_t Offset, |
431 | const SmallVectorImpl<uint8_t> &Opcodes) override; |
432 | |
433 | void switchVendor(StringRef Vendor) override; |
434 | void emitAttribute(unsigned Attribute, unsigned Value) override; |
435 | void emitTextAttribute(unsigned Attribute, StringRef String) override; |
436 | void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, |
437 | StringRef StringValue) override; |
438 | void emitArch(ARM::ArchKind Arch) override; |
439 | void emitObjectArch(ARM::ArchKind Arch) override; |
440 | void emitFPU(ARM::FPUKind FPU) override; |
441 | void emitInst(uint32_t Inst, char Suffix = '\0') override; |
442 | void finishAttributeSection() override; |
443 | void emitLabel(MCSymbol *Symbol) override; |
444 | |
445 | void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override; |
446 | void emitCode16() override; |
447 | void emitCode32() override; |
448 | void emitThumbFunc(MCSymbol *Symbol) override; |
449 | void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override; |
450 | |
451 | // Reset state between object emissions |
452 | void reset() override; |
453 | |
454 | void finish() override; |
455 | |
456 | public: |
457 | ARMTargetELFStreamer(MCStreamer &S) |
458 | : ARMTargetStreamer(S), CurrentVendor("aeabi" ) {} |
459 | }; |
460 | |
461 | /// Extend the generic ELFStreamer class so that it can emit mapping symbols at |
462 | /// the appropriate points in the object files. These symbols are defined in the |
463 | /// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf. |
464 | /// |
465 | /// In brief: $a, $t or $d should be emitted at the start of each contiguous |
466 | /// region of ARM code, Thumb code or data in a section. In practice, this |
467 | /// emission does not rely on explicit assembler directives but on inherent |
468 | /// properties of the directives doing the emission (e.g. ".byte" is data, "add |
469 | /// r0, r0, r0" an instruction). |
470 | /// |
471 | /// As a result this system is orthogonal to the DataRegion infrastructure used |
472 | /// by MachO. Beware! |
473 | class ARMELFStreamer : public MCELFStreamer { |
474 | public: |
475 | friend class ARMTargetELFStreamer; |
476 | |
477 | ARMELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, |
478 | std::unique_ptr<MCObjectWriter> OW, |
479 | std::unique_ptr<MCCodeEmitter> Emitter, bool IsThumb, |
480 | bool IsAndroid) |
481 | : MCELFStreamer(Context, std::move(TAB), std::move(OW), |
482 | std::move(Emitter)), |
483 | IsThumb(IsThumb), IsAndroid(IsAndroid) { |
484 | EHReset(); |
485 | } |
486 | |
487 | ~ARMELFStreamer() override = default; |
488 | |
489 | // ARM exception handling directives |
490 | void emitFnStart(); |
491 | void emitFnEnd(); |
492 | void emitCantUnwind(); |
493 | void emitPersonality(const MCSymbol *Per); |
494 | void emitPersonalityIndex(unsigned index); |
495 | void emitHandlerData(); |
496 | void emitSetFP(MCRegister NewFpReg, MCRegister NewSpReg, int64_t Offset = 0); |
497 | void emitMovSP(MCRegister Reg, int64_t Offset = 0); |
498 | void emitPad(int64_t Offset); |
499 | void emitRegSave(const SmallVectorImpl<MCRegister> &RegList, bool isVector); |
500 | void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes); |
501 | void emitFill(const MCExpr &NumBytes, uint64_t FillValue, |
502 | SMLoc Loc) override { |
503 | emitDataMappingSymbol(); |
504 | MCObjectStreamer::emitFill(NumBytes, FillValue, Loc); |
505 | } |
506 | |
507 | void changeSection(MCSection *Section, uint32_t Subsection) override { |
508 | LastMappingSymbols[getCurrentSection().first] = std::move(LastEMSInfo); |
509 | MCELFStreamer::changeSection(Section, Subsection); |
510 | auto LastMappingSymbol = LastMappingSymbols.find(Val: Section); |
511 | if (LastMappingSymbol != LastMappingSymbols.end()) { |
512 | LastEMSInfo = std::move(LastMappingSymbol->second); |
513 | return; |
514 | } |
515 | LastEMSInfo.reset(p: new ElfMappingSymbolInfo); |
516 | } |
517 | |
518 | /// This function is the one used to emit instruction data into the ELF |
519 | /// streamer. We override it to add the appropriate mapping symbol if |
520 | /// necessary. |
521 | void emitInstruction(const MCInst &Inst, |
522 | const MCSubtargetInfo &STI) override { |
523 | if (IsThumb) |
524 | EmitThumbMappingSymbol(); |
525 | else |
526 | EmitARMMappingSymbol(); |
527 | |
528 | MCELFStreamer::emitInstruction(Inst, STI); |
529 | } |
530 | |
531 | void emitInst(uint32_t Inst, char Suffix) { |
532 | unsigned Size; |
533 | char Buffer[4]; |
534 | const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian(); |
535 | |
536 | switch (Suffix) { |
537 | case '\0': |
538 | Size = 4; |
539 | |
540 | assert(!IsThumb); |
541 | EmitARMMappingSymbol(); |
542 | for (unsigned II = 0, IE = Size; II != IE; II++) { |
543 | const unsigned I = LittleEndian ? (Size - II - 1) : II; |
544 | Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT); |
545 | } |
546 | |
547 | break; |
548 | case 'n': |
549 | case 'w': |
550 | Size = (Suffix == 'n' ? 2 : 4); |
551 | |
552 | assert(IsThumb); |
553 | EmitThumbMappingSymbol(); |
554 | // Thumb wide instructions are emitted as a pair of 16-bit words of the |
555 | // appropriate endianness. |
556 | for (unsigned II = 0, IE = Size; II != IE; II = II + 2) { |
557 | const unsigned I0 = LittleEndian ? II + 0 : II + 1; |
558 | const unsigned I1 = LittleEndian ? II + 1 : II + 0; |
559 | Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT); |
560 | Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT); |
561 | } |
562 | |
563 | break; |
564 | default: |
565 | llvm_unreachable("Invalid Suffix" ); |
566 | } |
567 | |
568 | MCELFStreamer::emitBytes(Data: StringRef(Buffer, Size)); |
569 | } |
570 | |
571 | /// This is one of the functions used to emit data into an ELF section, so the |
572 | /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if |
573 | /// necessary. |
574 | void emitBytes(StringRef Data) override { |
575 | emitDataMappingSymbol(); |
576 | MCELFStreamer::emitBytes(Data); |
577 | } |
578 | |
579 | void FlushPendingMappingSymbol() { |
580 | if (!LastEMSInfo->hasInfo()) |
581 | return; |
582 | ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); |
583 | emitMappingSymbol(Name: "$d" , F&: *EMS->F, Offset: EMS->Offset); |
584 | EMS->resetInfo(); |
585 | } |
586 | |
587 | /// This is one of the functions used to emit data into an ELF section, so the |
588 | /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if |
589 | /// necessary. |
590 | void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { |
591 | if (const MCSymbolRefExpr *SRE = dyn_cast_or_null<MCSymbolRefExpr>(Val: Value)) { |
592 | if (SRE->getSpecifier() == ARM::S_SBREL && !(Size == 4)) { |
593 | getContext().reportError(L: Loc, Msg: "relocated expression must be 32-bit" ); |
594 | return; |
595 | } |
596 | getOrCreateDataFragment(); |
597 | } |
598 | |
599 | emitDataMappingSymbol(); |
600 | MCELFStreamer::emitValueImpl(Value, Size, Loc); |
601 | } |
602 | |
603 | /// If a label is defined before the .type directive sets the label's type |
604 | /// then the label can't be recorded as thumb function when the label is |
605 | /// defined. We override emitSymbolAttribute() which is called as part of the |
606 | /// parsing of .type so that if the symbol has already been defined we can |
607 | /// record the label as Thumb. FIXME: there is a corner case where the state |
608 | /// is changed in between the label definition and the .type directive, this |
609 | /// is not expected to occur in practice and handling it would require the |
610 | /// backend to track IsThumb for every label. |
611 | bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { |
612 | bool Val = MCELFStreamer::emitSymbolAttribute(Symbol, Attribute); |
613 | |
614 | if (!IsThumb) |
615 | return Val; |
616 | |
617 | unsigned Type = cast<MCSymbolELF>(Val: Symbol)->getType(); |
618 | if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) && |
619 | Symbol->isDefined()) |
620 | getAssembler().setIsThumbFunc(Symbol); |
621 | |
622 | return Val; |
623 | }; |
624 | |
625 | void setIsThumb(bool Val) { IsThumb = Val; } |
626 | |
627 | private: |
628 | enum ElfMappingSymbol { |
629 | EMS_None, |
630 | EMS_ARM, |
631 | EMS_Thumb, |
632 | EMS_Data |
633 | }; |
634 | |
635 | struct ElfMappingSymbolInfo { |
636 | void resetInfo() { |
637 | F = nullptr; |
638 | Offset = 0; |
639 | } |
640 | bool hasInfo() { return F != nullptr; } |
641 | MCDataFragment *F = nullptr; |
642 | uint64_t Offset = 0; |
643 | ElfMappingSymbol State = EMS_None; |
644 | }; |
645 | |
646 | void emitDataMappingSymbol() { |
647 | if (LastEMSInfo->State == EMS_Data) |
648 | return; |
649 | else if (LastEMSInfo->State == EMS_None) { |
650 | // This is a tentative symbol, it won't really be emitted until it's |
651 | // actually needed. |
652 | ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); |
653 | auto *DF = dyn_cast_or_null<MCDataFragment>(Val: getCurrentFragment()); |
654 | if (!DF) |
655 | return; |
656 | EMS->F = DF; |
657 | EMS->Offset = DF->getContents().size(); |
658 | LastEMSInfo->State = EMS_Data; |
659 | return; |
660 | } |
661 | EmitMappingSymbol(Name: "$d" ); |
662 | LastEMSInfo->State = EMS_Data; |
663 | } |
664 | |
665 | void EmitThumbMappingSymbol() { |
666 | if (LastEMSInfo->State == EMS_Thumb) |
667 | return; |
668 | FlushPendingMappingSymbol(); |
669 | EmitMappingSymbol(Name: "$t" ); |
670 | LastEMSInfo->State = EMS_Thumb; |
671 | } |
672 | |
673 | void EmitARMMappingSymbol() { |
674 | if (LastEMSInfo->State == EMS_ARM) |
675 | return; |
676 | FlushPendingMappingSymbol(); |
677 | EmitMappingSymbol(Name: "$a" ); |
678 | LastEMSInfo->State = EMS_ARM; |
679 | } |
680 | |
681 | void EmitMappingSymbol(StringRef Name) { |
682 | auto *Symbol = cast<MCSymbolELF>(Val: getContext().createLocalSymbol(Name)); |
683 | emitLabel(Symbol); |
684 | |
685 | Symbol->setType(ELF::STT_NOTYPE); |
686 | Symbol->setBinding(ELF::STB_LOCAL); |
687 | } |
688 | |
689 | void emitMappingSymbol(StringRef Name, MCDataFragment &F, uint64_t Offset) { |
690 | auto *Symbol = cast<MCSymbolELF>(Val: getContext().createLocalSymbol(Name)); |
691 | emitLabelAtPos(Symbol, Loc: SMLoc(), F, Offset); |
692 | Symbol->setType(ELF::STT_NOTYPE); |
693 | Symbol->setBinding(ELF::STB_LOCAL); |
694 | } |
695 | |
696 | // Helper functions for ARM exception handling directives |
697 | void EHReset(); |
698 | |
699 | // Reset state between object emissions |
700 | void reset() override; |
701 | |
702 | void EmitPersonalityFixup(StringRef Name); |
703 | void FlushPendingOffset(); |
704 | void FlushUnwindOpcodes(bool NoHandlerData); |
705 | |
706 | void SwitchToEHSection(StringRef Prefix, unsigned Type, unsigned Flags, |
707 | SectionKind Kind, const MCSymbol &Fn); |
708 | void SwitchToExTabSection(const MCSymbol &FnStart); |
709 | void SwitchToExIdxSection(const MCSymbol &FnStart); |
710 | |
711 | void EmitFixup(const MCExpr *Expr, MCFixupKind Kind); |
712 | |
713 | bool IsThumb; |
714 | bool IsAndroid; |
715 | |
716 | DenseMap<const MCSection *, std::unique_ptr<ElfMappingSymbolInfo>> |
717 | LastMappingSymbols; |
718 | |
719 | std::unique_ptr<ElfMappingSymbolInfo> LastEMSInfo; |
720 | |
721 | // ARM Exception Handling Frame Information |
722 | MCSymbol *ExTab; |
723 | MCSymbol *FnStart; |
724 | const MCSymbol *Personality; |
725 | unsigned PersonalityIndex; |
726 | MCRegister FPReg; // Frame pointer register |
727 | int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp) |
728 | int64_t SPOffset; // Offset: (final $sp) - (initial $sp) |
729 | int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp) |
730 | bool UsedFP; |
731 | bool CantUnwind; |
732 | SmallVector<uint8_t, 64> Opcodes; |
733 | UnwindOpcodeAssembler UnwindOpAsm; |
734 | }; |
735 | |
736 | } // end anonymous namespace |
737 | |
738 | ARMELFStreamer &ARMTargetELFStreamer::getStreamer() { |
739 | return static_cast<ARMELFStreamer &>(Streamer); |
740 | } |
741 | |
742 | void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); } |
743 | void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); } |
744 | void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); } |
745 | |
746 | void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) { |
747 | getStreamer().emitPersonality(Per: Personality); |
748 | } |
749 | |
750 | void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) { |
751 | getStreamer().emitPersonalityIndex(index: Index); |
752 | } |
753 | |
754 | void ARMTargetELFStreamer::emitHandlerData() { |
755 | getStreamer().emitHandlerData(); |
756 | } |
757 | |
758 | void ARMTargetELFStreamer::emitSetFP(MCRegister FpReg, MCRegister SpReg, |
759 | int64_t Offset) { |
760 | getStreamer().emitSetFP(NewFpReg: FpReg, NewSpReg: SpReg, Offset); |
761 | } |
762 | |
763 | void ARMTargetELFStreamer::emitMovSP(MCRegister Reg, int64_t Offset) { |
764 | getStreamer().emitMovSP(Reg, Offset); |
765 | } |
766 | |
767 | void ARMTargetELFStreamer::emitPad(int64_t Offset) { |
768 | getStreamer().emitPad(Offset); |
769 | } |
770 | |
771 | void ARMTargetELFStreamer::emitRegSave( |
772 | const SmallVectorImpl<MCRegister> &RegList, bool isVector) { |
773 | getStreamer().emitRegSave(RegList, isVector); |
774 | } |
775 | |
776 | void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset, |
777 | const SmallVectorImpl<uint8_t> &Opcodes) { |
778 | getStreamer().emitUnwindRaw(Offset, Opcodes); |
779 | } |
780 | |
781 | void ARMTargetELFStreamer::switchVendor(StringRef Vendor) { |
782 | assert(!Vendor.empty() && "Vendor cannot be empty." ); |
783 | |
784 | if (CurrentVendor == Vendor) |
785 | return; |
786 | |
787 | if (!CurrentVendor.empty()) |
788 | finishAttributeSection(); |
789 | |
790 | assert(getStreamer().Contents.empty() && |
791 | ".ARM.attributes should be flushed before changing vendor" ); |
792 | CurrentVendor = Vendor; |
793 | |
794 | } |
795 | |
796 | void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) { |
797 | getStreamer().setAttributeItem(Attribute, Value, |
798 | /* OverwriteExisting= */ true); |
799 | } |
800 | |
801 | void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute, |
802 | StringRef Value) { |
803 | getStreamer().setAttributeItem(Attribute, Value, |
804 | /* OverwriteExisting= */ true); |
805 | } |
806 | |
807 | void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute, |
808 | unsigned IntValue, |
809 | StringRef StringValue) { |
810 | getStreamer().setAttributeItems(Attribute, IntValue, StringValue, |
811 | /* OverwriteExisting= */ true); |
812 | } |
813 | |
814 | void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) { |
815 | Arch = Value; |
816 | } |
817 | |
818 | void ARMTargetELFStreamer::emitObjectArch(ARM::ArchKind Value) { |
819 | EmittedArch = Value; |
820 | } |
821 | |
822 | void ARMTargetELFStreamer::emitArchDefaultAttributes() { |
823 | using namespace ARMBuildAttrs; |
824 | ARMELFStreamer &S = getStreamer(); |
825 | |
826 | S.setAttributeItem(Attribute: CPU_name, Value: ARM::getCPUAttr(AK: Arch), OverwriteExisting: false); |
827 | |
828 | if (EmittedArch == ARM::ArchKind::INVALID) |
829 | S.setAttributeItem(Attribute: CPU_arch, Value: ARM::getArchAttr(AK: Arch), OverwriteExisting: false); |
830 | else |
831 | S.setAttributeItem(Attribute: CPU_arch, Value: ARM::getArchAttr(AK: EmittedArch), OverwriteExisting: false); |
832 | |
833 | switch (Arch) { |
834 | case ARM::ArchKind::ARMV4: |
835 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
836 | break; |
837 | |
838 | case ARM::ArchKind::ARMV4T: |
839 | case ARM::ArchKind::ARMV5T: |
840 | case ARM::ArchKind::XSCALE: |
841 | case ARM::ArchKind::ARMV5TE: |
842 | case ARM::ArchKind::ARMV6: |
843 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
844 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: Allowed, OverwriteExisting: false); |
845 | break; |
846 | |
847 | case ARM::ArchKind::ARMV6T2: |
848 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
849 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumb32, OverwriteExisting: false); |
850 | break; |
851 | |
852 | case ARM::ArchKind::ARMV6K: |
853 | case ARM::ArchKind::ARMV6KZ: |
854 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
855 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: Allowed, OverwriteExisting: false); |
856 | S.setAttributeItem(Attribute: Virtualization_use, Value: AllowTZ, OverwriteExisting: false); |
857 | break; |
858 | |
859 | case ARM::ArchKind::ARMV6M: |
860 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: Allowed, OverwriteExisting: false); |
861 | break; |
862 | |
863 | case ARM::ArchKind::ARMV7A: |
864 | S.setAttributeItem(Attribute: CPU_arch_profile, Value: ApplicationProfile, OverwriteExisting: false); |
865 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
866 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumb32, OverwriteExisting: false); |
867 | break; |
868 | |
869 | case ARM::ArchKind::ARMV7R: |
870 | S.setAttributeItem(Attribute: CPU_arch_profile, Value: RealTimeProfile, OverwriteExisting: false); |
871 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
872 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumb32, OverwriteExisting: false); |
873 | break; |
874 | |
875 | case ARM::ArchKind::ARMV7EM: |
876 | case ARM::ArchKind::ARMV7M: |
877 | S.setAttributeItem(Attribute: CPU_arch_profile, Value: MicroControllerProfile, OverwriteExisting: false); |
878 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumb32, OverwriteExisting: false); |
879 | break; |
880 | |
881 | case ARM::ArchKind::ARMV8A: |
882 | case ARM::ArchKind::ARMV8_1A: |
883 | case ARM::ArchKind::ARMV8_2A: |
884 | case ARM::ArchKind::ARMV8_3A: |
885 | case ARM::ArchKind::ARMV8_4A: |
886 | case ARM::ArchKind::ARMV8_5A: |
887 | case ARM::ArchKind::ARMV8_6A: |
888 | case ARM::ArchKind::ARMV8_7A: |
889 | case ARM::ArchKind::ARMV8_8A: |
890 | case ARM::ArchKind::ARMV8_9A: |
891 | case ARM::ArchKind::ARMV9A: |
892 | case ARM::ArchKind::ARMV9_1A: |
893 | case ARM::ArchKind::ARMV9_2A: |
894 | case ARM::ArchKind::ARMV9_3A: |
895 | case ARM::ArchKind::ARMV9_4A: |
896 | case ARM::ArchKind::ARMV9_5A: |
897 | case ARM::ArchKind::ARMV9_6A: |
898 | S.setAttributeItem(Attribute: CPU_arch_profile, Value: ApplicationProfile, OverwriteExisting: false); |
899 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
900 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumb32, OverwriteExisting: false); |
901 | S.setAttributeItem(Attribute: MPextension_use, Value: Allowed, OverwriteExisting: false); |
902 | S.setAttributeItem(Attribute: Virtualization_use, Value: AllowTZVirtualization, OverwriteExisting: false); |
903 | break; |
904 | |
905 | case ARM::ArchKind::ARMV8MBaseline: |
906 | case ARM::ArchKind::ARMV8MMainline: |
907 | case ARM::ArchKind::ARMV8_1MMainline: |
908 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: AllowThumbDerived, OverwriteExisting: false); |
909 | S.setAttributeItem(Attribute: CPU_arch_profile, Value: MicroControllerProfile, OverwriteExisting: false); |
910 | break; |
911 | |
912 | case ARM::ArchKind::IWMMXT: |
913 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
914 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: Allowed, OverwriteExisting: false); |
915 | S.setAttributeItem(Attribute: WMMX_arch, Value: AllowWMMXv1, OverwriteExisting: false); |
916 | break; |
917 | |
918 | case ARM::ArchKind::IWMMXT2: |
919 | S.setAttributeItem(Attribute: ARM_ISA_use, Value: Allowed, OverwriteExisting: false); |
920 | S.setAttributeItem(Attribute: THUMB_ISA_use, Value: Allowed, OverwriteExisting: false); |
921 | S.setAttributeItem(Attribute: WMMX_arch, Value: AllowWMMXv2, OverwriteExisting: false); |
922 | break; |
923 | |
924 | default: |
925 | report_fatal_error(reason: "Unknown Arch: " + Twine(ARM::getArchName(AK: Arch))); |
926 | break; |
927 | } |
928 | } |
929 | |
930 | void ARMTargetELFStreamer::emitFPU(ARM::FPUKind Value) { FPU = Value; } |
931 | |
932 | void ARMTargetELFStreamer::emitFPUDefaultAttributes() { |
933 | ARMELFStreamer &S = getStreamer(); |
934 | |
935 | switch (FPU) { |
936 | case ARM::FK_VFP: |
937 | case ARM::FK_VFPV2: |
938 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv2, |
939 | /* OverwriteExisting= */ false); |
940 | break; |
941 | |
942 | case ARM::FK_VFPV3: |
943 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3A, |
944 | /* OverwriteExisting= */ false); |
945 | break; |
946 | |
947 | case ARM::FK_VFPV3_FP16: |
948 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3A, |
949 | /* OverwriteExisting= */ false); |
950 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_HP_extension, Value: ARMBuildAttrs::AllowHPFP, |
951 | /* OverwriteExisting= */ false); |
952 | break; |
953 | |
954 | case ARM::FK_VFPV3_D16: |
955 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3B, |
956 | /* OverwriteExisting= */ false); |
957 | break; |
958 | |
959 | case ARM::FK_VFPV3_D16_FP16: |
960 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3B, |
961 | /* OverwriteExisting= */ false); |
962 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_HP_extension, Value: ARMBuildAttrs::AllowHPFP, |
963 | /* OverwriteExisting= */ false); |
964 | break; |
965 | |
966 | case ARM::FK_VFPV3XD: |
967 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3B, |
968 | /* OverwriteExisting= */ false); |
969 | break; |
970 | case ARM::FK_VFPV3XD_FP16: |
971 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3B, |
972 | /* OverwriteExisting= */ false); |
973 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_HP_extension, Value: ARMBuildAttrs::AllowHPFP, |
974 | /* OverwriteExisting= */ false); |
975 | break; |
976 | |
977 | case ARM::FK_VFPV4: |
978 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv4A, |
979 | /* OverwriteExisting= */ false); |
980 | break; |
981 | |
982 | // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same |
983 | // as _D16 here. |
984 | case ARM::FK_FPV4_SP_D16: |
985 | case ARM::FK_VFPV4_D16: |
986 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv4B, |
987 | /* OverwriteExisting= */ false); |
988 | break; |
989 | |
990 | case ARM::FK_FP_ARMV8: |
991 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPARMv8A, |
992 | /* OverwriteExisting= */ false); |
993 | break; |
994 | |
995 | // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so |
996 | // uses the FP_ARMV8_D16 build attribute. |
997 | case ARM::FK_FPV5_SP_D16: |
998 | case ARM::FK_FPV5_D16: |
999 | // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one |
1000 | // FPU, but there are two different names for it depending on the CPU. |
1001 | case ARM::FK_FP_ARMV8_FULLFP16_SP_D16: |
1002 | case ARM::FK_FP_ARMV8_FULLFP16_D16: |
1003 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPARMv8B, |
1004 | /* OverwriteExisting= */ false); |
1005 | break; |
1006 | |
1007 | case ARM::FK_NEON: |
1008 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3A, |
1009 | /* OverwriteExisting= */ false); |
1010 | S.setAttributeItem(Attribute: ARMBuildAttrs::Advanced_SIMD_arch, |
1011 | Value: ARMBuildAttrs::AllowNeon, |
1012 | /* OverwriteExisting= */ false); |
1013 | break; |
1014 | |
1015 | case ARM::FK_NEON_FP16: |
1016 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv3A, |
1017 | /* OverwriteExisting= */ false); |
1018 | S.setAttributeItem(Attribute: ARMBuildAttrs::Advanced_SIMD_arch, |
1019 | Value: ARMBuildAttrs::AllowNeon, |
1020 | /* OverwriteExisting= */ false); |
1021 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_HP_extension, Value: ARMBuildAttrs::AllowHPFP, |
1022 | /* OverwriteExisting= */ false); |
1023 | break; |
1024 | |
1025 | case ARM::FK_NEON_VFPV4: |
1026 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPv4A, |
1027 | /* OverwriteExisting= */ false); |
1028 | S.setAttributeItem(Attribute: ARMBuildAttrs::Advanced_SIMD_arch, |
1029 | Value: ARMBuildAttrs::AllowNeon2, |
1030 | /* OverwriteExisting= */ false); |
1031 | break; |
1032 | |
1033 | case ARM::FK_NEON_FP_ARMV8: |
1034 | case ARM::FK_CRYPTO_NEON_FP_ARMV8: |
1035 | S.setAttributeItem(Attribute: ARMBuildAttrs::FP_arch, Value: ARMBuildAttrs::AllowFPARMv8A, |
1036 | /* OverwriteExisting= */ false); |
1037 | // 'Advanced_SIMD_arch' must be emitted not here, but within |
1038 | // ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a() |
1039 | break; |
1040 | |
1041 | case ARM::FK_SOFTVFP: |
1042 | case ARM::FK_NONE: |
1043 | break; |
1044 | |
1045 | default: |
1046 | report_fatal_error(reason: "Unknown FPU: " + Twine(FPU)); |
1047 | break; |
1048 | } |
1049 | } |
1050 | |
1051 | void ARMTargetELFStreamer::finishAttributeSection() { |
1052 | ARMELFStreamer &S = getStreamer(); |
1053 | |
1054 | if (FPU != ARM::FK_INVALID) |
1055 | emitFPUDefaultAttributes(); |
1056 | |
1057 | if (Arch != ARM::ArchKind::INVALID) |
1058 | emitArchDefaultAttributes(); |
1059 | |
1060 | if (S.Contents.empty()) |
1061 | return; |
1062 | |
1063 | auto LessTag = [](const MCELFStreamer::AttributeItem &LHS, |
1064 | const MCELFStreamer::AttributeItem &RHS) -> bool { |
1065 | // The conformance tag must be emitted first when serialised into an |
1066 | // object file. Specifically, the addenda to the ARM ABI states that |
1067 | // (2.3.7.4): |
1068 | // |
1069 | // "To simplify recognition by consumers in the common case of claiming |
1070 | // conformity for the whole file, this tag should be emitted first in a |
1071 | // file-scope sub-subsection of the first public subsection of the |
1072 | // attributes section." |
1073 | // |
1074 | // So it is special-cased in this comparison predicate when the |
1075 | // attributes are sorted in finishAttributeSection(). |
1076 | return (RHS.Tag != ARMBuildAttrs::conformance) && |
1077 | ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag)); |
1078 | }; |
1079 | llvm::sort(C&: S.Contents, Comp: LessTag); |
1080 | |
1081 | S.emitAttributesSection(Vendor: CurrentVendor, Section: ".ARM.attributes" , |
1082 | Type: ELF::SHT_ARM_ATTRIBUTES, AttributeSection); |
1083 | |
1084 | FPU = ARM::FK_INVALID; |
1085 | } |
1086 | |
1087 | void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) { |
1088 | ARMELFStreamer &Streamer = getStreamer(); |
1089 | if (!Streamer.IsThumb) |
1090 | return; |
1091 | |
1092 | Streamer.getAssembler().registerSymbol(Symbol: *Symbol); |
1093 | unsigned Type = cast<MCSymbolELF>(Val: Symbol)->getType(); |
1094 | if (Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) |
1095 | emitThumbFunc(Symbol); |
1096 | } |
1097 | |
1098 | void ARMTargetELFStreamer::annotateTLSDescriptorSequence( |
1099 | const MCSymbolRefExpr *S) { |
1100 | getStreamer().EmitFixup(Expr: S, Kind: FK_Data_4); |
1101 | } |
1102 | |
1103 | void ARMTargetELFStreamer::emitCode16() { getStreamer().setIsThumb(true); } |
1104 | |
1105 | void ARMTargetELFStreamer::emitCode32() { getStreamer().setIsThumb(false); } |
1106 | |
1107 | void ARMTargetELFStreamer::emitThumbFunc(MCSymbol *Symbol) { |
1108 | getStreamer().getAssembler().setIsThumbFunc(Symbol); |
1109 | getStreamer().emitSymbolAttribute(Symbol, Attribute: MCSA_ELF_TypeFunction); |
1110 | } |
1111 | |
1112 | void ARMTargetELFStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) { |
1113 | if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val: Value)) { |
1114 | const MCSymbol &Sym = SRE->getSymbol(); |
1115 | if (!Sym.isDefined()) { |
1116 | getStreamer().emitAssignment(Symbol, Value); |
1117 | return; |
1118 | } |
1119 | } |
1120 | |
1121 | emitThumbFunc(Symbol); |
1122 | getStreamer().emitAssignment(Symbol, Value); |
1123 | } |
1124 | |
1125 | void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) { |
1126 | getStreamer().emitInst(Inst, Suffix); |
1127 | } |
1128 | |
1129 | void ARMTargetELFStreamer::reset() { AttributeSection = nullptr; } |
1130 | |
1131 | void ARMTargetELFStreamer::finish() { |
1132 | ARMTargetStreamer::finish(); |
1133 | finishAttributeSection(); |
1134 | |
1135 | // The mix of execute-only and non-execute-only at link time is |
1136 | // non-execute-only. To avoid the empty implicitly created .text |
1137 | // section from making the whole .text section non-execute-only, we |
1138 | // mark it execute-only if it is empty and there is at least one |
1139 | // execute-only section in the object. |
1140 | MCContext &Ctx = getContext(); |
1141 | auto &Asm = getStreamer().getAssembler(); |
1142 | if (any_of(Range&: Asm, P: [](const MCSection &Sec) { |
1143 | return cast<MCSectionELF>(Val: Sec).getFlags() & ELF::SHF_ARM_PURECODE; |
1144 | })) { |
1145 | auto *Text = |
1146 | static_cast<MCSectionELF *>(Ctx.getObjectFileInfo()->getTextSection()); |
1147 | for (auto &F : *Text) |
1148 | if (auto *DF = dyn_cast<MCDataFragment>(Val: &F)) |
1149 | if (!DF->getContents().empty()) |
1150 | return; |
1151 | Text->setFlags(Text->getFlags() | ELF::SHF_ARM_PURECODE); |
1152 | } |
1153 | } |
1154 | |
1155 | void ARMELFStreamer::reset() { |
1156 | MCTargetStreamer &TS = *getTargetStreamer(); |
1157 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); |
1158 | ATS.reset(); |
1159 | MCELFStreamer::reset(); |
1160 | LastMappingSymbols.clear(); |
1161 | LastEMSInfo.reset(); |
1162 | // MCELFStreamer clear's the assembler's e_flags. However, for |
1163 | // arm we manually set the ABI version on streamer creation, so |
1164 | // do the same here |
1165 | getWriter().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); |
1166 | } |
1167 | |
1168 | inline void ARMELFStreamer::SwitchToEHSection(StringRef Prefix, |
1169 | unsigned Type, |
1170 | unsigned Flags, |
1171 | SectionKind Kind, |
1172 | const MCSymbol &Fn) { |
1173 | const MCSectionELF &FnSection = |
1174 | static_cast<const MCSectionELF &>(Fn.getSection()); |
1175 | |
1176 | // Create the name for new section |
1177 | StringRef FnSecName(FnSection.getName()); |
1178 | SmallString<128> EHSecName(Prefix); |
1179 | if (FnSecName != ".text" ) { |
1180 | EHSecName += FnSecName; |
1181 | } |
1182 | |
1183 | // Get .ARM.extab or .ARM.exidx section |
1184 | const MCSymbolELF *Group = FnSection.getGroup(); |
1185 | if (Group) |
1186 | Flags |= ELF::SHF_GROUP; |
1187 | MCSectionELF *EHSection = getContext().getELFSection( |
1188 | Section: EHSecName, Type, Flags, EntrySize: 0, Group, /*IsComdat=*/true, |
1189 | UniqueID: FnSection.getUniqueID(), |
1190 | LinkedToSym: static_cast<const MCSymbolELF *>(FnSection.getBeginSymbol())); |
1191 | |
1192 | assert(EHSection && "Failed to get the required EH section" ); |
1193 | |
1194 | // Switch to .ARM.extab or .ARM.exidx section |
1195 | switchSection(Section: EHSection); |
1196 | emitValueToAlignment(Align(4), 0, 1, 0); |
1197 | } |
1198 | |
1199 | inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { |
1200 | SwitchToEHSection(Prefix: ".ARM.extab" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC, |
1201 | Kind: SectionKind::getData(), Fn: FnStart); |
1202 | } |
1203 | |
1204 | inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { |
1205 | SwitchToEHSection(Prefix: ".ARM.exidx" , Type: ELF::SHT_ARM_EXIDX, |
1206 | Flags: ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER, |
1207 | Kind: SectionKind::getData(), Fn: FnStart); |
1208 | } |
1209 | |
1210 | void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) { |
1211 | MCDataFragment *Frag = getOrCreateDataFragment(); |
1212 | Frag->addFixup(Fixup: MCFixup::create(Offset: Frag->getContents().size(), Value: Expr, Kind)); |
1213 | } |
1214 | |
1215 | void ARMELFStreamer::EHReset() { |
1216 | ExTab = nullptr; |
1217 | FnStart = nullptr; |
1218 | Personality = nullptr; |
1219 | PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX; |
1220 | FPReg = ARM::SP; |
1221 | FPOffset = 0; |
1222 | SPOffset = 0; |
1223 | PendingOffset = 0; |
1224 | UsedFP = false; |
1225 | CantUnwind = false; |
1226 | |
1227 | Opcodes.clear(); |
1228 | UnwindOpAsm.Reset(); |
1229 | } |
1230 | |
1231 | void ARMELFStreamer::emitFnStart() { |
1232 | assert(FnStart == nullptr); |
1233 | FnStart = getContext().createTempSymbol(); |
1234 | emitLabel(Symbol: FnStart); |
1235 | } |
1236 | |
1237 | void ARMELFStreamer::emitFnEnd() { |
1238 | assert(FnStart && ".fnstart must precedes .fnend" ); |
1239 | |
1240 | // Emit unwind opcodes if there is no .handlerdata directive |
1241 | if (!ExTab && !CantUnwind) |
1242 | FlushUnwindOpcodes(NoHandlerData: true); |
1243 | |
1244 | // Emit the exception index table entry |
1245 | SwitchToExIdxSection(FnStart: *FnStart); |
1246 | |
1247 | // The EHABI requires a dependency preserving R_ARM_NONE relocation to the |
1248 | // personality routine to protect it from an arbitrary platform's static |
1249 | // linker garbage collection. We disable this for Android where the unwinder |
1250 | // is either dynamically linked or directly references the personality |
1251 | // routine. |
1252 | if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX && !IsAndroid) |
1253 | EmitPersonalityFixup(Name: GetAEABIUnwindPersonalityName(Index: PersonalityIndex)); |
1254 | |
1255 | const MCSymbolRefExpr *FnStartRef = |
1256 | MCSymbolRefExpr::create(Symbol: FnStart, specifier: ARM::S_PREL31, Ctx&: getContext()); |
1257 | |
1258 | emitValue(Value: FnStartRef, Size: 4); |
1259 | |
1260 | if (CantUnwind) { |
1261 | emitInt32(Value: ARM::EHABI::EXIDX_CANTUNWIND); |
1262 | } else if (ExTab) { |
1263 | // Emit a reference to the unwind opcodes in the ".ARM.extab" section. |
1264 | const MCSymbolRefExpr *ExTabEntryRef = |
1265 | MCSymbolRefExpr::create(Symbol: ExTab, specifier: ARM::S_PREL31, Ctx&: getContext()); |
1266 | emitValue(Value: ExTabEntryRef, Size: 4); |
1267 | } else { |
1268 | // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in |
1269 | // the second word of exception index table entry. The size of the unwind |
1270 | // opcodes should always be 4 bytes. |
1271 | assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 && |
1272 | "Compact model must use __aeabi_unwind_cpp_pr0 as personality" ); |
1273 | assert(Opcodes.size() == 4u && |
1274 | "Unwind opcode size for __aeabi_unwind_cpp_pr0 must be equal to 4" ); |
1275 | uint64_t Intval = Opcodes[0] | |
1276 | Opcodes[1] << 8 | |
1277 | Opcodes[2] << 16 | |
1278 | Opcodes[3] << 24; |
1279 | emitIntValue(Value: Intval, Size: Opcodes.size()); |
1280 | } |
1281 | |
1282 | // Switch to the section containing FnStart |
1283 | switchSection(Section: &FnStart->getSection()); |
1284 | |
1285 | // Clean exception handling frame information |
1286 | EHReset(); |
1287 | } |
1288 | |
1289 | void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; } |
1290 | |
1291 | // Add the R_ARM_NONE fixup at the same position |
1292 | void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { |
1293 | const MCSymbol *PersonalitySym = getContext().getOrCreateSymbol(Name); |
1294 | |
1295 | const MCSymbolRefExpr *PersonalityRef = |
1296 | MCSymbolRefExpr::create(Symbol: PersonalitySym, specifier: ARM::S_ARM_NONE, Ctx&: getContext()); |
1297 | |
1298 | visitUsedExpr(Expr: *PersonalityRef); |
1299 | MCDataFragment *DF = getOrCreateDataFragment(); |
1300 | DF->addFixup( |
1301 | Fixup: MCFixup::create(Offset: DF->getContents().size(), Value: PersonalityRef, Kind: FK_Data_4)); |
1302 | } |
1303 | |
1304 | void ARMELFStreamer::FlushPendingOffset() { |
1305 | if (PendingOffset != 0) { |
1306 | UnwindOpAsm.EmitSPOffset(Offset: -PendingOffset); |
1307 | PendingOffset = 0; |
1308 | } |
1309 | } |
1310 | |
1311 | void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { |
1312 | // Emit the unwind opcode to restore $sp. |
1313 | if (UsedFP) { |
1314 | const MCRegisterInfo *MRI = getContext().getRegisterInfo(); |
1315 | int64_t LastRegSaveSPOffset = SPOffset - PendingOffset; |
1316 | UnwindOpAsm.EmitSPOffset(Offset: LastRegSaveSPOffset - FPOffset); |
1317 | UnwindOpAsm.EmitSetSP(Reg: MRI->getEncodingValue(Reg: FPReg)); |
1318 | } else { |
1319 | FlushPendingOffset(); |
1320 | } |
1321 | |
1322 | // Finalize the unwind opcode sequence |
1323 | UnwindOpAsm.Finalize(PersonalityIndex, Result&: Opcodes); |
1324 | |
1325 | // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx |
1326 | // section. Thus, we don't have to create an entry in the .ARM.extab |
1327 | // section. |
1328 | if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0) |
1329 | return; |
1330 | |
1331 | // Switch to .ARM.extab section. |
1332 | SwitchToExTabSection(FnStart: *FnStart); |
1333 | |
1334 | // Create .ARM.extab label for offset in .ARM.exidx |
1335 | assert(!ExTab); |
1336 | ExTab = getContext().createTempSymbol(); |
1337 | emitLabel(Symbol: ExTab); |
1338 | |
1339 | // Emit personality |
1340 | if (Personality) { |
1341 | const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::create( |
1342 | Symbol: Personality, specifier: uint16_t(ARM::S_PREL31), Ctx&: getContext()); |
1343 | |
1344 | emitValue(Value: PersonalityRef, Size: 4); |
1345 | } |
1346 | |
1347 | // Emit unwind opcodes |
1348 | assert((Opcodes.size() % 4) == 0 && |
1349 | "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be multiple of 4" ); |
1350 | for (unsigned I = 0; I != Opcodes.size(); I += 4) { |
1351 | uint64_t Intval = Opcodes[I] | |
1352 | Opcodes[I + 1] << 8 | |
1353 | Opcodes[I + 2] << 16 | |
1354 | Opcodes[I + 3] << 24; |
1355 | emitInt32(Value: Intval); |
1356 | } |
1357 | |
1358 | // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or |
1359 | // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted |
1360 | // after the unwind opcodes. The handler data consists of several 32-bit |
1361 | // words, and should be terminated by zero. |
1362 | // |
1363 | // In case that the .handlerdata directive is not specified by the |
1364 | // programmer, we should emit zero to terminate the handler data. |
1365 | if (NoHandlerData && !Personality) |
1366 | emitInt32(Value: 0); |
1367 | } |
1368 | |
1369 | void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(NoHandlerData: false); } |
1370 | |
1371 | void ARMELFStreamer::emitPersonality(const MCSymbol *Per) { |
1372 | Personality = Per; |
1373 | UnwindOpAsm.setPersonality(Per); |
1374 | } |
1375 | |
1376 | void ARMELFStreamer::emitPersonalityIndex(unsigned Index) { |
1377 | assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index" ); |
1378 | PersonalityIndex = Index; |
1379 | } |
1380 | |
1381 | void ARMELFStreamer::emitSetFP(MCRegister NewFPReg, MCRegister NewSPReg, |
1382 | int64_t Offset) { |
1383 | assert((NewSPReg == ARM::SP || NewSPReg == FPReg) && |
1384 | "the operand of .setfp directive should be either $sp or $fp" ); |
1385 | |
1386 | UsedFP = true; |
1387 | FPReg = NewFPReg; |
1388 | |
1389 | if (NewSPReg == ARM::SP) |
1390 | FPOffset = SPOffset + Offset; |
1391 | else |
1392 | FPOffset += Offset; |
1393 | } |
1394 | |
1395 | void ARMELFStreamer::emitMovSP(MCRegister Reg, int64_t Offset) { |
1396 | assert((Reg != ARM::SP && Reg != ARM::PC) && |
1397 | "the operand of .movsp cannot be either sp or pc" ); |
1398 | assert(FPReg == ARM::SP && "current FP must be SP" ); |
1399 | |
1400 | FlushPendingOffset(); |
1401 | |
1402 | FPReg = Reg; |
1403 | FPOffset = SPOffset + Offset; |
1404 | |
1405 | const MCRegisterInfo *MRI = getContext().getRegisterInfo(); |
1406 | UnwindOpAsm.EmitSetSP(Reg: MRI->getEncodingValue(Reg: FPReg)); |
1407 | } |
1408 | |
1409 | void ARMELFStreamer::emitPad(int64_t Offset) { |
1410 | // Track the change of the $sp offset |
1411 | SPOffset -= Offset; |
1412 | |
1413 | // To squash multiple .pad directives, we should delay the unwind opcode |
1414 | // until the .save, .vsave, .handlerdata, or .fnend directives. |
1415 | PendingOffset -= Offset; |
1416 | } |
1417 | |
1418 | static std::pair<unsigned, unsigned> |
1419 | collectHWRegs(const MCRegisterInfo &MRI, unsigned Idx, |
1420 | const SmallVectorImpl<MCRegister> &RegList, bool IsVector, |
1421 | uint32_t &Mask_) { |
1422 | uint32_t Mask = 0; |
1423 | unsigned Count = 0; |
1424 | while (Idx > 0) { |
1425 | MCRegister Reg = RegList[Idx - 1]; |
1426 | if (Reg == ARM::RA_AUTH_CODE) |
1427 | break; |
1428 | unsigned RegEnc = MRI.getEncodingValue(Reg); |
1429 | assert(RegEnc < (IsVector ? 32U : 16U) && "Register out of range" ); |
1430 | unsigned Bit = (1u << RegEnc); |
1431 | if ((Mask & Bit) == 0) { |
1432 | Mask |= Bit; |
1433 | ++Count; |
1434 | } |
1435 | --Idx; |
1436 | } |
1437 | |
1438 | Mask_ = Mask; |
1439 | return {Idx, Count}; |
1440 | } |
1441 | |
1442 | void ARMELFStreamer::emitRegSave(const SmallVectorImpl<MCRegister> &RegList, |
1443 | bool IsVector) { |
1444 | uint32_t Mask; |
1445 | unsigned Idx, Count; |
1446 | const MCRegisterInfo &MRI = *getContext().getRegisterInfo(); |
1447 | |
1448 | // Collect the registers in the register list. Issue unwinding instructions in |
1449 | // three parts: ordinary hardware registers, return address authentication |
1450 | // code pseudo register, the rest of the registers. The RA PAC is kept in an |
1451 | // architectural register (usually r12), but we treat it as a special case in |
1452 | // order to distinguish between that register containing RA PAC or a general |
1453 | // value. |
1454 | Idx = RegList.size(); |
1455 | while (Idx > 0) { |
1456 | std::tie(args&: Idx, args&: Count) = collectHWRegs(MRI, Idx, RegList, IsVector, Mask_&: Mask); |
1457 | if (Count) { |
1458 | // Track the change the $sp offset: For the .save directive, the |
1459 | // corresponding push instruction will decrease the $sp by (4 * Count). |
1460 | // For the .vsave directive, the corresponding vpush instruction will |
1461 | // decrease $sp by (8 * Count). |
1462 | SPOffset -= Count * (IsVector ? 8 : 4); |
1463 | |
1464 | // Emit the opcode |
1465 | FlushPendingOffset(); |
1466 | if (IsVector) |
1467 | UnwindOpAsm.EmitVFPRegSave(VFPRegSave: Mask); |
1468 | else |
1469 | UnwindOpAsm.EmitRegSave(RegSave: Mask); |
1470 | } else if (Idx > 0 && RegList[Idx - 1] == ARM::RA_AUTH_CODE) { |
1471 | --Idx; |
1472 | SPOffset -= 4; |
1473 | FlushPendingOffset(); |
1474 | UnwindOpAsm.EmitRegSave(RegSave: 0); |
1475 | } |
1476 | } |
1477 | } |
1478 | |
1479 | void ARMELFStreamer::emitUnwindRaw(int64_t Offset, |
1480 | const SmallVectorImpl<uint8_t> &Opcodes) { |
1481 | FlushPendingOffset(); |
1482 | SPOffset = SPOffset - Offset; |
1483 | UnwindOpAsm.EmitRaw(Opcodes); |
1484 | } |
1485 | |
1486 | namespace llvm { |
1487 | |
1488 | MCTargetStreamer *createARMTargetAsmStreamer(MCStreamer &S, |
1489 | formatted_raw_ostream &OS, |
1490 | MCInstPrinter *InstPrint) { |
1491 | return new ARMTargetAsmStreamer(S, OS, *InstPrint); |
1492 | } |
1493 | |
1494 | MCTargetStreamer *createARMNullTargetStreamer(MCStreamer &S) { |
1495 | return new ARMTargetStreamer(S); |
1496 | } |
1497 | |
1498 | MCTargetStreamer *createARMObjectTargetELFStreamer(MCStreamer &S) { |
1499 | return new ARMTargetELFStreamer(S); |
1500 | } |
1501 | |
1502 | MCELFStreamer *createARMELFStreamer(MCContext &Context, |
1503 | std::unique_ptr<MCAsmBackend> TAB, |
1504 | std::unique_ptr<MCObjectWriter> OW, |
1505 | std::unique_ptr<MCCodeEmitter> Emitter, |
1506 | bool IsThumb, bool IsAndroid) { |
1507 | ARMELFStreamer *S = |
1508 | new ARMELFStreamer(Context, std::move(TAB), std::move(OW), |
1509 | std::move(Emitter), IsThumb, IsAndroid); |
1510 | // FIXME: This should eventually end up somewhere else where more |
1511 | // intelligent flag decisions can be made. For now we are just maintaining |
1512 | // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. |
1513 | S->getWriter().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); |
1514 | |
1515 | return S; |
1516 | } |
1517 | |
1518 | } // end namespace llvm |
1519 | |