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
GetAEABIUnwindPersonalityName(unsigned Index)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
ARMTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter & InstPrinter)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
emitFnStart()1260b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; }
emitFnEnd()1270b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; }
emitCantUnwind()1280b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; }
1290b57cec5SDimitry Andric
emitPersonality(const MCSymbol * Personality)1300b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) {
1310b57cec5SDimitry Andric OS << "\t.personality " << Personality->getName() << '\n';
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
emitPersonalityIndex(unsigned Index)1340b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPersonalityIndex(unsigned Index) {
1350b57cec5SDimitry Andric OS << "\t.personalityindex " << Index << '\n';
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric
emitHandlerData()1380b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; }
1390b57cec5SDimitry Andric
emitSetFP(unsigned FpReg,unsigned SpReg,int64_t Offset)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
emitMovSP(unsigned Reg,int64_t Offset)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
emitPad(int64_t Offset)1620b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
1630b57cec5SDimitry Andric OS << "\t.pad\t#" << Offset << '\n';
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool isVector)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
switchVendor(StringRef Vendor)1840b57cec5SDimitry Andric void ARMTargetAsmStreamer::switchVendor(StringRef Vendor) {}
1850b57cec5SDimitry Andric
emitAttribute(unsigned Attribute,unsigned Value)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
emitTextAttribute(unsigned Attribute,StringRef String)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
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)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
emitArch(ARM::ArchKind Arch)2390b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitArch(ARM::ArchKind Arch) {
2400b57cec5SDimitry Andric OS << "\t.arch\t" << ARM::getArchName(Arch) << "\n";
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric
emitArchExtension(uint64_t ArchExt)2435ffd83dbSDimitry Andric void ARMTargetAsmStreamer::emitArchExtension(uint64_t ArchExt) {
2440b57cec5SDimitry Andric OS << "\t.arch_extension\t" << ARM::getArchExtName(ArchExt) << "\n";
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
emitObjectArch(ARM::ArchKind Arch)2470b57cec5SDimitry Andric void ARMTargetAsmStreamer::emitObjectArch(ARM::ArchKind Arch) {
2480b57cec5SDimitry Andric OS << "\t.object_arch\t" << ARM::getArchName(Arch) << '\n';
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
emitFPU(ARM::FPUKind FPU)25106c3fb27SDimitry Andric void ARMTargetAsmStreamer::emitFPU(ARM::FPUKind FPU) {
2520b57cec5SDimitry Andric OS << "\t.fpu\t" << ARM::getFPUName(FPU) << "\n";
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric
finishAttributeSection()2550b57cec5SDimitry Andric void ARMTargetAsmStreamer::finishAttributeSection() {}
2560b57cec5SDimitry Andric
annotateTLSDescriptorSequence(const MCSymbolRefExpr * S)25781ad6265SDimitry Andric void ARMTargetAsmStreamer::annotateTLSDescriptorSequence(
25881ad6265SDimitry Andric const MCSymbolRefExpr *S) {
2595ffd83dbSDimitry Andric OS << "\t.tlsdescseq\t" << S->getSymbol().getName() << "\n";
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric
emitThumbSet(MCSymbol * Symbol,const MCExpr * Value)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
emitInst(uint32_t Inst,char Suffix)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
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)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
emitARMWinCFIAllocStack(unsigned Size,bool Wide)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
printRegs(formatted_raw_ostream & OS,ListSeparator & LS,int First,int Last)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
emitARMWinCFISaveRegMask(unsigned Mask,bool Wide)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
emitARMWinCFISaveSP(unsigned Reg)32881ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveSP(unsigned Reg) {
32981ad6265SDimitry Andric OS << "\t.seh_save_sp\tr" << Reg << "\n";
33081ad6265SDimitry Andric }
33181ad6265SDimitry Andric
emitARMWinCFISaveFRegs(unsigned First,unsigned Last)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
emitARMWinCFISaveLR(unsigned Offset)34081ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFISaveLR(unsigned Offset) {
34181ad6265SDimitry Andric OS << "\t.seh_save_lr\t" << Offset << "\n";
34281ad6265SDimitry Andric }
34381ad6265SDimitry Andric
emitARMWinCFIPrologEnd(bool Fragment)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
emitARMWinCFINop(bool Wide)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
emitARMWinCFIEpilogStart(unsigned Condition)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
emitARMWinCFIEpilogEnd()36681ad6265SDimitry Andric void ARMTargetAsmStreamer::emitARMWinCFIEpilogEnd() {
36781ad6265SDimitry Andric OS << "\t.seh_endepilogue\n";
36881ad6265SDimitry Andric }
36981ad6265SDimitry Andric
emitARMWinCFICustom(unsigned Opcode)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:
ARMTargetELFStreamer(MCStreamer & S)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
ARMELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> TAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter,bool IsThumb,bool IsAndroid)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);
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)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
changeSection(MCSection * Section,uint32_t Subsection)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.
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)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
emitInst(uint32_t Inst,char Suffix)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.
emitBytes(StringRef Data)5485ffd83dbSDimitry Andric void emitBytes(StringRef Data) override {
5495ffd83dbSDimitry Andric emitDataMappingSymbol();
5505ffd83dbSDimitry Andric MCELFStreamer::emitBytes(Data);
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
FlushPendingMappingSymbol()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.
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)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
emitAssemblerFlag(MCAssemblerFlag Flag)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.
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)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 {
resetInfo__anonf150d5940111::ARMELFStreamer::ElfMappingSymbolInfo6270b57cec5SDimitry Andric void resetInfo() {
6280b57cec5SDimitry Andric F = nullptr;
6290b57cec5SDimitry Andric Offset = 0;
6300b57cec5SDimitry Andric }
hasInfo__anonf150d5940111::ARMELFStreamer::ElfMappingSymbolInfo6310b57cec5SDimitry 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
emitDataMappingSymbol()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
EmitThumbMappingSymbol()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
EmitARMMappingSymbol()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
EmitMappingSymbol(StringRef Name)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
emitMappingSymbol(StringRef Name,MCDataFragment & F,uint64_t Offset)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
emitThumbFunc(MCSymbol * Func)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
getStreamer()7340b57cec5SDimitry Andric ARMELFStreamer &ARMTargetELFStreamer::getStreamer() {
7350b57cec5SDimitry Andric return static_cast<ARMELFStreamer &>(Streamer);
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric
emitFnStart()7380b57cec5SDimitry Andric void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); }
emitFnEnd()7390b57cec5SDimitry Andric void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); }
emitCantUnwind()7400b57cec5SDimitry Andric void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); }
7410b57cec5SDimitry Andric
emitPersonality(const MCSymbol * Personality)7420b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) {
7430b57cec5SDimitry Andric getStreamer().emitPersonality(Personality);
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric
emitPersonalityIndex(unsigned Index)7460b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPersonalityIndex(unsigned Index) {
7470b57cec5SDimitry Andric getStreamer().emitPersonalityIndex(Index);
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric
emitHandlerData()7500b57cec5SDimitry Andric void ARMTargetELFStreamer::emitHandlerData() {
7510b57cec5SDimitry Andric getStreamer().emitHandlerData();
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric
emitSetFP(unsigned FpReg,unsigned SpReg,int64_t Offset)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
emitMovSP(unsigned Reg,int64_t Offset)7590b57cec5SDimitry Andric void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
7600b57cec5SDimitry Andric getStreamer().emitMovSP(Reg, Offset);
7610b57cec5SDimitry Andric }
7620b57cec5SDimitry Andric
emitPad(int64_t Offset)7630b57cec5SDimitry Andric void ARMTargetELFStreamer::emitPad(int64_t Offset) {
7640b57cec5SDimitry Andric getStreamer().emitPad(Offset);
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool isVector)7670b57cec5SDimitry Andric void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
7680b57cec5SDimitry Andric bool isVector) {
7690b57cec5SDimitry Andric getStreamer().emitRegSave(RegList, isVector);
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)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
switchVendor(StringRef Vendor)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
emitAttribute(unsigned Attribute,unsigned Value)7920b57cec5SDimitry Andric void ARMTargetELFStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
793fe6060f1SDimitry Andric getStreamer().setAttributeItem(Attribute, Value,
794fe6060f1SDimitry Andric /* OverwriteExisting= */ true);
7950b57cec5SDimitry Andric }
7960b57cec5SDimitry Andric
emitTextAttribute(unsigned Attribute,StringRef Value)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
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)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
emitArch(ARM::ArchKind Value)8100b57cec5SDimitry Andric void ARMTargetELFStreamer::emitArch(ARM::ArchKind Value) {
8110b57cec5SDimitry Andric Arch = Value;
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric
emitObjectArch(ARM::ArchKind Value)8140b57cec5SDimitry Andric void ARMTargetELFStreamer::emitObjectArch(ARM::ArchKind Value) {
8150b57cec5SDimitry Andric EmittedArch = Value;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric
emitArchDefaultAttributes()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
emitFPU(ARM::FPUKind Value)92406c3fb27SDimitry Andric void ARMTargetELFStreamer::emitFPU(ARM::FPUKind Value) { FPU = Value; }
9250b57cec5SDimitry Andric
emitFPUDefaultAttributes()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
finishAttributeSection()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
emitLabel(MCSymbol * Symbol)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
annotateTLSDescriptorSequence(const MCSymbolRefExpr * S)108881ad6265SDimitry Andric void ARMTargetELFStreamer::annotateTLSDescriptorSequence(
108981ad6265SDimitry Andric const MCSymbolRefExpr *S) {
10900b57cec5SDimitry Andric getStreamer().EmitFixup(S, FK_Data_4);
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric
emitThumbSet(MCSymbol * Symbol,const MCExpr * Value)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
emitInst(uint32_t Inst,char Suffix)11060b57cec5SDimitry Andric void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
11070b57cec5SDimitry Andric getStreamer().emitInst(Inst, Suffix);
11080b57cec5SDimitry Andric }
11090b57cec5SDimitry Andric
reset()11100b57cec5SDimitry Andric void ARMTargetELFStreamer::reset() { AttributeSection = nullptr; }
11110b57cec5SDimitry Andric
finish()11120fca6ea1SDimitry Andric void ARMTargetELFStreamer::finish() {
11130fca6ea1SDimitry Andric ARMTargetStreamer::finish();
11140fca6ea1SDimitry Andric finishAttributeSection();
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric
reset()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
SwitchToEHSection(StringRef Prefix,unsigned Type,unsigned Flags,SectionKind Kind,const MCSymbol & Fn)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
SwitchToExTabSection(const MCSymbol & FnStart)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
SwitchToExIdxSection(const MCSymbol & FnStart)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
EmitFixup(const MCExpr * Expr,MCFixupKind Kind)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
EHReset()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
emitFnStart()11940b57cec5SDimitry Andric void ARMELFStreamer::emitFnStart() {
11950b57cec5SDimitry Andric assert(FnStart == nullptr);
11960b57cec5SDimitry Andric FnStart = getContext().createTempSymbol();
11975ffd83dbSDimitry Andric emitLabel(FnStart);
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric
emitFnEnd()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
emitCantUnwind()12560b57cec5SDimitry Andric void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; }
12570b57cec5SDimitry Andric
12580b57cec5SDimitry Andric // Add the R_ARM_NONE fixup at the same position
EmitPersonalityFixup(StringRef Name)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
FlushPendingOffset()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
FlushUnwindOpcodes(bool NoHandlerData)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
emitHandlerData()13390b57cec5SDimitry Andric void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); }
13400b57cec5SDimitry Andric
emitPersonality(const MCSymbol * Per)13410b57cec5SDimitry Andric void ARMELFStreamer::emitPersonality(const MCSymbol *Per) {
13420b57cec5SDimitry Andric Personality = Per;
13430b57cec5SDimitry Andric UnwindOpAsm.setPersonality(Per);
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric
emitPersonalityIndex(unsigned Index)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
emitSetFP(unsigned NewFPReg,unsigned NewSPReg,int64_t Offset)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
emitMovSP(unsigned Reg,int64_t Offset)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
emitPad(int64_t Offset)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>
collectHWRegs(const MCRegisterInfo & MRI,unsigned Idx,const SmallVectorImpl<unsigned> & RegList,bool IsVector,uint32_t & Mask_)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
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool IsVector)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
emitUnwindRaw(int64_t Offset,const SmallVectorImpl<uint8_t> & Opcodes)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
createARMTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter * InstPrint)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
createARMNullTargetStreamer(MCStreamer & S)14640b57cec5SDimitry Andric MCTargetStreamer *createARMNullTargetStreamer(MCStreamer &S) {
14650b57cec5SDimitry Andric return new ARMTargetStreamer(S);
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric
createARMObjectTargetELFStreamer(MCStreamer & S)146881ad6265SDimitry Andric MCTargetStreamer *createARMObjectTargetELFStreamer(MCStreamer &S) {
14690b57cec5SDimitry Andric return new ARMTargetELFStreamer(S);
14700b57cec5SDimitry Andric }
14710b57cec5SDimitry Andric
createARMELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> TAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter,bool IsThumb,bool IsAndroid)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