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