xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
10b57cec5SDimitry Andric //===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file assembles .s files and emits ARM ELF .o object files. Different
100b57cec5SDimitry Andric // from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to
110b57cec5SDimitry Andric // delimit regions of data and code.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
155f757f3fSDimitry Andric #include "ARMMCTargetDesc.h"
160b57cec5SDimitry Andric #include "ARMUnwindOpAsm.h"
175f757f3fSDimitry Andric #include "Utils/ARMBaseInfo.h"
180b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
2181ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
230b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
240b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
390b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
400b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
410b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
420b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
430b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
440b57cec5SDimitry Andric #include "llvm/MC/SectionKind.h"
450b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
460b57cec5SDimitry Andric #include "llvm/Support/ARMEHABI.h"
470b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
480b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
490b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
500b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
510b57cec5SDimitry Andric #include <algorithm>
520b57cec5SDimitry Andric #include <cassert>
530b57cec5SDimitry Andric #include <climits>
540b57cec5SDimitry Andric #include <cstddef>
550b57cec5SDimitry Andric #include <cstdint>
560b57cec5SDimitry Andric #include <string>
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric using namespace llvm;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
610b57cec5SDimitry Andric   assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX &&
620b57cec5SDimitry Andric          "Invalid personality index");
630b57cec5SDimitry Andric   return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric namespace {
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric class ARMELFStreamer;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric class ARMTargetAsmStreamer : public ARMTargetStreamer {
710b57cec5SDimitry Andric   formatted_raw_ostream &OS;
720b57cec5SDimitry Andric   MCInstPrinter &InstPrinter;
730b57cec5SDimitry Andric   bool IsVerboseAsm;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   void emitFnStart() override;
760b57cec5SDimitry Andric   void emitFnEnd() override;
770b57cec5SDimitry Andric   void emitCantUnwind() override;
780b57cec5SDimitry Andric   void emitPersonality(const MCSymbol *Personality) override;
790b57cec5SDimitry Andric   void emitPersonalityIndex(unsigned Index) override;
800b57cec5SDimitry Andric   void emitHandlerData() override;
810b57cec5SDimitry Andric   void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override;
820b57cec5SDimitry Andric   void emitMovSP(unsigned Reg, int64_t Offset = 0) override;
830b57cec5SDimitry Andric   void emitPad(int64_t Offset) override;
840b57cec5SDimitry Andric   void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
850b57cec5SDimitry Andric                    bool isVector) override;
860b57cec5SDimitry Andric   void emitUnwindRaw(int64_t Offset,
870b57cec5SDimitry Andric                      const SmallVectorImpl<uint8_t> &Opcodes) override;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   void switchVendor(StringRef Vendor) override;
900b57cec5SDimitry Andric   void emitAttribute(unsigned Attribute, unsigned Value) override;
910b57cec5SDimitry Andric   void emitTextAttribute(unsigned Attribute, StringRef String) override;
920b57cec5SDimitry Andric   void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
930b57cec5SDimitry Andric                             StringRef StringValue) override;
940b57cec5SDimitry Andric   void emitArch(ARM::ArchKind Arch) override;
955ffd83dbSDimitry Andric   void emitArchExtension(uint64_t ArchExt) override;
960b57cec5SDimitry Andric   void emitObjectArch(ARM::ArchKind Arch) override;
9706c3fb27SDimitry Andric   void emitFPU(ARM::FPUKind FPU) override;
980b57cec5SDimitry Andric   void emitInst(uint32_t Inst, char Suffix = '\0') override;
990b57cec5SDimitry Andric   void finishAttributeSection() override;
1000b57cec5SDimitry Andric 
10181ad6265SDimitry Andric   void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
1020b57cec5SDimitry Andric   void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
1030b57cec5SDimitry Andric 
10481ad6265SDimitry Andric   void emitARMWinCFIAllocStack(unsigned Size, bool Wide) override;
10581ad6265SDimitry Andric   void emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) override;
10681ad6265SDimitry Andric   void emitARMWinCFISaveSP(unsigned Reg) override;
10781ad6265SDimitry Andric   void emitARMWinCFISaveFRegs(unsigned First, unsigned Last) override;
10881ad6265SDimitry Andric   void emitARMWinCFISaveLR(unsigned Offset) override;
10981ad6265SDimitry Andric   void emitARMWinCFIPrologEnd(bool Fragment) override;
11081ad6265SDimitry Andric   void emitARMWinCFINop(bool Wide) override;
11181ad6265SDimitry Andric   void emitARMWinCFIEpilogStart(unsigned Condition) override;
11281ad6265SDimitry Andric   void emitARMWinCFIEpilogEnd() override;
11381ad6265SDimitry Andric   void emitARMWinCFICustom(unsigned Opcode) override;
11481ad6265SDimitry Andric 
1150b57cec5SDimitry Andric public:
1160b57cec5SDimitry Andric   ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,
1170fca6ea1SDimitry Andric                        MCInstPrinter &InstPrinter);
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric ARMTargetAsmStreamer::ARMTargetAsmStreamer(MCStreamer &S,
1210b57cec5SDimitry Andric                                            formatted_raw_ostream &OS,
1220fca6ea1SDimitry Andric                                            MCInstPrinter &InstPrinter)
1230b57cec5SDimitry Andric     : ARMTargetStreamer(S), OS(OS), InstPrinter(InstPrinter),
1240fca6ea1SDimitry Andric       IsVerboseAsm(S.isVerboseAsm()) {}
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; }
1270b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; }
1280b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
1310b57cec5SDimitry Andric   OS << "\t.personality " << Personality->getName() << '\n';
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) {
1350b57cec5SDimitry Andric   OS << "\t.personalityindex " << Index << '\n';
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
1410b57cec5SDimitry Andric                                      int64_t Offset) {
1420b57cec5SDimitry Andric   OS << "\t.setfp\t";
1430b57cec5SDimitry Andric   InstPrinter.printRegName(OS, FpReg);
1440b57cec5SDimitry Andric   OS << ", ";
1450b57cec5SDimitry Andric   InstPrinter.printRegName(OS, SpReg);
1460b57cec5SDimitry Andric   if (Offset)
1470b57cec5SDimitry Andric     OS << ", #" << Offset;
1480b57cec5SDimitry Andric   OS << '\n';
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
1520b57cec5SDimitry Andric   assert((Reg != ARM::SP && Reg != ARM::PC) &&
1530b57cec5SDimitry Andric          "the operand of .movsp cannot be either sp or pc");
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   OS << "\t.movsp\t";
1560b57cec5SDimitry Andric   InstPrinter.printRegName(OS, Reg);
1570b57cec5SDimitry Andric   if (Offset)
1580b57cec5SDimitry Andric     OS << ", #" << Offset;
1590b57cec5SDimitry Andric   OS << '\n';
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
1630b57cec5SDimitry Andric   OS << "\t.pad\t#" << Offset << '\n';
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
1670b57cec5SDimitry Andric                                        bool isVector) {
1680b57cec5SDimitry Andric   assert(RegList.size() && "RegList should not be empty");
1690b57cec5SDimitry Andric   if (isVector)
1700b57cec5SDimitry Andric     OS << "\t.vsave\t{";
1710b57cec5SDimitry Andric   else
1720b57cec5SDimitry Andric     OS << "\t.save\t{";
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   InstPrinter.printRegName(OS, RegList[0]);
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   for (unsigned i = 1, e = RegList.size(); i != e; ++i) {
1770b57cec5SDimitry Andric     OS << ", ";
1780b57cec5SDimitry Andric     InstPrinter.printRegName(OS, RegList[i]);
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   OS << "}\n";
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {}
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
1870b57cec5SDimitry Andric   OS << "\t.eabi_attribute\t" << Attribute << ", " << Twine(Value);
1880b57cec5SDimitry Andric   if (IsVerboseAsm) {
189fe6060f1SDimitry Andric     StringRef Name = ELFAttrs::attrTypeAsString(
190fe6060f1SDimitry Andric         Attribute, ARMBuildAttrs::getARMAttributeTags());
1910b57cec5SDimitry Andric     if (!Name.empty())
1920b57cec5SDimitry Andric       OS << "\t@ " << Name;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric   OS << "\n";
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
1980b57cec5SDimitry Andric                                              StringRef String) {
1990b57cec5SDimitry Andric   switch (Attribute) {
2000b57cec5SDimitry Andric   case ARMBuildAttrs::CPU_name:
2010b57cec5SDimitry Andric     OS << "\t.cpu\t" << String.lower();
2020b57cec5SDimitry Andric     break;
2030b57cec5SDimitry Andric   default:
204bdd1243dSDimitry Andric     OS << "\t.eabi_attribute\t" << Attribute << ", \"";
205bdd1243dSDimitry Andric     if (Attribute == ARMBuildAttrs::also_compatible_with)
206bdd1243dSDimitry Andric       OS.write_escaped(String);
207bdd1243dSDimitry Andric     else
208bdd1243dSDimitry Andric       OS << String;
209bdd1243dSDimitry Andric     OS << "\"";
2100b57cec5SDimitry Andric     if (IsVerboseAsm) {
2115ffd83dbSDimitry Andric       StringRef Name = ELFAttrs::attrTypeAsString(
212fe6060f1SDimitry Andric           Attribute, ARMBuildAttrs::getARMAttributeTags());
2130b57cec5SDimitry Andric       if (!Name.empty())
2140b57cec5SDimitry Andric         OS << "\t@ " << Name;
2150b57cec5SDimitry Andric     }
2160b57cec5SDimitry Andric     break;
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric   OS << "\n";
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
2220b57cec5SDimitry Andric                                                 unsigned IntValue,
2230b57cec5SDimitry Andric                                                 StringRef StringValue) {
2240b57cec5SDimitry Andric   switch (Attribute) {
2250b57cec5SDimitry Andric   default: llvm_unreachable("unsupported multi-value attribute in asm mode");
2260b57cec5SDimitry Andric   case ARMBuildAttrs::compatibility:
2270b57cec5SDimitry Andric     OS << "\t.eabi_attribute\t" << Attribute << ", " << IntValue;
2280b57cec5SDimitry Andric     if (!StringValue.empty())
2290b57cec5SDimitry Andric       OS << ", \"" << StringValue << "\"";
2300b57cec5SDimitry Andric     if (IsVerboseAsm)
2315ffd83dbSDimitry Andric       OS << "\t@ "
2325ffd83dbSDimitry Andric          << ELFAttrs::attrTypeAsString(Attribute,
233fe6060f1SDimitry Andric                                        ARMBuildAttrs::getARMAttributeTags());
2340b57cec5SDimitry Andric     break;
2350b57cec5SDimitry Andric   }
2360b57cec5SDimitry Andric   OS << "\n";
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitArch(ARM::ArchKind Arch) {
2400b57cec5SDimitry Andric   OS << "\t.arch\t" << ARM::getArchName(Arch) << "\n";
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric 
2435ffd83dbSDimitry Andric void ARMTargetAsmStreamer::emitArchExtension(uint64_t ArchExt) {
2440b57cec5SDimitry Andric   OS << "\t.arch_extension\t" << ARM::getArchExtName(ArchExt) << "\n";
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitObjectArch(ARM::ArchKind Arch) {
2480b57cec5SDimitry Andric   OS << "\t.object_arch\t" << ARM::getArchName(Arch) << '\n';
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
25106c3fb27SDimitry Andric void ARMTargetAsmStreamer::emitFPU(ARM::FPUKind FPU) {
2520b57cec5SDimitry Andric   OS << "\t.fpu\t" << ARM::getFPUName(FPU) << "\n";
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric void ARMTargetAsmStreamer::finishAttributeSection() {}
2560b57cec5SDimitry Andric 
25781ad6265SDimitry Andric void ARMTargetAsmStreamer::annotateTLSDescriptorSequence(
25881ad6265SDimitry Andric     const MCSymbolRefExpr *S) {
2595ffd83dbSDimitry Andric   OS << "\t.tlsdescseq\t" << S->getSymbol().getName() << "\n";
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {
2630b57cec5SDimitry Andric   const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   OS << "\t.thumb_set\t";
2660b57cec5SDimitry Andric   Symbol->print(OS, MAI);
2670b57cec5SDimitry Andric   OS << ", ";
2680b57cec5SDimitry Andric   Value->print(OS, MAI);
2690b57cec5SDimitry Andric   OS << '\n';
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) {
2730b57cec5SDimitry Andric   OS << "\t.inst";
2740b57cec5SDimitry Andric   if (Suffix)
2750b57cec5SDimitry Andric     OS << "." << Suffix;
2760b57cec5SDimitry Andric   OS << "\t0x" << Twine::utohexstr(Inst) << "\n";
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitUnwindRaw(int64_t Offset,
2800b57cec5SDimitry Andric                                       const SmallVectorImpl<uint8_t> &Opcodes) {
2810b57cec5SDimitry Andric   OS << "\t.unwind_raw " << Offset;
28204eeddc0SDimitry Andric   for (uint8_t Opcode : Opcodes)
28304eeddc0SDimitry Andric     OS << ", 0x" << Twine::utohexstr(Opcode);
2840b57cec5SDimitry Andric   OS << '\n';
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric 
28781ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFIAllocStack(unsigned Size, bool Wide) {
28881ad6265SDimitry Andric   if (Wide)
28981ad6265SDimitry Andric     OS << "\t.seh_stackalloc_w\t" << Size << "\n";
29081ad6265SDimitry Andric   else
29181ad6265SDimitry Andric     OS << "\t.seh_stackalloc\t" << Size << "\n";
29281ad6265SDimitry Andric }
29381ad6265SDimitry Andric 
29481ad6265SDimitry Andric static void printRegs(formatted_raw_ostream &OS, ListSeparator &LS, int First,
29581ad6265SDimitry Andric                       int Last) {
29681ad6265SDimitry Andric   if (First != Last)
29781ad6265SDimitry Andric     OS << LS << "r" << First << "-r" << Last;
29881ad6265SDimitry Andric   else
29981ad6265SDimitry Andric     OS << LS << "r" << First;
30081ad6265SDimitry Andric }
30181ad6265SDimitry Andric 
30281ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) {
30381ad6265SDimitry Andric   if (Wide)
30481ad6265SDimitry Andric     OS << "\t.seh_save_regs_w\t";
30581ad6265SDimitry Andric   else
30681ad6265SDimitry Andric     OS << "\t.seh_save_regs\t";
30781ad6265SDimitry Andric   ListSeparator LS;
30881ad6265SDimitry Andric   int First = -1;
30981ad6265SDimitry Andric   OS << "{";
31081ad6265SDimitry Andric   for (int I = 0; I <= 12; I++) {
31181ad6265SDimitry Andric     if (Mask & (1 << I)) {
31281ad6265SDimitry Andric       if (First < 0)
31381ad6265SDimitry Andric         First = I;
31481ad6265SDimitry Andric     } else {
31581ad6265SDimitry Andric       if (First >= 0) {
31681ad6265SDimitry Andric         printRegs(OS, LS, First, I - 1);
31781ad6265SDimitry Andric         First = -1;
31881ad6265SDimitry Andric       }
31981ad6265SDimitry Andric     }
32081ad6265SDimitry Andric   }
32181ad6265SDimitry Andric   if (First >= 0)
32281ad6265SDimitry Andric     printRegs(OS, LS, First, 12);
32381ad6265SDimitry Andric   if (Mask & (1 << 14))
32481ad6265SDimitry Andric     OS << LS << "lr";
32581ad6265SDimitry Andric   OS << "}\n";
32681ad6265SDimitry Andric }
32781ad6265SDimitry Andric 
32881ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveSP(unsigned Reg) {
32981ad6265SDimitry Andric   OS << "\t.seh_save_sp\tr" << Reg << "\n";
33081ad6265SDimitry Andric }
33181ad6265SDimitry Andric 
33281ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveFRegs(unsigned First,
33381ad6265SDimitry Andric                                                   unsigned Last) {
33481ad6265SDimitry Andric   if (First != Last)
33581ad6265SDimitry Andric     OS << "\t.seh_save_fregs\t{d" << First << "-d" << Last << "}\n";
33681ad6265SDimitry Andric   else
33781ad6265SDimitry Andric     OS << "\t.seh_save_fregs\t{d" << First << "}\n";
33881ad6265SDimitry Andric }
33981ad6265SDimitry Andric 
34081ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveLR(unsigned Offset) {
34181ad6265SDimitry Andric   OS << "\t.seh_save_lr\t" << Offset << "\n";
34281ad6265SDimitry Andric }
34381ad6265SDimitry Andric 
34481ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFIPrologEnd(bool Fragment) {
34581ad6265SDimitry Andric   if (Fragment)
34681ad6265SDimitry Andric     OS << "\t.seh_endprologue_fragment\n";
34781ad6265SDimitry Andric   else
34881ad6265SDimitry Andric     OS << "\t.seh_endprologue\n";
34981ad6265SDimitry Andric }
35081ad6265SDimitry Andric 
35181ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFINop(bool Wide) {
35281ad6265SDimitry Andric   if (Wide)
35381ad6265SDimitry Andric     OS << "\t.seh_nop_w\n";
35481ad6265SDimitry Andric   else
35581ad6265SDimitry Andric     OS << "\t.seh_nop\n";
35681ad6265SDimitry Andric }
35781ad6265SDimitry Andric 
35881ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFIEpilogStart(unsigned Condition) {
35981ad6265SDimitry Andric   if (Condition == ARMCC::AL)
36081ad6265SDimitry Andric     OS << "\t.seh_startepilogue\n";
36181ad6265SDimitry Andric   else
36281ad6265SDimitry Andric     OS << "\t.seh_startepilogue_cond\t"
36381ad6265SDimitry Andric        << ARMCondCodeToString(static_cast<ARMCC::CondCodes>(Condition)) << "\n";
36481ad6265SDimitry Andric }
36581ad6265SDimitry Andric 
36681ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFIEpilogEnd() {
36781ad6265SDimitry Andric   OS << "\t.seh_endepilogue\n";
36881ad6265SDimitry Andric }
36981ad6265SDimitry Andric 
37081ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFICustom(unsigned Opcode) {
37181ad6265SDimitry Andric   int I;
37281ad6265SDimitry Andric   for (I = 3; I > 0; I--)
37381ad6265SDimitry Andric     if (Opcode & (0xffu << (8 * I)))
37481ad6265SDimitry Andric       break;
37581ad6265SDimitry Andric   ListSeparator LS;
37681ad6265SDimitry Andric   OS << "\t.seh_custom\t";
37781ad6265SDimitry Andric   for (; I >= 0; I--)
37881ad6265SDimitry Andric     OS << LS << ((Opcode >> (8 * I)) & 0xff);
37981ad6265SDimitry Andric   OS << "\n";
38081ad6265SDimitry Andric }
38181ad6265SDimitry Andric 
3820b57cec5SDimitry Andric class ARMTargetELFStreamer : public ARMTargetStreamer {
3830b57cec5SDimitry Andric private:
3840b57cec5SDimitry Andric   StringRef CurrentVendor;
38506c3fb27SDimitry Andric   ARM::FPUKind FPU = ARM::FK_INVALID;
3860b57cec5SDimitry Andric   ARM::ArchKind Arch = ARM::ArchKind::INVALID;
3870b57cec5SDimitry Andric   ARM::ArchKind EmittedArch = ARM::ArchKind::INVALID;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   MCSection *AttributeSection = nullptr;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   void emitArchDefaultAttributes();
3920b57cec5SDimitry Andric   void emitFPUDefaultAttributes();
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   ARMELFStreamer &getStreamer();
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   void emitFnStart() override;
3970b57cec5SDimitry Andric   void emitFnEnd() override;
3980b57cec5SDimitry Andric   void emitCantUnwind() override;
3990b57cec5SDimitry Andric   void emitPersonality(const MCSymbol *Personality) override;
4000b57cec5SDimitry Andric   void emitPersonalityIndex(unsigned Index) override;
4010b57cec5SDimitry Andric   void emitHandlerData() override;
4020b57cec5SDimitry Andric   void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0) override;
4030b57cec5SDimitry Andric   void emitMovSP(unsigned Reg, int64_t Offset = 0) override;
4040b57cec5SDimitry Andric   void emitPad(int64_t Offset) override;
4050b57cec5SDimitry Andric   void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
4060b57cec5SDimitry Andric                    bool isVector) override;
4070b57cec5SDimitry Andric   void emitUnwindRaw(int64_t Offset,
4080b57cec5SDimitry Andric                      const SmallVectorImpl<uint8_t> &Opcodes) override;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   void switchVendor(StringRef Vendor) override;
4110b57cec5SDimitry Andric   void emitAttribute(unsigned Attribute, unsigned Value) override;
4120b57cec5SDimitry Andric   void emitTextAttribute(unsigned Attribute, StringRef String) override;
4130b57cec5SDimitry Andric   void emitIntTextAttribute(unsigned Attribute, unsigned IntValue,
4140b57cec5SDimitry Andric                             StringRef StringValue) override;
4150b57cec5SDimitry Andric   void emitArch(ARM::ArchKind Arch) override;
4160b57cec5SDimitry Andric   void emitObjectArch(ARM::ArchKind Arch) override;
41706c3fb27SDimitry Andric   void emitFPU(ARM::FPUKind FPU) override;
4180b57cec5SDimitry Andric   void emitInst(uint32_t Inst, char Suffix = '\0') override;
4190b57cec5SDimitry Andric   void finishAttributeSection() override;
4200b57cec5SDimitry Andric   void emitLabel(MCSymbol *Symbol) override;
4210b57cec5SDimitry Andric 
42281ad6265SDimitry Andric   void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) override;
4230b57cec5SDimitry Andric   void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) override;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   // Reset state between object emissions
4260b57cec5SDimitry Andric   void reset() override;
4270b57cec5SDimitry Andric 
4280fca6ea1SDimitry Andric   void finish() override;
4290fca6ea1SDimitry Andric 
4300b57cec5SDimitry Andric public:
4310b57cec5SDimitry Andric   ARMTargetELFStreamer(MCStreamer &S)
4320b57cec5SDimitry Andric     : ARMTargetStreamer(S), CurrentVendor("aeabi") {}
4330b57cec5SDimitry Andric };
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric /// Extend the generic ELFStreamer class so that it can emit mapping symbols at
4360b57cec5SDimitry Andric /// the appropriate points in the object files. These symbols are defined in the
4370b57cec5SDimitry Andric /// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
4380b57cec5SDimitry Andric ///
4390b57cec5SDimitry Andric /// In brief: $a, $t or $d should be emitted at the start of each contiguous
4400b57cec5SDimitry Andric /// region of ARM code, Thumb code or data in a section. In practice, this
4410b57cec5SDimitry Andric /// emission does not rely on explicit assembler directives but on inherent
4420b57cec5SDimitry Andric /// properties of the directives doing the emission (e.g. ".byte" is data, "add
4430b57cec5SDimitry Andric /// r0, r0, r0" an instruction).
4440b57cec5SDimitry Andric ///
4450b57cec5SDimitry Andric /// As a result this system is orthogonal to the DataRegion infrastructure used
4460b57cec5SDimitry Andric /// by MachO. Beware!
4470b57cec5SDimitry Andric class ARMELFStreamer : public MCELFStreamer {
4480b57cec5SDimitry Andric public:
4490b57cec5SDimitry Andric   friend class ARMTargetELFStreamer;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   ARMELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
452480093f4SDimitry Andric                  std::unique_ptr<MCObjectWriter> OW,
453480093f4SDimitry Andric                  std::unique_ptr<MCCodeEmitter> Emitter, bool IsThumb,
454480093f4SDimitry Andric                  bool IsAndroid)
455480093f4SDimitry Andric       : MCELFStreamer(Context, std::move(TAB), std::move(OW),
456480093f4SDimitry Andric                       std::move(Emitter)),
457480093f4SDimitry Andric         IsThumb(IsThumb), IsAndroid(IsAndroid) {
4580b57cec5SDimitry Andric     EHReset();
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   ~ARMELFStreamer() override = default;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   // ARM exception handling directives
4640b57cec5SDimitry Andric   void emitFnStart();
4650b57cec5SDimitry Andric   void emitFnEnd();
4660b57cec5SDimitry Andric   void emitCantUnwind();
4670b57cec5SDimitry Andric   void emitPersonality(const MCSymbol *Per);
4680b57cec5SDimitry Andric   void emitPersonalityIndex(unsigned index);
4690b57cec5SDimitry Andric   void emitHandlerData();
4700b57cec5SDimitry Andric   void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
4710b57cec5SDimitry Andric   void emitMovSP(unsigned Reg, int64_t Offset = 0);
4720b57cec5SDimitry Andric   void emitPad(int64_t Offset);
4730b57cec5SDimitry Andric   void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
4740b57cec5SDimitry Andric   void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
4750b57cec5SDimitry Andric   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
4760b57cec5SDimitry Andric                 SMLoc Loc) override {
4775ffd83dbSDimitry Andric     emitDataMappingSymbol();
4780b57cec5SDimitry Andric     MCObjectStreamer::emitFill(NumBytes, FillValue, Loc);
4790b57cec5SDimitry Andric   }
4800b57cec5SDimitry Andric 
4810fca6ea1SDimitry Andric   void changeSection(MCSection *Section, uint32_t Subsection) override {
4820b57cec5SDimitry Andric     LastMappingSymbols[getCurrentSection().first] = std::move(LastEMSInfo);
4835ffd83dbSDimitry Andric     MCELFStreamer::changeSection(Section, Subsection);
4840b57cec5SDimitry Andric     auto LastMappingSymbol = LastMappingSymbols.find(Section);
4850b57cec5SDimitry Andric     if (LastMappingSymbol != LastMappingSymbols.end()) {
4860b57cec5SDimitry Andric       LastEMSInfo = std::move(LastMappingSymbol->second);
4870b57cec5SDimitry Andric       return;
4880b57cec5SDimitry Andric     }
4890fca6ea1SDimitry Andric     LastEMSInfo.reset(new ElfMappingSymbolInfo);
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   /// This function is the one used to emit instruction data into the ELF
4930b57cec5SDimitry Andric   /// streamer. We override it to add the appropriate mapping symbol if
4940b57cec5SDimitry Andric   /// necessary.
4955ffd83dbSDimitry Andric   void emitInstruction(const MCInst &Inst,
4960b57cec5SDimitry Andric                        const MCSubtargetInfo &STI) override {
4970b57cec5SDimitry Andric     if (IsThumb)
4980b57cec5SDimitry Andric       EmitThumbMappingSymbol();
4990b57cec5SDimitry Andric     else
5000b57cec5SDimitry Andric       EmitARMMappingSymbol();
5010b57cec5SDimitry Andric 
5025ffd83dbSDimitry Andric     MCELFStreamer::emitInstruction(Inst, STI);
5030b57cec5SDimitry Andric   }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   void emitInst(uint32_t Inst, char Suffix) {
5060b57cec5SDimitry Andric     unsigned Size;
5070b57cec5SDimitry Andric     char Buffer[4];
5080b57cec5SDimitry Andric     const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian();
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     switch (Suffix) {
5110b57cec5SDimitry Andric     case '\0':
5120b57cec5SDimitry Andric       Size = 4;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric       assert(!IsThumb);
5150b57cec5SDimitry Andric       EmitARMMappingSymbol();
5160b57cec5SDimitry Andric       for (unsigned II = 0, IE = Size; II != IE; II++) {
5170b57cec5SDimitry Andric         const unsigned I = LittleEndian ? (Size - II - 1) : II;
5180b57cec5SDimitry Andric         Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
5190b57cec5SDimitry Andric       }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric       break;
5220b57cec5SDimitry Andric     case 'n':
5230b57cec5SDimitry Andric     case 'w':
5240b57cec5SDimitry Andric       Size = (Suffix == 'n' ? 2 : 4);
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric       assert(IsThumb);
5270b57cec5SDimitry Andric       EmitThumbMappingSymbol();
5280b57cec5SDimitry Andric       // Thumb wide instructions are emitted as a pair of 16-bit words of the
5290b57cec5SDimitry Andric       // appropriate endianness.
5300b57cec5SDimitry Andric       for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
5310b57cec5SDimitry Andric         const unsigned I0 = LittleEndian ? II + 0 : II + 1;
5320b57cec5SDimitry Andric         const unsigned I1 = LittleEndian ? II + 1 : II + 0;
5330b57cec5SDimitry Andric         Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
5340b57cec5SDimitry Andric         Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
5350b57cec5SDimitry Andric       }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric       break;
5380b57cec5SDimitry Andric     default:
5390b57cec5SDimitry Andric       llvm_unreachable("Invalid Suffix");
5400b57cec5SDimitry Andric     }
5410b57cec5SDimitry Andric 
5425ffd83dbSDimitry Andric     MCELFStreamer::emitBytes(StringRef(Buffer, Size));
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   /// This is one of the functions used to emit data into an ELF section, so the
5460b57cec5SDimitry Andric   /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
5470b57cec5SDimitry Andric   /// necessary.
5485ffd83dbSDimitry Andric   void emitBytes(StringRef Data) override {
5495ffd83dbSDimitry Andric     emitDataMappingSymbol();
5505ffd83dbSDimitry Andric     MCELFStreamer::emitBytes(Data);
5510b57cec5SDimitry Andric   }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   void FlushPendingMappingSymbol() {
5540b57cec5SDimitry Andric     if (!LastEMSInfo->hasInfo())
5550b57cec5SDimitry Andric       return;
5560b57cec5SDimitry Andric     ElfMappingSymbolInfo *EMS = LastEMSInfo.get();
5570fca6ea1SDimitry Andric     emitMappingSymbol("$d", *EMS->F, EMS->Offset);
5580b57cec5SDimitry Andric     EMS->resetInfo();
5590b57cec5SDimitry Andric   }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   /// This is one of the functions used to emit data into an ELF section, so the
5620b57cec5SDimitry Andric   /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
5630b57cec5SDimitry Andric   /// necessary.
5645ffd83dbSDimitry Andric   void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override {
5650b57cec5SDimitry Andric     if (const MCSymbolRefExpr *SRE = dyn_cast_or_null<MCSymbolRefExpr>(Value)) {
5660b57cec5SDimitry Andric       if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_SBREL && !(Size == 4)) {
5670b57cec5SDimitry Andric         getContext().reportError(Loc, "relocated expression must be 32-bit");
5680b57cec5SDimitry Andric         return;
5690b57cec5SDimitry Andric       }
5700b57cec5SDimitry Andric       getOrCreateDataFragment();
5710b57cec5SDimitry Andric     }
5720b57cec5SDimitry Andric 
5735ffd83dbSDimitry Andric     emitDataMappingSymbol();
5745ffd83dbSDimitry Andric     MCELFStreamer::emitValueImpl(Value, Size, Loc);
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
5775ffd83dbSDimitry Andric   void emitAssemblerFlag(MCAssemblerFlag Flag) override {
5785ffd83dbSDimitry Andric     MCELFStreamer::emitAssemblerFlag(Flag);
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric     switch (Flag) {
5810b57cec5SDimitry Andric     case MCAF_SyntaxUnified:
5820b57cec5SDimitry Andric       return; // no-op here.
5830b57cec5SDimitry Andric     case MCAF_Code16:
5840b57cec5SDimitry Andric       IsThumb = true;
5850b57cec5SDimitry Andric       return; // Change to Thumb mode
5860b57cec5SDimitry Andric     case MCAF_Code32:
5870b57cec5SDimitry Andric       IsThumb = false;
5880b57cec5SDimitry Andric       return; // Change to ARM mode
5890b57cec5SDimitry Andric     case MCAF_Code64:
5900b57cec5SDimitry Andric       return;
5910b57cec5SDimitry Andric     case MCAF_SubsectionsViaSymbols:
5920b57cec5SDimitry Andric       return;
5930b57cec5SDimitry Andric     }
5940b57cec5SDimitry Andric   }
5950b57cec5SDimitry Andric 
596fe6060f1SDimitry Andric   /// If a label is defined before the .type directive sets the label's type
597fe6060f1SDimitry Andric   /// then the label can't be recorded as thumb function when the label is
598fe6060f1SDimitry Andric   /// defined. We override emitSymbolAttribute() which is called as part of the
599fe6060f1SDimitry Andric   /// parsing of .type so that if the symbol has already been defined we can
600fe6060f1SDimitry Andric   /// record the label as Thumb. FIXME: there is a corner case where the state
601fe6060f1SDimitry Andric   /// is changed in between the label definition and the .type directive, this
602fe6060f1SDimitry Andric   /// is not expected to occur in practice and handling it would require the
603fe6060f1SDimitry Andric   /// backend to track IsThumb for every label.
604fe6060f1SDimitry Andric   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
605fe6060f1SDimitry Andric     bool Val = MCELFStreamer::emitSymbolAttribute(Symbol, Attribute);
606fe6060f1SDimitry Andric 
607fe6060f1SDimitry Andric     if (!IsThumb)
608fe6060f1SDimitry Andric       return Val;
609fe6060f1SDimitry Andric 
610fe6060f1SDimitry Andric     unsigned Type = cast<MCSymbolELF>(Symbol)->getType();
611fe6060f1SDimitry Andric     if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC) &&
612fe6060f1SDimitry Andric         Symbol->isDefined())
613fe6060f1SDimitry Andric       getAssembler().setIsThumbFunc(Symbol);
614fe6060f1SDimitry Andric 
615fe6060f1SDimitry Andric     return Val;
616fe6060f1SDimitry Andric   };
617fe6060f1SDimitry Andric 
6180b57cec5SDimitry Andric private:
6190b57cec5SDimitry Andric   enum ElfMappingSymbol {
6200b57cec5SDimitry Andric     EMS_None,
6210b57cec5SDimitry Andric     EMS_ARM,
6220b57cec5SDimitry Andric     EMS_Thumb,
6230b57cec5SDimitry Andric     EMS_Data
6240b57cec5SDimitry Andric   };
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   struct ElfMappingSymbolInfo {
6270b57cec5SDimitry Andric     void resetInfo() {
6280b57cec5SDimitry Andric       F = nullptr;
6290b57cec5SDimitry Andric       Offset = 0;
6300b57cec5SDimitry Andric     }
6310b57cec5SDimitry Andric     bool hasInfo() { return F != nullptr; }
6320fca6ea1SDimitry Andric     MCDataFragment *F = nullptr;
6330fca6ea1SDimitry Andric     uint64_t Offset = 0;
6340fca6ea1SDimitry Andric     ElfMappingSymbol State = EMS_None;
6350b57cec5SDimitry Andric   };
6360b57cec5SDimitry Andric 
6375ffd83dbSDimitry Andric   void emitDataMappingSymbol() {
6380b57cec5SDimitry Andric     if (LastEMSInfo->State == EMS_Data)
6390b57cec5SDimitry Andric       return;
6400b57cec5SDimitry Andric     else if (LastEMSInfo->State == EMS_None) {
6410b57cec5SDimitry Andric       // This is a tentative symbol, it won't really be emitted until it's
6420b57cec5SDimitry Andric       // actually needed.
6430b57cec5SDimitry Andric       ElfMappingSymbolInfo *EMS = LastEMSInfo.get();
6440b57cec5SDimitry Andric       auto *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
6450b57cec5SDimitry Andric       if (!DF)
6460b57cec5SDimitry Andric         return;
6470fca6ea1SDimitry Andric       EMS->F = DF;
6480b57cec5SDimitry Andric       EMS->Offset = DF->getContents().size();
6490b57cec5SDimitry Andric       LastEMSInfo->State = EMS_Data;
6500b57cec5SDimitry Andric       return;
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric     EmitMappingSymbol("$d");
6530b57cec5SDimitry Andric     LastEMSInfo->State = EMS_Data;
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   void EmitThumbMappingSymbol() {
6570b57cec5SDimitry Andric     if (LastEMSInfo->State == EMS_Thumb)
6580b57cec5SDimitry Andric       return;
6590b57cec5SDimitry Andric     FlushPendingMappingSymbol();
6600b57cec5SDimitry Andric     EmitMappingSymbol("$t");
6610b57cec5SDimitry Andric     LastEMSInfo->State = EMS_Thumb;
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   void EmitARMMappingSymbol() {
6650b57cec5SDimitry Andric     if (LastEMSInfo->State == EMS_ARM)
6660b57cec5SDimitry Andric       return;
6670b57cec5SDimitry Andric     FlushPendingMappingSymbol();
6680b57cec5SDimitry Andric     EmitMappingSymbol("$a");
6690b57cec5SDimitry Andric     LastEMSInfo->State = EMS_ARM;
6700b57cec5SDimitry Andric   }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   void EmitMappingSymbol(StringRef Name) {
673*36b606aeSDimitry Andric     auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
6745ffd83dbSDimitry Andric     emitLabel(Symbol);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     Symbol->setType(ELF::STT_NOTYPE);
6770b57cec5SDimitry Andric     Symbol->setBinding(ELF::STB_LOCAL);
6780b57cec5SDimitry Andric   }
6790b57cec5SDimitry Andric 
6800fca6ea1SDimitry Andric   void emitMappingSymbol(StringRef Name, MCDataFragment &F, uint64_t Offset) {
681*36b606aeSDimitry Andric     auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
6820fca6ea1SDimitry Andric     emitLabelAtPos(Symbol, SMLoc(), F, Offset);
6830b57cec5SDimitry Andric     Symbol->setType(ELF::STT_NOTYPE);
6840b57cec5SDimitry Andric     Symbol->setBinding(ELF::STB_LOCAL);
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric 
6875ffd83dbSDimitry Andric   void emitThumbFunc(MCSymbol *Func) override {
6880b57cec5SDimitry Andric     getAssembler().setIsThumbFunc(Func);
6895ffd83dbSDimitry Andric     emitSymbolAttribute(Func, MCSA_ELF_TypeFunction);
6900b57cec5SDimitry Andric   }
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric   // Helper functions for ARM exception handling directives
6930b57cec5SDimitry Andric   void EHReset();
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   // Reset state between object emissions
6960b57cec5SDimitry Andric   void reset() override;
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   void EmitPersonalityFixup(StringRef Name);
6990b57cec5SDimitry Andric   void FlushPendingOffset();
7000b57cec5SDimitry Andric   void FlushUnwindOpcodes(bool NoHandlerData);
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   void SwitchToEHSection(StringRef Prefix, unsigned Type, unsigned Flags,
7030b57cec5SDimitry Andric                          SectionKind Kind, const MCSymbol &Fn);
7040b57cec5SDimitry Andric   void SwitchToExTabSection(const MCSymbol &FnStart);
7050b57cec5SDimitry Andric   void SwitchToExIdxSection(const MCSymbol &FnStart);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   void EmitFixup(const MCExpr *Expr, MCFixupKind Kind);
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   bool IsThumb;
710480093f4SDimitry Andric   bool IsAndroid;
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric   DenseMap<const MCSection *, std::unique_ptr<ElfMappingSymbolInfo>>
7130b57cec5SDimitry Andric       LastMappingSymbols;
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   std::unique_ptr<ElfMappingSymbolInfo> LastEMSInfo;
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   // ARM Exception Handling Frame Information
7180b57cec5SDimitry Andric   MCSymbol *ExTab;
7190b57cec5SDimitry Andric   MCSymbol *FnStart;
7200b57cec5SDimitry Andric   const MCSymbol *Personality;
7210b57cec5SDimitry Andric   unsigned PersonalityIndex;
7220b57cec5SDimitry Andric   unsigned FPReg; // Frame pointer register
7230b57cec5SDimitry Andric   int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp)
7240b57cec5SDimitry Andric   int64_t SPOffset; // Offset: (final $sp) - (initial $sp)
7250b57cec5SDimitry Andric   int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp)
7260b57cec5SDimitry Andric   bool UsedFP;
7270b57cec5SDimitry Andric   bool CantUnwind;
7280b57cec5SDimitry Andric   SmallVector<uint8_t, 64> Opcodes;
7290b57cec5SDimitry Andric   UnwindOpcodeAssembler UnwindOpAsm;
7300b57cec5SDimitry Andric };
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric } // end anonymous namespace
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric ARMELFStreamer &ARMTargetELFStreamer::getStreamer() {
7350b57cec5SDimitry Andric   return static_cast<ARMELFStreamer &>(Streamer);
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); }
7390b57cec5SDimitry Andric void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); }
7400b57cec5SDimitry Andric void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); }
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
7430b57cec5SDimitry Andric   getStreamer().emitPersonality(Personality);
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) {
7470b57cec5SDimitry Andric   getStreamer().emitPersonalityIndex(Index);
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric void ARMTargetELFStreamer::emitHandlerData() {
7510b57cec5SDimitry Andric   getStreamer().emitHandlerData();
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
7550b57cec5SDimitry Andric                                      int64_t Offset) {
7560b57cec5SDimitry Andric   getStreamer().emitSetFP(FpReg, SpReg, Offset);
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
7600b57cec5SDimitry Andric   getStreamer().emitMovSP(Reg, Offset);
7610b57cec5SDimitry Andric }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPad(int64_t Offset) {
7640b57cec5SDimitry Andric   getStreamer().emitPad(Offset);
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
7680b57cec5SDimitry Andric                                        bool isVector) {
7690b57cec5SDimitry Andric   getStreamer().emitRegSave(RegList, isVector);
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
7730b57cec5SDimitry Andric                                       const SmallVectorImpl<uint8_t> &Opcodes) {
7740b57cec5SDimitry Andric   getStreamer().emitUnwindRaw(Offset, Opcodes);
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric void ARMTargetELFStreamer::switchVendor(StringRef Vendor) {
7780b57cec5SDimitry Andric   assert(!Vendor.empty() && "Vendor cannot be empty.");
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   if (CurrentVendor == Vendor)
7810b57cec5SDimitry Andric     return;
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric   if (!CurrentVendor.empty())
7840b57cec5SDimitry Andric     finishAttributeSection();
7850b57cec5SDimitry Andric 
786fe6060f1SDimitry Andric   assert(getStreamer().Contents.empty() &&
7870b57cec5SDimitry Andric          ".ARM.attributes should be flushed before changing vendor");
7880b57cec5SDimitry Andric   CurrentVendor = Vendor;
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
793fe6060f1SDimitry Andric   getStreamer().setAttributeItem(Attribute, Value,
794fe6060f1SDimitry Andric                                  /* OverwriteExisting= */ true);
7950b57cec5SDimitry Andric }
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric void ARMTargetELFStreamer::emitTextAttribute(unsigned Attribute,
7980b57cec5SDimitry Andric                                              StringRef Value) {
799fe6060f1SDimitry Andric   getStreamer().setAttributeItem(Attribute, Value,
800fe6060f1SDimitry Andric                                  /* OverwriteExisting= */ true);
8010b57cec5SDimitry Andric }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric void ARMTargetELFStreamer::emitIntTextAttribute(unsigned Attribute,
8040b57cec5SDimitry Andric                                                 unsigned IntValue,
8050b57cec5SDimitry Andric                                                 StringRef StringValue) {
806fe6060f1SDimitry Andric   getStreamer().setAttributeItems(Attribute, IntValue, StringValue,
8070b57cec5SDimitry Andric                                   /* OverwriteExisting= */ true);
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
8110b57cec5SDimitry Andric   Arch = Value;
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric void ARMTargetELFStreamer::emitObjectArch(ARM::ArchKind Value) {
8150b57cec5SDimitry Andric   EmittedArch = Value;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric void ARMTargetELFStreamer::emitArchDefaultAttributes() {
8190b57cec5SDimitry Andric   using namespace ARMBuildAttrs;
820fe6060f1SDimitry Andric   ARMELFStreamer &S = getStreamer();
8210b57cec5SDimitry Andric 
822fe6060f1SDimitry Andric   S.setAttributeItem(CPU_name, ARM::getCPUAttr(Arch), false);
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   if (EmittedArch == ARM::ArchKind::INVALID)
825fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch, ARM::getArchAttr(Arch), false);
8260b57cec5SDimitry Andric   else
827fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch, ARM::getArchAttr(EmittedArch), false);
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric   switch (Arch) {
8300b57cec5SDimitry Andric   case ARM::ArchKind::ARMV4:
831fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
8320b57cec5SDimitry Andric     break;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   case ARM::ArchKind::ARMV4T:
8350b57cec5SDimitry Andric   case ARM::ArchKind::ARMV5T:
836fe6060f1SDimitry Andric   case ARM::ArchKind::XSCALE:
8370b57cec5SDimitry Andric   case ARM::ArchKind::ARMV5TE:
8380b57cec5SDimitry Andric   case ARM::ArchKind::ARMV6:
839fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
840fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, Allowed, false);
8410b57cec5SDimitry Andric     break;
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric   case ARM::ArchKind::ARMV6T2:
844fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
845fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
8460b57cec5SDimitry Andric     break;
8470b57cec5SDimitry Andric 
8480b57cec5SDimitry Andric   case ARM::ArchKind::ARMV6K:
8490b57cec5SDimitry Andric   case ARM::ArchKind::ARMV6KZ:
850fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
851fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, Allowed, false);
852fe6060f1SDimitry Andric     S.setAttributeItem(Virtualization_use, AllowTZ, false);
8530b57cec5SDimitry Andric     break;
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric   case ARM::ArchKind::ARMV6M:
856fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, Allowed, false);
8570b57cec5SDimitry Andric     break;
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric   case ARM::ArchKind::ARMV7A:
860fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
861fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
862fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
8630b57cec5SDimitry Andric     break;
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   case ARM::ArchKind::ARMV7R:
866fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch_profile, RealTimeProfile, false);
867fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
868fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
8690b57cec5SDimitry Andric     break;
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric   case ARM::ArchKind::ARMV7EM:
8720b57cec5SDimitry Andric   case ARM::ArchKind::ARMV7M:
873fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
874fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
8750b57cec5SDimitry Andric     break;
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8A:
8780b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8_1A:
8790b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8_2A:
8800b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8_3A:
8810b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8_4A:
8820b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8_5A:
8835ffd83dbSDimitry Andric   case ARM::ArchKind::ARMV8_6A:
884bdd1243dSDimitry Andric   case ARM::ArchKind::ARMV8_7A:
885bdd1243dSDimitry Andric   case ARM::ArchKind::ARMV8_8A:
886bdd1243dSDimitry Andric   case ARM::ArchKind::ARMV8_9A:
887349cc55cSDimitry Andric   case ARM::ArchKind::ARMV9A:
888349cc55cSDimitry Andric   case ARM::ArchKind::ARMV9_1A:
889349cc55cSDimitry Andric   case ARM::ArchKind::ARMV9_2A:
89004eeddc0SDimitry Andric   case ARM::ArchKind::ARMV9_3A:
891bdd1243dSDimitry Andric   case ARM::ArchKind::ARMV9_4A:
8927a6dacacSDimitry Andric   case ARM::ArchKind::ARMV9_5A:
893fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch_profile, ApplicationProfile, false);
894fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
895fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumb32, false);
896fe6060f1SDimitry Andric     S.setAttributeItem(MPextension_use, Allowed, false);
897fe6060f1SDimitry Andric     S.setAttributeItem(Virtualization_use, AllowTZVirtualization, false);
8980b57cec5SDimitry Andric     break;
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8MBaseline:
9010b57cec5SDimitry Andric   case ARM::ArchKind::ARMV8MMainline:
902fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, AllowThumbDerived, false);
903fe6060f1SDimitry Andric     S.setAttributeItem(CPU_arch_profile, MicroControllerProfile, false);
9040b57cec5SDimitry Andric     break;
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   case ARM::ArchKind::IWMMXT:
907fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
908fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, Allowed, false);
909fe6060f1SDimitry Andric     S.setAttributeItem(WMMX_arch, AllowWMMXv1, false);
9100b57cec5SDimitry Andric     break;
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   case ARM::ArchKind::IWMMXT2:
913fe6060f1SDimitry Andric     S.setAttributeItem(ARM_ISA_use, Allowed, false);
914fe6060f1SDimitry Andric     S.setAttributeItem(THUMB_ISA_use, Allowed, false);
915fe6060f1SDimitry Andric     S.setAttributeItem(WMMX_arch, AllowWMMXv2, false);
9160b57cec5SDimitry Andric     break;
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   default:
9190b57cec5SDimitry Andric     report_fatal_error("Unknown Arch: " + Twine(ARM::getArchName(Arch)));
9200b57cec5SDimitry Andric     break;
9210b57cec5SDimitry Andric   }
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
92406c3fb27SDimitry Andric void ARMTargetELFStreamer::emitFPU(ARM::FPUKind Value) { FPU = Value; }
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric void ARMTargetELFStreamer::emitFPUDefaultAttributes() {
927fe6060f1SDimitry Andric   ARMELFStreamer &S = getStreamer();
928fe6060f1SDimitry Andric 
9290b57cec5SDimitry Andric   switch (FPU) {
9300b57cec5SDimitry Andric   case ARM::FK_VFP:
9310b57cec5SDimitry Andric   case ARM::FK_VFPV2:
932fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv2,
9330b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9340b57cec5SDimitry Andric     break;
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   case ARM::FK_VFPV3:
937fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
9380b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9390b57cec5SDimitry Andric     break;
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric   case ARM::FK_VFPV3_FP16:
942fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
9430b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
944fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
9450b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9460b57cec5SDimitry Andric     break;
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   case ARM::FK_VFPV3_D16:
949fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
9500b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9510b57cec5SDimitry Andric     break;
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   case ARM::FK_VFPV3_D16_FP16:
954fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
9550b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
956fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
9570b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9580b57cec5SDimitry Andric     break;
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   case ARM::FK_VFPV3XD:
961fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
9620b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9630b57cec5SDimitry Andric     break;
9640b57cec5SDimitry Andric   case ARM::FK_VFPV3XD_FP16:
965fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3B,
9660b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
967fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
9680b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9690b57cec5SDimitry Andric     break;
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   case ARM::FK_VFPV4:
972fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
9730b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9740b57cec5SDimitry Andric     break;
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric   // ABI_HardFP_use is handled in ARMAsmPrinter, so _SP_D16 is treated the same
9770b57cec5SDimitry Andric   // as _D16 here.
9780b57cec5SDimitry Andric   case ARM::FK_FPV4_SP_D16:
9790b57cec5SDimitry Andric   case ARM::FK_VFPV4_D16:
980fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4B,
9810b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9820b57cec5SDimitry Andric     break;
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric   case ARM::FK_FP_ARMV8:
985fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
9860b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9870b57cec5SDimitry Andric     break;
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric   // FPV5_D16 is identical to FP_ARMV8 except for the number of D registers, so
9900b57cec5SDimitry Andric   // uses the FP_ARMV8_D16 build attribute.
9910b57cec5SDimitry Andric   case ARM::FK_FPV5_SP_D16:
9920b57cec5SDimitry Andric   case ARM::FK_FPV5_D16:
993fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8B,
9940b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
9950b57cec5SDimitry Andric     break;
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   case ARM::FK_NEON:
998fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
9990b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
1000fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
10010b57cec5SDimitry Andric                        ARMBuildAttrs::AllowNeon,
10020b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
10030b57cec5SDimitry Andric     break;
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   case ARM::FK_NEON_FP16:
1006fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv3A,
10070b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
1008fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
10090b57cec5SDimitry Andric                        ARMBuildAttrs::AllowNeon,
10100b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
1011fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP,
10120b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
10130b57cec5SDimitry Andric     break;
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   case ARM::FK_NEON_VFPV4:
1016fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPv4A,
10170b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
1018fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::Advanced_SIMD_arch,
10190b57cec5SDimitry Andric                        ARMBuildAttrs::AllowNeon2,
10200b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
10210b57cec5SDimitry Andric     break;
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   case ARM::FK_NEON_FP_ARMV8:
10240b57cec5SDimitry Andric   case ARM::FK_CRYPTO_NEON_FP_ARMV8:
1025fe6060f1SDimitry Andric     S.setAttributeItem(ARMBuildAttrs::FP_arch, ARMBuildAttrs::AllowFPARMv8A,
10260b57cec5SDimitry Andric                        /* OverwriteExisting= */ false);
10270b57cec5SDimitry Andric     // 'Advanced_SIMD_arch' must be emitted not here, but within
10280b57cec5SDimitry Andric     // ARMAsmPrinter::emitAttributes(), depending on hasV8Ops() and hasV8_1a()
10290b57cec5SDimitry Andric     break;
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   case ARM::FK_SOFTVFP:
10320b57cec5SDimitry Andric   case ARM::FK_NONE:
10330b57cec5SDimitry Andric     break;
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   default:
10360b57cec5SDimitry Andric     report_fatal_error("Unknown FPU: " + Twine(FPU));
10370b57cec5SDimitry Andric     break;
10380b57cec5SDimitry Andric   }
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric void ARMTargetELFStreamer::finishAttributeSection() {
1042fe6060f1SDimitry Andric   ARMELFStreamer &S = getStreamer();
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   if (FPU != ARM::FK_INVALID)
10450b57cec5SDimitry Andric     emitFPUDefaultAttributes();
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   if (Arch != ARM::ArchKind::INVALID)
10480b57cec5SDimitry Andric     emitArchDefaultAttributes();
10490b57cec5SDimitry Andric 
1050fe6060f1SDimitry Andric   if (S.Contents.empty())
10510b57cec5SDimitry Andric     return;
10520b57cec5SDimitry Andric 
1053fe6060f1SDimitry Andric   auto LessTag = [](const MCELFStreamer::AttributeItem &LHS,
1054fe6060f1SDimitry Andric                     const MCELFStreamer::AttributeItem &RHS) -> bool {
1055fe6060f1SDimitry Andric     // The conformance tag must be emitted first when serialised into an
1056fe6060f1SDimitry Andric     // object file. Specifically, the addenda to the ARM ABI states that
1057fe6060f1SDimitry Andric     // (2.3.7.4):
1058fe6060f1SDimitry Andric     //
1059fe6060f1SDimitry Andric     // "To simplify recognition by consumers in the common case of claiming
1060fe6060f1SDimitry Andric     // conformity for the whole file, this tag should be emitted first in a
1061fe6060f1SDimitry Andric     // file-scope sub-subsection of the first public subsection of the
1062fe6060f1SDimitry Andric     // attributes section."
1063fe6060f1SDimitry Andric     //
1064fe6060f1SDimitry Andric     // So it is special-cased in this comparison predicate when the
1065fe6060f1SDimitry Andric     // attributes are sorted in finishAttributeSection().
1066fe6060f1SDimitry Andric     return (RHS.Tag != ARMBuildAttrs::conformance) &&
1067fe6060f1SDimitry Andric            ((LHS.Tag == ARMBuildAttrs::conformance) || (LHS.Tag < RHS.Tag));
1068fe6060f1SDimitry Andric   };
1069fe6060f1SDimitry Andric   llvm::sort(S.Contents, LessTag);
10700b57cec5SDimitry Andric 
1071fe6060f1SDimitry Andric   S.emitAttributesSection(CurrentVendor, ".ARM.attributes",
1072fe6060f1SDimitry Andric                           ELF::SHT_ARM_ATTRIBUTES, AttributeSection);
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   FPU = ARM::FK_INVALID;
10750b57cec5SDimitry Andric }
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric void ARMTargetELFStreamer::emitLabel(MCSymbol *Symbol) {
10780b57cec5SDimitry Andric   ARMELFStreamer &Streamer = getStreamer();
10790b57cec5SDimitry Andric   if (!Streamer.IsThumb)
10800b57cec5SDimitry Andric     return;
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   Streamer.getAssembler().registerSymbol(*Symbol);
10830b57cec5SDimitry Andric   unsigned Type = cast<MCSymbolELF>(Symbol)->getType();
10840b57cec5SDimitry Andric   if (Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC)
10855ffd83dbSDimitry Andric     Streamer.emitThumbFunc(Symbol);
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
108881ad6265SDimitry Andric void ARMTargetELFStreamer::annotateTLSDescriptorSequence(
108981ad6265SDimitry Andric     const MCSymbolRefExpr *S) {
10900b57cec5SDimitry Andric   getStreamer().EmitFixup(S, FK_Data_4);
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric void ARMTargetELFStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {
10940b57cec5SDimitry Andric   if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Value)) {
10950b57cec5SDimitry Andric     const MCSymbol &Sym = SRE->getSymbol();
10960b57cec5SDimitry Andric     if (!Sym.isDefined()) {
10975ffd83dbSDimitry Andric       getStreamer().emitAssignment(Symbol, Value);
10980b57cec5SDimitry Andric       return;
10990b57cec5SDimitry Andric     }
11000b57cec5SDimitry Andric   }
11010b57cec5SDimitry Andric 
11025ffd83dbSDimitry Andric   getStreamer().emitThumbFunc(Symbol);
11035ffd83dbSDimitry Andric   getStreamer().emitAssignment(Symbol, Value);
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
11070b57cec5SDimitry Andric   getStreamer().emitInst(Inst, Suffix);
11080b57cec5SDimitry Andric }
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric void ARMTargetELFStreamer::reset() { AttributeSection = nullptr; }
11110b57cec5SDimitry Andric 
11120fca6ea1SDimitry Andric void ARMTargetELFStreamer::finish() {
11130fca6ea1SDimitry Andric   ARMTargetStreamer::finish();
11140fca6ea1SDimitry Andric   finishAttributeSection();
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric void ARMELFStreamer::reset() {
11180b57cec5SDimitry Andric   MCTargetStreamer &TS = *getTargetStreamer();
11190b57cec5SDimitry Andric   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
11200b57cec5SDimitry Andric   ATS.reset();
11210b57cec5SDimitry Andric   MCELFStreamer::reset();
11220b57cec5SDimitry Andric   LastMappingSymbols.clear();
11230b57cec5SDimitry Andric   LastEMSInfo.reset();
11240b57cec5SDimitry Andric   // MCELFStreamer clear's the assembler's e_flags. However, for
11250b57cec5SDimitry Andric   // arm we manually set the ABI version on streamer creation, so
11260b57cec5SDimitry Andric   // do the same here
11270fca6ea1SDimitry Andric   getWriter().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5);
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric inline void ARMELFStreamer::SwitchToEHSection(StringRef Prefix,
11310b57cec5SDimitry Andric                                               unsigned Type,
11320b57cec5SDimitry Andric                                               unsigned Flags,
11330b57cec5SDimitry Andric                                               SectionKind Kind,
11340b57cec5SDimitry Andric                                               const MCSymbol &Fn) {
11350b57cec5SDimitry Andric   const MCSectionELF &FnSection =
11360b57cec5SDimitry Andric     static_cast<const MCSectionELF &>(Fn.getSection());
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   // Create the name for new section
11395ffd83dbSDimitry Andric   StringRef FnSecName(FnSection.getName());
11400b57cec5SDimitry Andric   SmallString<128> EHSecName(Prefix);
11410b57cec5SDimitry Andric   if (FnSecName != ".text") {
11420b57cec5SDimitry Andric     EHSecName += FnSecName;
11430b57cec5SDimitry Andric   }
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   // Get .ARM.extab or .ARM.exidx section
11460b57cec5SDimitry Andric   const MCSymbolELF *Group = FnSection.getGroup();
11470b57cec5SDimitry Andric   if (Group)
11480b57cec5SDimitry Andric     Flags |= ELF::SHF_GROUP;
11490b57cec5SDimitry Andric   MCSectionELF *EHSection = getContext().getELFSection(
1150fe6060f1SDimitry Andric       EHSecName, Type, Flags, 0, Group, /*IsComdat=*/true,
1151fe6060f1SDimitry Andric       FnSection.getUniqueID(),
11525ffd83dbSDimitry Andric       static_cast<const MCSymbolELF *>(FnSection.getBeginSymbol()));
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   assert(EHSection && "Failed to get the required EH section");
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   // Switch to .ARM.extab or .ARM.exidx section
115781ad6265SDimitry Andric   switchSection(EHSection);
1158bdd1243dSDimitry Andric   emitValueToAlignment(Align(4), 0, 1, 0);
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
11620b57cec5SDimitry Andric   SwitchToEHSection(".ARM.extab", ELF::SHT_PROGBITS, ELF::SHF_ALLOC,
11630b57cec5SDimitry Andric                     SectionKind::getData(), FnStart);
11640b57cec5SDimitry Andric }
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
11670b57cec5SDimitry Andric   SwitchToEHSection(".ARM.exidx", ELF::SHT_ARM_EXIDX,
11680b57cec5SDimitry Andric                     ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
11690b57cec5SDimitry Andric                     SectionKind::getData(), FnStart);
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) {
11730b57cec5SDimitry Andric   MCDataFragment *Frag = getOrCreateDataFragment();
11740b57cec5SDimitry Andric   Frag->getFixups().push_back(MCFixup::create(Frag->getContents().size(), Expr,
11750b57cec5SDimitry Andric                                               Kind));
11760b57cec5SDimitry Andric }
11770b57cec5SDimitry Andric 
11780b57cec5SDimitry Andric void ARMELFStreamer::EHReset() {
11790b57cec5SDimitry Andric   ExTab = nullptr;
11800b57cec5SDimitry Andric   FnStart = nullptr;
11810b57cec5SDimitry Andric   Personality = nullptr;
11820b57cec5SDimitry Andric   PersonalityIndex = ARM::EHABI::NUM_PERSONALITY_INDEX;
11830b57cec5SDimitry Andric   FPReg = ARM::SP;
11840b57cec5SDimitry Andric   FPOffset = 0;
11850b57cec5SDimitry Andric   SPOffset = 0;
11860b57cec5SDimitry Andric   PendingOffset = 0;
11870b57cec5SDimitry Andric   UsedFP = false;
11880b57cec5SDimitry Andric   CantUnwind = false;
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric   Opcodes.clear();
11910b57cec5SDimitry Andric   UnwindOpAsm.Reset();
11920b57cec5SDimitry Andric }
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric void ARMELFStreamer::emitFnStart() {
11950b57cec5SDimitry Andric   assert(FnStart == nullptr);
11960b57cec5SDimitry Andric   FnStart = getContext().createTempSymbol();
11975ffd83dbSDimitry Andric   emitLabel(FnStart);
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric void ARMELFStreamer::emitFnEnd() {
12010b57cec5SDimitry Andric   assert(FnStart && ".fnstart must precedes .fnend");
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   // Emit unwind opcodes if there is no .handlerdata directive
12040b57cec5SDimitry Andric   if (!ExTab && !CantUnwind)
12050b57cec5SDimitry Andric     FlushUnwindOpcodes(true);
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric   // Emit the exception index table entry
12080b57cec5SDimitry Andric   SwitchToExIdxSection(*FnStart);
12090b57cec5SDimitry Andric 
1210480093f4SDimitry Andric   // The EHABI requires a dependency preserving R_ARM_NONE relocation to the
1211480093f4SDimitry Andric   // personality routine to protect it from an arbitrary platform's static
1212480093f4SDimitry Andric   // linker garbage collection. We disable this for Android where the unwinder
1213480093f4SDimitry Andric   // is either dynamically linked or directly references the personality
1214480093f4SDimitry Andric   // routine.
1215480093f4SDimitry Andric   if (PersonalityIndex < ARM::EHABI::NUM_PERSONALITY_INDEX && !IsAndroid)
12160b57cec5SDimitry Andric     EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   const MCSymbolRefExpr *FnStartRef =
12190b57cec5SDimitry Andric     MCSymbolRefExpr::create(FnStart,
12200b57cec5SDimitry Andric                             MCSymbolRefExpr::VK_ARM_PREL31,
12210b57cec5SDimitry Andric                             getContext());
12220b57cec5SDimitry Andric 
12235ffd83dbSDimitry Andric   emitValue(FnStartRef, 4);
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric   if (CantUnwind) {
12265ffd83dbSDimitry Andric     emitInt32(ARM::EHABI::EXIDX_CANTUNWIND);
12270b57cec5SDimitry Andric   } else if (ExTab) {
12280b57cec5SDimitry Andric     // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
12290b57cec5SDimitry Andric     const MCSymbolRefExpr *ExTabEntryRef =
12300b57cec5SDimitry Andric       MCSymbolRefExpr::create(ExTab,
12310b57cec5SDimitry Andric                               MCSymbolRefExpr::VK_ARM_PREL31,
12320b57cec5SDimitry Andric                               getContext());
12335ffd83dbSDimitry Andric     emitValue(ExTabEntryRef, 4);
12340b57cec5SDimitry Andric   } else {
12350b57cec5SDimitry Andric     // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
12360b57cec5SDimitry Andric     // the second word of exception index table entry.  The size of the unwind
12370b57cec5SDimitry Andric     // opcodes should always be 4 bytes.
12380b57cec5SDimitry Andric     assert(PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0 &&
12390b57cec5SDimitry Andric            "Compact model must use __aeabi_unwind_cpp_pr0 as personality");
12400b57cec5SDimitry Andric     assert(Opcodes.size() == 4u &&
12410b57cec5SDimitry Andric            "Unwind opcode size for __aeabi_unwind_cpp_pr0 must be equal to 4");
12420b57cec5SDimitry Andric     uint64_t Intval = Opcodes[0] |
12430b57cec5SDimitry Andric                       Opcodes[1] << 8 |
12440b57cec5SDimitry Andric                       Opcodes[2] << 16 |
12450b57cec5SDimitry Andric                       Opcodes[3] << 24;
12465ffd83dbSDimitry Andric     emitIntValue(Intval, Opcodes.size());
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   // Switch to the section containing FnStart
125081ad6265SDimitry Andric   switchSection(&FnStart->getSection());
12510b57cec5SDimitry Andric 
12520b57cec5SDimitry Andric   // Clean exception handling frame information
12530b57cec5SDimitry Andric   EHReset();
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; }
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric // Add the R_ARM_NONE fixup at the same position
12590b57cec5SDimitry Andric void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
12600b57cec5SDimitry Andric   const MCSymbol *PersonalitySym = getContext().getOrCreateSymbol(Name);
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric   const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::create(
12630b57cec5SDimitry Andric       PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext());
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   visitUsedExpr(*PersonalityRef);
12660b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
12670b57cec5SDimitry Andric   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
12680b57cec5SDimitry Andric                                             PersonalityRef,
12690b57cec5SDimitry Andric                                             MCFixup::getKindForSize(4, false)));
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric void ARMELFStreamer::FlushPendingOffset() {
12730b57cec5SDimitry Andric   if (PendingOffset != 0) {
12740b57cec5SDimitry Andric     UnwindOpAsm.EmitSPOffset(-PendingOffset);
12750b57cec5SDimitry Andric     PendingOffset = 0;
12760b57cec5SDimitry Andric   }
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
12800b57cec5SDimitry Andric   // Emit the unwind opcode to restore $sp.
12810b57cec5SDimitry Andric   if (UsedFP) {
12820b57cec5SDimitry Andric     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
12830b57cec5SDimitry Andric     int64_t LastRegSaveSPOffset = SPOffset - PendingOffset;
12840b57cec5SDimitry Andric     UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset);
12850b57cec5SDimitry Andric     UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
12860b57cec5SDimitry Andric   } else {
12870b57cec5SDimitry Andric     FlushPendingOffset();
12880b57cec5SDimitry Andric   }
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   // Finalize the unwind opcode sequence
12910b57cec5SDimitry Andric   UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
12940b57cec5SDimitry Andric   // section.  Thus, we don't have to create an entry in the .ARM.extab
12950b57cec5SDimitry Andric   // section.
12960b57cec5SDimitry Andric   if (NoHandlerData && PersonalityIndex == ARM::EHABI::AEABI_UNWIND_CPP_PR0)
12970b57cec5SDimitry Andric     return;
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   // Switch to .ARM.extab section.
13000b57cec5SDimitry Andric   SwitchToExTabSection(*FnStart);
13010b57cec5SDimitry Andric 
13020b57cec5SDimitry Andric   // Create .ARM.extab label for offset in .ARM.exidx
13030b57cec5SDimitry Andric   assert(!ExTab);
13040b57cec5SDimitry Andric   ExTab = getContext().createTempSymbol();
13055ffd83dbSDimitry Andric   emitLabel(ExTab);
13060b57cec5SDimitry Andric 
13070b57cec5SDimitry Andric   // Emit personality
13080b57cec5SDimitry Andric   if (Personality) {
13090b57cec5SDimitry Andric     const MCSymbolRefExpr *PersonalityRef =
13100b57cec5SDimitry Andric       MCSymbolRefExpr::create(Personality,
13110b57cec5SDimitry Andric                               MCSymbolRefExpr::VK_ARM_PREL31,
13120b57cec5SDimitry Andric                               getContext());
13130b57cec5SDimitry Andric 
13145ffd83dbSDimitry Andric     emitValue(PersonalityRef, 4);
13150b57cec5SDimitry Andric   }
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric   // Emit unwind opcodes
13180b57cec5SDimitry Andric   assert((Opcodes.size() % 4) == 0 &&
13190b57cec5SDimitry Andric          "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be multiple of 4");
13200b57cec5SDimitry Andric   for (unsigned I = 0; I != Opcodes.size(); I += 4) {
13210b57cec5SDimitry Andric     uint64_t Intval = Opcodes[I] |
13220b57cec5SDimitry Andric                       Opcodes[I + 1] << 8 |
13230b57cec5SDimitry Andric                       Opcodes[I + 2] << 16 |
13240b57cec5SDimitry Andric                       Opcodes[I + 3] << 24;
13255ffd83dbSDimitry Andric     emitInt32(Intval);
13260b57cec5SDimitry Andric   }
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or
13290b57cec5SDimitry Andric   // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted
13300b57cec5SDimitry Andric   // after the unwind opcodes.  The handler data consists of several 32-bit
13310b57cec5SDimitry Andric   // words, and should be terminated by zero.
13320b57cec5SDimitry Andric   //
13330b57cec5SDimitry Andric   // In case that the .handlerdata directive is not specified by the
13340b57cec5SDimitry Andric   // programmer, we should emit zero to terminate the handler data.
13350b57cec5SDimitry Andric   if (NoHandlerData && !Personality)
13365ffd83dbSDimitry Andric     emitInt32(0);
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); }
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric void ARMELFStreamer::emitPersonality(const MCSymbol *Per) {
13420b57cec5SDimitry Andric   Personality = Per;
13430b57cec5SDimitry Andric   UnwindOpAsm.setPersonality(Per);
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric void ARMELFStreamer::emitPersonalityIndex(unsigned Index) {
13470b57cec5SDimitry Andric   assert(Index < ARM::EHABI::NUM_PERSONALITY_INDEX && "invalid index");
13480b57cec5SDimitry Andric   PersonalityIndex = Index;
13490b57cec5SDimitry Andric }
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg,
13520b57cec5SDimitry Andric                                int64_t Offset) {
13530b57cec5SDimitry Andric   assert((NewSPReg == ARM::SP || NewSPReg == FPReg) &&
13540b57cec5SDimitry Andric          "the operand of .setfp directive should be either $sp or $fp");
13550b57cec5SDimitry Andric 
13560b57cec5SDimitry Andric   UsedFP = true;
13570b57cec5SDimitry Andric   FPReg = NewFPReg;
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   if (NewSPReg == ARM::SP)
13600b57cec5SDimitry Andric     FPOffset = SPOffset + Offset;
13610b57cec5SDimitry Andric   else
13620b57cec5SDimitry Andric     FPOffset += Offset;
13630b57cec5SDimitry Andric }
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
13660b57cec5SDimitry Andric   assert((Reg != ARM::SP && Reg != ARM::PC) &&
13670b57cec5SDimitry Andric          "the operand of .movsp cannot be either sp or pc");
13680b57cec5SDimitry Andric   assert(FPReg == ARM::SP && "current FP must be SP");
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric   FlushPendingOffset();
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   FPReg = Reg;
13730b57cec5SDimitry Andric   FPOffset = SPOffset + Offset;
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric   const MCRegisterInfo *MRI = getContext().getRegisterInfo();
13760b57cec5SDimitry Andric   UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
13770b57cec5SDimitry Andric }
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric void ARMELFStreamer::emitPad(int64_t Offset) {
13800b57cec5SDimitry Andric   // Track the change of the $sp offset
13810b57cec5SDimitry Andric   SPOffset -= Offset;
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric   // To squash multiple .pad directives, we should delay the unwind opcode
13840b57cec5SDimitry Andric   // until the .save, .vsave, .handlerdata, or .fnend directives.
13850b57cec5SDimitry Andric   PendingOffset -= Offset;
13860b57cec5SDimitry Andric }
13870b57cec5SDimitry Andric 
13880eae32dcSDimitry Andric static std::pair<unsigned, unsigned>
13890eae32dcSDimitry Andric collectHWRegs(const MCRegisterInfo &MRI, unsigned Idx,
13900eae32dcSDimitry Andric               const SmallVectorImpl<unsigned> &RegList, bool IsVector,
13910eae32dcSDimitry Andric               uint32_t &Mask_) {
13920b57cec5SDimitry Andric   uint32_t Mask = 0;
13930eae32dcSDimitry Andric   unsigned Count = 0;
13940eae32dcSDimitry Andric   while (Idx > 0) {
13950eae32dcSDimitry Andric     unsigned Reg = RegList[Idx - 1];
13960eae32dcSDimitry Andric     if (Reg == ARM::RA_AUTH_CODE)
13970eae32dcSDimitry Andric       break;
13980eae32dcSDimitry Andric     Reg = MRI.getEncodingValue(Reg);
13990b57cec5SDimitry Andric     assert(Reg < (IsVector ? 32U : 16U) && "Register out of range");
14000b57cec5SDimitry Andric     unsigned Bit = (1u << Reg);
14010b57cec5SDimitry Andric     if ((Mask & Bit) == 0) {
14020b57cec5SDimitry Andric       Mask |= Bit;
14030b57cec5SDimitry Andric       ++Count;
14040b57cec5SDimitry Andric     }
14050eae32dcSDimitry Andric     --Idx;
14060b57cec5SDimitry Andric   }
14070b57cec5SDimitry Andric 
14080eae32dcSDimitry Andric   Mask_ = Mask;
14090eae32dcSDimitry Andric   return {Idx, Count};
14100eae32dcSDimitry Andric }
14110eae32dcSDimitry Andric 
14120eae32dcSDimitry Andric void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
14130eae32dcSDimitry Andric                                  bool IsVector) {
14140eae32dcSDimitry Andric   uint32_t Mask;
14150eae32dcSDimitry Andric   unsigned Idx, Count;
14160eae32dcSDimitry Andric   const MCRegisterInfo &MRI = *getContext().getRegisterInfo();
14170eae32dcSDimitry Andric 
14180eae32dcSDimitry Andric   // Collect the registers in the register list. Issue unwinding instructions in
14190eae32dcSDimitry Andric   // three parts: ordinary hardware registers, return address authentication
14200eae32dcSDimitry Andric   // code pseudo register, the rest of the registers. The RA PAC is kept in an
14210eae32dcSDimitry Andric   // architectural register (usually r12), but we treat it as a special case in
14220eae32dcSDimitry Andric   // order to distinguish between that register containing RA PAC or a general
14230eae32dcSDimitry Andric   // value.
14240eae32dcSDimitry Andric   Idx = RegList.size();
14250eae32dcSDimitry Andric   while (Idx > 0) {
14260eae32dcSDimitry Andric     std::tie(Idx, Count) = collectHWRegs(MRI, Idx, RegList, IsVector, Mask);
14270eae32dcSDimitry Andric     if (Count) {
14280b57cec5SDimitry Andric       // Track the change the $sp offset: For the .save directive, the
14290b57cec5SDimitry Andric       // corresponding push instruction will decrease the $sp by (4 * Count).
14300b57cec5SDimitry Andric       // For the .vsave directive, the corresponding vpush instruction will
14310b57cec5SDimitry Andric       // decrease $sp by (8 * Count).
14320b57cec5SDimitry Andric       SPOffset -= Count * (IsVector ? 8 : 4);
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric       // Emit the opcode
14350b57cec5SDimitry Andric       FlushPendingOffset();
14360b57cec5SDimitry Andric       if (IsVector)
14370b57cec5SDimitry Andric         UnwindOpAsm.EmitVFPRegSave(Mask);
14380b57cec5SDimitry Andric       else
14390b57cec5SDimitry Andric         UnwindOpAsm.EmitRegSave(Mask);
14400eae32dcSDimitry Andric     } else if (Idx > 0 && RegList[Idx - 1] == ARM::RA_AUTH_CODE) {
14410eae32dcSDimitry Andric       --Idx;
14420eae32dcSDimitry Andric       SPOffset -= 4;
14430eae32dcSDimitry Andric       FlushPendingOffset();
14440eae32dcSDimitry Andric       UnwindOpAsm.EmitRegSave(0);
14450eae32dcSDimitry Andric     }
14460eae32dcSDimitry Andric   }
14470b57cec5SDimitry Andric }
14480b57cec5SDimitry Andric 
14490b57cec5SDimitry Andric void ARMELFStreamer::emitUnwindRaw(int64_t Offset,
14500b57cec5SDimitry Andric                                    const SmallVectorImpl<uint8_t> &Opcodes) {
14510b57cec5SDimitry Andric   FlushPendingOffset();
14520b57cec5SDimitry Andric   SPOffset = SPOffset - Offset;
14530b57cec5SDimitry Andric   UnwindOpAsm.EmitRaw(Opcodes);
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric namespace llvm {
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric MCTargetStreamer *createARMTargetAsmStreamer(MCStreamer &S,
14590b57cec5SDimitry Andric                                              formatted_raw_ostream &OS,
14600fca6ea1SDimitry Andric                                              MCInstPrinter *InstPrint) {
14610fca6ea1SDimitry Andric   return new ARMTargetAsmStreamer(S, OS, *InstPrint);
14620b57cec5SDimitry Andric }
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric MCTargetStreamer *createARMNullTargetStreamer(MCStreamer &S) {
14650b57cec5SDimitry Andric   return new ARMTargetStreamer(S);
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric 
146881ad6265SDimitry Andric MCTargetStreamer *createARMObjectTargetELFStreamer(MCStreamer &S) {
14690b57cec5SDimitry Andric   return new ARMTargetELFStreamer(S);
14700b57cec5SDimitry Andric }
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric MCELFStreamer *createARMELFStreamer(MCContext &Context,
14730b57cec5SDimitry Andric                                     std::unique_ptr<MCAsmBackend> TAB,
14740b57cec5SDimitry Andric                                     std::unique_ptr<MCObjectWriter> OW,
14750b57cec5SDimitry Andric                                     std::unique_ptr<MCCodeEmitter> Emitter,
14760fca6ea1SDimitry Andric                                     bool IsThumb, bool IsAndroid) {
1477480093f4SDimitry Andric   ARMELFStreamer *S =
1478480093f4SDimitry Andric       new ARMELFStreamer(Context, std::move(TAB), std::move(OW),
1479480093f4SDimitry Andric                          std::move(Emitter), IsThumb, IsAndroid);
14800b57cec5SDimitry Andric   // FIXME: This should eventually end up somewhere else where more
14810b57cec5SDimitry Andric   // intelligent flag decisions can be made. For now we are just maintaining
14820b57cec5SDimitry Andric   // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default.
14830fca6ea1SDimitry Andric   S->getWriter().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5);
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   return S;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric } // end namespace llvm
1489