1 //===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the ARMTargetStreamer class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/ARMMCTargetDesc.h" 14 #include "llvm/MC/ConstantPools.h" 15 #include "llvm/MC/MCAsmInfo.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCExpr.h" 18 #include "llvm/MC/MCStreamer.h" 19 #include "llvm/MC/MCSubtargetInfo.h" 20 #include "llvm/Support/ARMBuildAttributes.h" 21 22 using namespace llvm; 23 24 // 25 // ARMTargetStreamer Implemenation 26 // 27 28 ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S) 29 : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {} 30 31 ARMTargetStreamer::~ARMTargetStreamer() = default; 32 33 // The constant pool handling is shared by all ARMTargetStreamer 34 // implementations. 35 const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc) { 36 return ConstantPools->addEntry(Streamer, Expr, 4, Loc); 37 } 38 39 void ARMTargetStreamer::emitCurrentConstantPool() { 40 ConstantPools->emitForCurrentSection(Streamer); 41 ConstantPools->clearCacheForCurrentSection(Streamer); 42 } 43 44 // finish() - write out any non-empty assembler constant pools. 45 void ARMTargetStreamer::emitConstantPools() { 46 ConstantPools->emitAll(Streamer); 47 } 48 49 // reset() - Reset any state 50 void ARMTargetStreamer::reset() {} 51 52 void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) { 53 unsigned Size; 54 char Buffer[4]; 55 const bool LittleEndian = getContext().getAsmInfo()->isLittleEndian(); 56 57 switch (Suffix) { 58 case '\0': 59 Size = 4; 60 61 for (unsigned II = 0, IE = Size; II != IE; II++) { 62 const unsigned I = LittleEndian ? (Size - II - 1) : II; 63 Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT); 64 } 65 66 break; 67 case 'n': 68 case 'w': 69 Size = (Suffix == 'n' ? 2 : 4); 70 71 // Thumb wide instructions are emitted as a pair of 16-bit words of the 72 // appropriate endianness. 73 for (unsigned II = 0, IE = Size; II != IE; II = II + 2) { 74 const unsigned I0 = LittleEndian ? II + 0 : II + 1; 75 const unsigned I1 = LittleEndian ? II + 1 : II + 0; 76 Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT); 77 Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT); 78 } 79 80 break; 81 default: 82 llvm_unreachable("Invalid Suffix"); 83 } 84 getStreamer().emitBytes(StringRef(Buffer, Size)); 85 } 86 87 // The remaining callbacks should be handled separately by each 88 // streamer. 89 void ARMTargetStreamer::emitFnStart() {} 90 void ARMTargetStreamer::emitFnEnd() {} 91 void ARMTargetStreamer::emitCantUnwind() {} 92 void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {} 93 void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {} 94 void ARMTargetStreamer::emitHandlerData() {} 95 void ARMTargetStreamer::emitSetFP(MCRegister FpReg, MCRegister SpReg, 96 int64_t Offset) {} 97 void ARMTargetStreamer::emitMovSP(MCRegister Reg, int64_t Offset) {} 98 void ARMTargetStreamer::emitPad(int64_t Offset) {} 99 void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<MCRegister> &RegList, 100 bool isVector) {} 101 void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset, 102 const SmallVectorImpl<uint8_t> &Opcodes) { 103 } 104 void ARMTargetStreamer::switchVendor(StringRef Vendor) {} 105 void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} 106 void ARMTargetStreamer::emitTextAttribute(unsigned Attribute, 107 StringRef String) {} 108 void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute, 109 unsigned IntValue, 110 StringRef StringValue) {} 111 void ARMTargetStreamer::emitArch(ARM::ArchKind Arch) {} 112 void ARMTargetStreamer::emitArchExtension(uint64_t ArchExt) {} 113 void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {} 114 void ARMTargetStreamer::emitFPU(ARM::FPUKind FPU) {} 115 void ARMTargetStreamer::finishAttributeSection() {} 116 void ARMTargetStreamer::annotateTLSDescriptorSequence( 117 const MCSymbolRefExpr *SRE) {} 118 void ARMTargetStreamer::emitSyntaxUnified() {} 119 void ARMTargetStreamer::emitCode16() {} 120 void ARMTargetStreamer::emitCode32() {} 121 void ARMTargetStreamer::emitThumbFunc(MCSymbol *Symbol) {} 122 void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {} 123 124 void ARMTargetStreamer::emitARMWinCFIAllocStack(unsigned Size, bool Wide) {} 125 void ARMTargetStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) {} 126 void ARMTargetStreamer::emitARMWinCFISaveSP(unsigned Reg) {} 127 void ARMTargetStreamer::emitARMWinCFISaveFRegs(unsigned First, unsigned Last) {} 128 void ARMTargetStreamer::emitARMWinCFISaveLR(unsigned Offset) {} 129 void ARMTargetStreamer::emitARMWinCFINop(bool Wide) {} 130 void ARMTargetStreamer::emitARMWinCFIPrologEnd(bool Fragment) {} 131 void ARMTargetStreamer::emitARMWinCFIEpilogStart(unsigned Condition) {} 132 void ARMTargetStreamer::emitARMWinCFIEpilogEnd() {} 133 void ARMTargetStreamer::emitARMWinCFICustom(unsigned Opcode) {} 134 135 static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) { 136 if (STI.getCPU() == "xscale") 137 return ARMBuildAttrs::v5TEJ; 138 139 if (STI.hasFeature(ARM::HasV9_0aOps)) 140 return ARMBuildAttrs::v9_A; 141 else if (STI.hasFeature(ARM::HasV8Ops)) { 142 if (STI.hasFeature(ARM::FeatureRClass)) 143 return ARMBuildAttrs::v8_R; 144 return ARMBuildAttrs::v8_A; 145 } else if (STI.hasFeature(ARM::HasV8_1MMainlineOps)) 146 return ARMBuildAttrs::v8_1_M_Main; 147 else if (STI.hasFeature(ARM::HasV8MMainlineOps)) 148 return ARMBuildAttrs::v8_M_Main; 149 else if (STI.hasFeature(ARM::HasV7Ops)) { 150 if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP)) 151 return ARMBuildAttrs::v7E_M; 152 return ARMBuildAttrs::v7; 153 } else if (STI.hasFeature(ARM::HasV6T2Ops)) 154 return ARMBuildAttrs::v6T2; 155 else if (STI.hasFeature(ARM::HasV8MBaselineOps)) 156 return ARMBuildAttrs::v8_M_Base; 157 else if (STI.hasFeature(ARM::HasV6MOps)) 158 return ARMBuildAttrs::v6S_M; 159 else if (STI.hasFeature(ARM::HasV6Ops)) 160 return ARMBuildAttrs::v6; 161 else if (STI.hasFeature(ARM::HasV5TEOps)) 162 return ARMBuildAttrs::v5TE; 163 else if (STI.hasFeature(ARM::HasV5TOps)) 164 return ARMBuildAttrs::v5T; 165 else if (STI.hasFeature(ARM::HasV4TOps)) 166 return ARMBuildAttrs::v4T; 167 else 168 return ARMBuildAttrs::v4; 169 } 170 171 static bool isV8M(const MCSubtargetInfo &STI) { 172 // Note that v8M Baseline is a subset of v6T2! 173 return (STI.hasFeature(ARM::HasV8MBaselineOps) && 174 !STI.hasFeature(ARM::HasV6T2Ops)) || 175 STI.hasFeature(ARM::HasV8MMainlineOps); 176 } 177 178 /// Emit the build attributes that only depend on the hardware that we expect 179 // /to be available, and not on the ABI, or any source-language choices. 180 void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { 181 switchVendor("aeabi"); 182 183 const StringRef CPUString = STI.getCPU(); 184 if (!CPUString.empty() && !CPUString.starts_with("generic")) { 185 // FIXME: remove krait check when GNU tools support krait cpu 186 if (STI.hasFeature(ARM::ProcKrait)) { 187 emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9"); 188 // We consider krait as a "cortex-a9" + hwdiv CPU 189 // Enable hwdiv through ".arch_extension idiv" 190 if (STI.hasFeature(ARM::FeatureHWDivThumb) || 191 STI.hasFeature(ARM::FeatureHWDivARM)) 192 emitArchExtension(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM); 193 } else { 194 emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); 195 } 196 } 197 198 emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI)); 199 200 if (STI.hasFeature(ARM::FeatureAClass)) { 201 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 202 ARMBuildAttrs::ApplicationProfile); 203 } else if (STI.hasFeature(ARM::FeatureRClass)) { 204 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 205 ARMBuildAttrs::RealTimeProfile); 206 } else if (STI.hasFeature(ARM::FeatureMClass)) { 207 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 208 ARMBuildAttrs::MicroControllerProfile); 209 } 210 211 emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM) 212 ? ARMBuildAttrs::Not_Allowed 213 : ARMBuildAttrs::Allowed); 214 215 if (isV8M(STI)) { 216 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 217 ARMBuildAttrs::AllowThumbDerived); 218 } else if (STI.hasFeature(ARM::FeatureThumb2)) { 219 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 220 ARMBuildAttrs::AllowThumb32); 221 } else if (STI.hasFeature(ARM::HasV4TOps)) { 222 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed); 223 } 224 225 if (STI.hasFeature(ARM::FeatureNEON)) { 226 /* NEON is not exactly a VFP architecture, but GAS emit one of 227 * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ 228 if (STI.hasFeature(ARM::FeatureFPARMv8)) { 229 if (STI.hasFeature(ARM::FeatureCrypto)) 230 emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8); 231 else 232 emitFPU(ARM::FK_NEON_FP_ARMV8); 233 } else if (STI.hasFeature(ARM::FeatureVFP4)) 234 emitFPU(ARM::FK_NEON_VFPV4); 235 else 236 emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16 237 : ARM::FK_NEON); 238 // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture 239 if (STI.hasFeature(ARM::HasV8Ops)) 240 emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 241 STI.hasFeature(ARM::HasV8_1aOps) 242 ? ARMBuildAttrs::AllowNeonARMv8_1a 243 : ARMBuildAttrs::AllowNeonARMv8); 244 } else { 245 if (STI.hasFeature(ARM::FeatureFPARMv8_D16_SP)) { 246 // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one 247 // FPU, but there are two different names for it depending on the CPU. 248 if (STI.hasFeature(ARM::FeatureD32)) 249 emitFPU(ARM::FK_FP_ARMV8); 250 else { 251 emitFPU(STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_FPV5_D16 252 : ARM::FK_FPV5_SP_D16); 253 if (STI.hasFeature(ARM::HasMVEFloatOps)) 254 emitArchExtension(ARM::AEK_MVE | ARM::AEK_DSP | ARM::AEK_FP); 255 } 256 } else if (STI.hasFeature(ARM::FeatureVFP4_D16_SP)) 257 emitFPU(STI.hasFeature(ARM::FeatureD32) 258 ? ARM::FK_VFPV4 259 : (STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_VFPV4_D16 260 : ARM::FK_FPV4_SP_D16)); 261 else if (STI.hasFeature(ARM::FeatureVFP3_D16_SP)) 262 emitFPU( 263 STI.hasFeature(ARM::FeatureD32) 264 // +d32 265 ? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16 266 : ARM::FK_VFPV3) 267 // -d32 268 : (STI.hasFeature(ARM::FeatureFP64) 269 ? (STI.hasFeature(ARM::FeatureFP16) 270 ? ARM::FK_VFPV3_D16_FP16 271 : ARM::FK_VFPV3_D16) 272 : (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16 273 : ARM::FK_VFPV3XD))); 274 else if (STI.hasFeature(ARM::FeatureVFP2_SP)) 275 emitFPU(ARM::FK_VFPV2); 276 } 277 278 // ABI_HardFP_use attribute to indicate single precision FP. 279 if (STI.hasFeature(ARM::FeatureVFP2_SP) && !STI.hasFeature(ARM::FeatureFP64)) 280 emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 281 ARMBuildAttrs::HardFPSinglePrecision); 282 283 if (STI.hasFeature(ARM::FeatureFP16)) 284 emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP); 285 286 if (STI.hasFeature(ARM::FeatureMP)) 287 emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP); 288 289 if (STI.hasFeature(ARM::HasMVEFloatOps)) 290 emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEIntegerAndFloat); 291 else if (STI.hasFeature(ARM::HasMVEIntegerOps)) 292 emitAttribute(ARMBuildAttrs::MVE_arch, ARMBuildAttrs::AllowMVEInteger); 293 294 // Hardware divide in ARM mode is part of base arch, starting from ARMv8. 295 // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M). 296 // It is not possible to produce DisallowDIV: if hwdiv is present in the base 297 // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits. 298 // AllowDIVExt is only emitted if hwdiv isn't available in the base arch; 299 // otherwise, the default value (AllowDIVIfExists) applies. 300 if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops)) 301 emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt); 302 303 if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI)) 304 emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed); 305 306 if (STI.hasFeature(ARM::FeatureStrictAlign)) 307 emitAttribute(ARMBuildAttrs::CPU_unaligned_access, 308 ARMBuildAttrs::Not_Allowed); 309 else 310 emitAttribute(ARMBuildAttrs::CPU_unaligned_access, 311 ARMBuildAttrs::Allowed); 312 313 if (STI.hasFeature(ARM::FeatureTrustZone) && 314 STI.hasFeature(ARM::FeatureVirtualization)) 315 emitAttribute(ARMBuildAttrs::Virtualization_use, 316 ARMBuildAttrs::AllowTZVirtualization); 317 else if (STI.hasFeature(ARM::FeatureTrustZone)) 318 emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ); 319 else if (STI.hasFeature(ARM::FeatureVirtualization)) 320 emitAttribute(ARMBuildAttrs::Virtualization_use, 321 ARMBuildAttrs::AllowVirtualization); 322 323 if (STI.hasFeature(ARM::FeaturePACBTI)) { 324 emitAttribute(ARMBuildAttrs::PAC_extension, ARMBuildAttrs::AllowPAC); 325 emitAttribute(ARMBuildAttrs::BTI_extension, ARMBuildAttrs::AllowBTI); 326 } 327 } 328 329 MCTargetStreamer * 330 llvm::createARMObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { 331 const Triple &TT = STI.getTargetTriple(); 332 if (TT.isOSBinFormatELF()) 333 return createARMObjectTargetELFStreamer(S); 334 if (TT.isOSBinFormatCOFF()) 335 return createARMObjectTargetWinCOFFStreamer(S); 336 if (TT.isOSBinFormatMachO()) 337 return createARMObjectTargetMachOStreamer(S); 338 return new ARMTargetStreamer(S); 339 } 340