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