xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//
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 implements the ARMTargetStreamer class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCTargetDesc.h"
140b57cec5SDimitry Andric #include "llvm/MC/ConstantPools.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric //
250b57cec5SDimitry Andric // ARMTargetStreamer Implemenation
260b57cec5SDimitry Andric //
270b57cec5SDimitry Andric 
ARMTargetStreamer(MCStreamer & S)280b57cec5SDimitry Andric ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)
290b57cec5SDimitry Andric     : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric ARMTargetStreamer::~ARMTargetStreamer() = default;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric // The constant pool handling is shared by all ARMTargetStreamer
340b57cec5SDimitry Andric // implementations.
addConstantPoolEntry(const MCExpr * Expr,SMLoc Loc)350b57cec5SDimitry Andric const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc) {
360b57cec5SDimitry Andric   return ConstantPools->addEntry(Streamer, Expr, 4, Loc);
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
emitCurrentConstantPool()390b57cec5SDimitry Andric void ARMTargetStreamer::emitCurrentConstantPool() {
400b57cec5SDimitry Andric   ConstantPools->emitForCurrentSection(Streamer);
410b57cec5SDimitry Andric   ConstantPools->clearCacheForCurrentSection(Streamer);
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric // finish() - write out any non-empty assembler constant pools.
emitConstantPools()45349cc55cSDimitry Andric void ARMTargetStreamer::emitConstantPools() {
46349cc55cSDimitry Andric   ConstantPools->emitAll(Streamer);
47349cc55cSDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric // reset() - Reset any state
reset()500b57cec5SDimitry Andric void ARMTargetStreamer::reset() {}
510b57cec5SDimitry Andric 
emitInst(uint32_t Inst,char Suffix)520b57cec5SDimitry Andric void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
530b57cec5SDimitry Andric   unsigned Size;
540b57cec5SDimitry Andric   char Buffer[4];
550b57cec5SDimitry Andric   const bool LittleEndian = getStreamer().getContext().getAsmInfo()->isLittleEndian();
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   switch (Suffix) {
580b57cec5SDimitry Andric   case '\0':
590b57cec5SDimitry Andric     Size = 4;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric     for (unsigned II = 0, IE = Size; II != IE; II++) {
620b57cec5SDimitry Andric       const unsigned I = LittleEndian ? (Size - II - 1) : II;
630b57cec5SDimitry Andric       Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
640b57cec5SDimitry Andric     }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     break;
670b57cec5SDimitry Andric   case 'n':
680b57cec5SDimitry Andric   case 'w':
690b57cec5SDimitry Andric     Size = (Suffix == 'n' ? 2 : 4);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric     // Thumb wide instructions are emitted as a pair of 16-bit words of the
720b57cec5SDimitry Andric     // appropriate endianness.
730b57cec5SDimitry Andric     for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
740b57cec5SDimitry Andric       const unsigned I0 = LittleEndian ? II + 0 : II + 1;
750b57cec5SDimitry Andric       const unsigned I1 = LittleEndian ? II + 1 : II + 0;
760b57cec5SDimitry Andric       Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
770b57cec5SDimitry Andric       Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
780b57cec5SDimitry Andric     }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric     break;
810b57cec5SDimitry Andric   default:
820b57cec5SDimitry Andric     llvm_unreachable("Invalid Suffix");
830b57cec5SDimitry Andric   }
845ffd83dbSDimitry Andric   getStreamer().emitBytes(StringRef(Buffer, Size));
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric // The remaining callbacks should be handled separately by each
880b57cec5SDimitry Andric // streamer.
emitFnStart()890b57cec5SDimitry Andric void ARMTargetStreamer::emitFnStart() {}
emitFnEnd()900b57cec5SDimitry Andric void ARMTargetStreamer::emitFnEnd() {}
emitCantUnwind()910b57cec5SDimitry Andric void ARMTargetStreamer::emitCantUnwind() {}
emitPersonality(const MCSymbol * Personality)920b57cec5SDimitry Andric void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {}
emitPersonalityIndex(unsigned Index)930b57cec5SDimitry Andric void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {}
emitHandlerData()940b57cec5SDimitry Andric void ARMTargetStreamer::emitHandlerData() {}
emitSetFP(unsigned FpReg,unsigned SpReg,int64_t Offset)950b57cec5SDimitry Andric void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
960b57cec5SDimitry Andric                                   int64_t Offset) {}
emitMovSP(unsigned Reg,int64_t Offset)970b57cec5SDimitry Andric void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {}
emitPad(int64_t Offset)980b57cec5SDimitry Andric void ARMTargetStreamer::emitPad(int64_t Offset) {}
emitRegSave(const SmallVectorImpl<unsigned> & RegList,bool isVector)990b57cec5SDimitry Andric void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
1000b57cec5SDimitry Andric                                     bool isVector) {}
emitUnwindRaw(int64_t StackOffset,const SmallVectorImpl<uint8_t> & Opcodes)1010b57cec5SDimitry Andric void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset,
1020b57cec5SDimitry Andric                                       const SmallVectorImpl<uint8_t> &Opcodes) {
1030b57cec5SDimitry Andric }
switchVendor(StringRef Vendor)1040b57cec5SDimitry Andric void ARMTargetStreamer::switchVendor(StringRef Vendor) {}
emitAttribute(unsigned Attribute,unsigned Value)1050b57cec5SDimitry Andric void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
emitTextAttribute(unsigned Attribute,StringRef String)1060b57cec5SDimitry Andric void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,
1070b57cec5SDimitry Andric                                           StringRef String) {}
emitIntTextAttribute(unsigned Attribute,unsigned IntValue,StringRef StringValue)1080b57cec5SDimitry Andric void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,
1090b57cec5SDimitry Andric                                              unsigned IntValue,
1100b57cec5SDimitry Andric                                              StringRef StringValue) {}
emitArch(ARM::ArchKind Arch)1110b57cec5SDimitry Andric void ARMTargetStreamer::emitArch(ARM::ArchKind Arch) {}
emitArchExtension(uint64_t ArchExt)1125ffd83dbSDimitry Andric void ARMTargetStreamer::emitArchExtension(uint64_t ArchExt) {}
emitObjectArch(ARM::ArchKind Arch)1130b57cec5SDimitry Andric void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {}
emitFPU(ARM::FPUKind FPU)11406c3fb27SDimitry Andric void ARMTargetStreamer::emitFPU(ARM::FPUKind FPU) {}
finishAttributeSection()1150b57cec5SDimitry Andric void ARMTargetStreamer::finishAttributeSection() {}
annotateTLSDescriptorSequence(const MCSymbolRefExpr * SRE)11681ad6265SDimitry Andric void ARMTargetStreamer::annotateTLSDescriptorSequence(
11781ad6265SDimitry Andric     const MCSymbolRefExpr *SRE) {}
emitThumbSet(MCSymbol * Symbol,const MCExpr * Value)1180b57cec5SDimitry Andric void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {}
1190b57cec5SDimitry Andric 
emitARMWinCFIAllocStack(unsigned Size,bool Wide)12081ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFIAllocStack(unsigned Size, bool Wide) {}
emitARMWinCFISaveRegMask(unsigned Mask,bool Wide)12181ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) {}
emitARMWinCFISaveSP(unsigned Reg)12281ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFISaveSP(unsigned Reg) {}
emitARMWinCFISaveFRegs(unsigned First,unsigned Last)12381ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFISaveFRegs(unsigned First, unsigned Last) {}
emitARMWinCFISaveLR(unsigned Offset)12481ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFISaveLR(unsigned Offset) {}
emitARMWinCFINop(bool Wide)12581ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFINop(bool Wide) {}
emitARMWinCFIPrologEnd(bool Fragment)12681ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFIPrologEnd(bool Fragment) {}
emitARMWinCFIEpilogStart(unsigned Condition)12781ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFIEpilogStart(unsigned Condition) {}
emitARMWinCFIEpilogEnd()12881ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFIEpilogEnd() {}
emitARMWinCFICustom(unsigned Opcode)12981ad6265SDimitry Andric void ARMTargetStreamer::emitARMWinCFICustom(unsigned Opcode) {}
13081ad6265SDimitry Andric 
getArchForCPU(const MCSubtargetInfo & STI)1310b57cec5SDimitry Andric static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) {
1320b57cec5SDimitry Andric   if (STI.getCPU() == "xscale")
1330b57cec5SDimitry Andric     return ARMBuildAttrs::v5TEJ;
1340b57cec5SDimitry Andric 
13581ad6265SDimitry Andric   if (STI.hasFeature(ARM::HasV9_0aOps))
13681ad6265SDimitry Andric     return ARMBuildAttrs::v9_A;
13781ad6265SDimitry Andric   else if (STI.hasFeature(ARM::HasV8Ops)) {
1380b57cec5SDimitry Andric     if (STI.hasFeature(ARM::FeatureRClass))
1390b57cec5SDimitry Andric       return ARMBuildAttrs::v8_R;
1400b57cec5SDimitry Andric     return ARMBuildAttrs::v8_A;
1410b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::HasV8_1MMainlineOps))
1420b57cec5SDimitry Andric     return ARMBuildAttrs::v8_1_M_Main;
1430b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV8MMainlineOps))
1440b57cec5SDimitry Andric     return ARMBuildAttrs::v8_M_Main;
1450b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV7Ops)) {
1460b57cec5SDimitry Andric     if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP))
1470b57cec5SDimitry Andric       return ARMBuildAttrs::v7E_M;
1480b57cec5SDimitry Andric     return ARMBuildAttrs::v7;
1490b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::HasV6T2Ops))
1500b57cec5SDimitry Andric     return ARMBuildAttrs::v6T2;
1510b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV8MBaselineOps))
1520b57cec5SDimitry Andric     return ARMBuildAttrs::v8_M_Base;
1530b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV6MOps))
1540b57cec5SDimitry Andric     return ARMBuildAttrs::v6S_M;
1550b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV6Ops))
1560b57cec5SDimitry Andric     return ARMBuildAttrs::v6;
1570b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV5TEOps))
1580b57cec5SDimitry Andric     return ARMBuildAttrs::v5TE;
1590b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV5TOps))
1600b57cec5SDimitry Andric     return ARMBuildAttrs::v5T;
1610b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasV4TOps))
1620b57cec5SDimitry Andric     return ARMBuildAttrs::v4T;
1630b57cec5SDimitry Andric   else
1640b57cec5SDimitry Andric     return ARMBuildAttrs::v4;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
isV8M(const MCSubtargetInfo & STI)1670b57cec5SDimitry Andric static bool isV8M(const MCSubtargetInfo &STI) {
1680b57cec5SDimitry Andric   // Note that v8M Baseline is a subset of v6T2!
1690b57cec5SDimitry Andric   return (STI.hasFeature(ARM::HasV8MBaselineOps) &&
1700b57cec5SDimitry Andric           !STI.hasFeature(ARM::HasV6T2Ops)) ||
1710b57cec5SDimitry Andric          STI.hasFeature(ARM::HasV8MMainlineOps);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric /// Emit the build attributes that only depend on the hardware that we expect
1750b57cec5SDimitry Andric // /to be available, and not on the ABI, or any source-language choices.
emitTargetAttributes(const MCSubtargetInfo & STI)1760b57cec5SDimitry Andric void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {
1770b57cec5SDimitry Andric   switchVendor("aeabi");
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   const StringRef CPUString = STI.getCPU();
180*5f757f3fSDimitry Andric   if (!CPUString.empty() && !CPUString.starts_with("generic")) {
1810b57cec5SDimitry Andric     // FIXME: remove krait check when GNU tools support krait cpu
1820b57cec5SDimitry Andric     if (STI.hasFeature(ARM::ProcKrait)) {
1830b57cec5SDimitry Andric       emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9");
1840b57cec5SDimitry Andric       // We consider krait as a "cortex-a9" + hwdiv CPU
1850b57cec5SDimitry Andric       // Enable hwdiv through ".arch_extension idiv"
1860b57cec5SDimitry Andric       if (STI.hasFeature(ARM::FeatureHWDivThumb) ||
1870b57cec5SDimitry Andric           STI.hasFeature(ARM::FeatureHWDivARM))
1880b57cec5SDimitry Andric         emitArchExtension(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM);
1890b57cec5SDimitry Andric     } else {
1900b57cec5SDimitry Andric       emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
1910b57cec5SDimitry Andric     }
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI));
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureAClass)) {
1970b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::CPU_arch_profile,
1980b57cec5SDimitry Andric                       ARMBuildAttrs::ApplicationProfile);
1990b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::FeatureRClass)) {
2000b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::CPU_arch_profile,
2010b57cec5SDimitry Andric                       ARMBuildAttrs::RealTimeProfile);
2020b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::FeatureMClass)) {
2030b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::CPU_arch_profile,
2040b57cec5SDimitry Andric                       ARMBuildAttrs::MicroControllerProfile);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM)
2080b57cec5SDimitry Andric                                                 ? ARMBuildAttrs::Not_Allowed
2090b57cec5SDimitry Andric                                                 : ARMBuildAttrs::Allowed);
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   if (isV8M(STI)) {
2120b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
2130b57cec5SDimitry Andric                       ARMBuildAttrs::AllowThumbDerived);
2140b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::FeatureThumb2)) {
2150b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
2160b57cec5SDimitry Andric                       ARMBuildAttrs::AllowThumb32);
2170b57cec5SDimitry Andric   } else if (STI.hasFeature(ARM::HasV4TOps)) {
2180b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed);
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureNEON)) {
2220b57cec5SDimitry Andric     /* NEON is not exactly a VFP architecture, but GAS emit one of
2230b57cec5SDimitry Andric      * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
2240b57cec5SDimitry Andric     if (STI.hasFeature(ARM::FeatureFPARMv8)) {
2250b57cec5SDimitry Andric       if (STI.hasFeature(ARM::FeatureCrypto))
2260b57cec5SDimitry Andric         emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);
2270b57cec5SDimitry Andric       else
2280b57cec5SDimitry Andric         emitFPU(ARM::FK_NEON_FP_ARMV8);
2290b57cec5SDimitry Andric     } else if (STI.hasFeature(ARM::FeatureVFP4))
2300b57cec5SDimitry Andric       emitFPU(ARM::FK_NEON_VFPV4);
2310b57cec5SDimitry Andric     else
2320b57cec5SDimitry Andric       emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16
2330b57cec5SDimitry Andric                                                : ARM::FK_NEON);
2340b57cec5SDimitry Andric     // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
2350b57cec5SDimitry Andric     if (STI.hasFeature(ARM::HasV8Ops))
2360b57cec5SDimitry Andric       emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
2370b57cec5SDimitry Andric                     STI.hasFeature(ARM::HasV8_1aOps)
2380b57cec5SDimitry Andric                         ? ARMBuildAttrs::AllowNeonARMv8_1a
2390b57cec5SDimitry Andric                         : ARMBuildAttrs::AllowNeonARMv8);
2400b57cec5SDimitry Andric   } else {
241*5f757f3fSDimitry Andric     if (STI.hasFeature(ARM::FeatureFPARMv8_D16_SP)) {
2420b57cec5SDimitry Andric       // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
2430b57cec5SDimitry Andric       // FPU, but there are two different names for it depending on the CPU.
244*5f757f3fSDimitry Andric       if (STI.hasFeature(ARM::FeatureD32))
245*5f757f3fSDimitry Andric         emitFPU(ARM::FK_FP_ARMV8);
246*5f757f3fSDimitry Andric       else {
247*5f757f3fSDimitry Andric         emitFPU(STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_FPV5_D16
248*5f757f3fSDimitry Andric                                                  : ARM::FK_FPV5_SP_D16);
249*5f757f3fSDimitry Andric         if (STI.hasFeature(ARM::HasMVEFloatOps))
250*5f757f3fSDimitry Andric           emitArchExtension(ARM::AEK_SIMD | ARM::AEK_DSP | ARM::AEK_FP);
251*5f757f3fSDimitry Andric       }
252*5f757f3fSDimitry Andric     } else if (STI.hasFeature(ARM::FeatureVFP4_D16_SP))
2530b57cec5SDimitry Andric       emitFPU(STI.hasFeature(ARM::FeatureD32)
2540b57cec5SDimitry Andric                   ? ARM::FK_VFPV4
2550b57cec5SDimitry Andric                   : (STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_VFPV4_D16
2560b57cec5SDimitry Andric                                                       : ARM::FK_FPV4_SP_D16));
2570b57cec5SDimitry Andric     else if (STI.hasFeature(ARM::FeatureVFP3_D16_SP))
2580b57cec5SDimitry Andric       emitFPU(
2590b57cec5SDimitry Andric           STI.hasFeature(ARM::FeatureD32)
2600b57cec5SDimitry Andric               // +d32
2610b57cec5SDimitry Andric               ? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16
2620b57cec5SDimitry Andric                                                   : ARM::FK_VFPV3)
2630b57cec5SDimitry Andric               // -d32
2640b57cec5SDimitry Andric               : (STI.hasFeature(ARM::FeatureFP64)
2650b57cec5SDimitry Andric                      ? (STI.hasFeature(ARM::FeatureFP16)
2660b57cec5SDimitry Andric                             ? ARM::FK_VFPV3_D16_FP16
2670b57cec5SDimitry Andric                             : ARM::FK_VFPV3_D16)
2680b57cec5SDimitry Andric                      : (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16
2690b57cec5SDimitry Andric                                                          : ARM::FK_VFPV3XD)));
2708bcb0991SDimitry Andric     else if (STI.hasFeature(ARM::FeatureVFP2_SP))
2710b57cec5SDimitry Andric       emitFPU(ARM::FK_VFPV2);
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   // ABI_HardFP_use attribute to indicate single precision FP.
2758bcb0991SDimitry Andric   if (STI.hasFeature(ARM::FeatureVFP2_SP) && !STI.hasFeature(ARM::FeatureFP64))
2760b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
2770b57cec5SDimitry Andric                   ARMBuildAttrs::HardFPSinglePrecision);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureFP16))
2800b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureMP))
2830b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   if (STI.hasFeature(ARM::HasMVEFloatOps))
2860b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEIntegerAndFloat);
2870b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::HasMVEIntegerOps))
2880b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEInteger);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   // Hardware divide in ARM mode is part of base arch, starting from ARMv8.
2910b57cec5SDimitry Andric   // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
2920b57cec5SDimitry Andric   // It is not possible to produce DisallowDIV: if hwdiv is present in the base
2930b57cec5SDimitry Andric   // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
2940b57cec5SDimitry Andric   // AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
2950b57cec5SDimitry Andric   // otherwise, the default value (AllowDIVIfExists) applies.
2960b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops))
2970b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI))
3000b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed);
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureStrictAlign))
3030b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
3040b57cec5SDimitry Andric                   ARMBuildAttrs::Not_Allowed);
3050b57cec5SDimitry Andric   else
3060b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
3070b57cec5SDimitry Andric                   ARMBuildAttrs::Allowed);
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   if (STI.hasFeature(ARM::FeatureTrustZone) &&
3100b57cec5SDimitry Andric       STI.hasFeature(ARM::FeatureVirtualization))
3110b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::Virtualization_use,
3120b57cec5SDimitry Andric                   ARMBuildAttrs::AllowTZVirtualization);
3130b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::FeatureTrustZone))
3140b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ);
3150b57cec5SDimitry Andric   else if (STI.hasFeature(ARM::FeatureVirtualization))
3160b57cec5SDimitry Andric     emitAttribute(ARMBuildAttrs::Virtualization_use,
3170b57cec5SDimitry Andric                   ARMBuildAttrs::AllowVirtualization);
3184824e7fdSDimitry Andric 
3194824e7fdSDimitry Andric   if (STI.hasFeature(ARM::FeaturePACBTI)) {
3204824e7fdSDimitry Andric     emitAttribute(ARMBuildAttrs::PAC_extension, ARMBuildAttrs::AllowPAC);
3214824e7fdSDimitry Andric     emitAttribute(ARMBuildAttrs::BTI_extension, ARMBuildAttrs::AllowBTI);
3224824e7fdSDimitry Andric   }
3230b57cec5SDimitry Andric }
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric MCTargetStreamer *
createARMObjectTargetStreamer(MCStreamer & S,const MCSubtargetInfo & STI)32681ad6265SDimitry Andric llvm::createARMObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
32781ad6265SDimitry Andric   const Triple &TT = STI.getTargetTriple();
32881ad6265SDimitry Andric   if (TT.isOSBinFormatELF())
32981ad6265SDimitry Andric     return createARMObjectTargetELFStreamer(S);
33081ad6265SDimitry Andric   if (TT.isOSBinFormatCOFF())
33181ad6265SDimitry Andric     return createARMObjectTargetWinCOFFStreamer(S);
33281ad6265SDimitry Andric   return new ARMTargetStreamer(S);
33381ad6265SDimitry Andric }
334