1 //===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the ARMTargetStreamer class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMTargetMachine.h" 15 #include "llvm/MC/ConstantPools.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCStreamer.h" 18 #include "llvm/MC/MCSubtargetInfo.h" 19 #include "llvm/Support/ARMBuildAttributes.h" 20 #include "llvm/Support/TargetParser.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 } 42 43 // finish() - write out any non-empty assembler constant pools. 44 void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); } 45 46 // reset() - Reset any state 47 void ARMTargetStreamer::reset() {} 48 49 // The remaining callbacks should be handled separately by each 50 // streamer. 51 void ARMTargetStreamer::emitFnStart() {} 52 void ARMTargetStreamer::emitFnEnd() {} 53 void ARMTargetStreamer::emitCantUnwind() {} 54 void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {} 55 void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {} 56 void ARMTargetStreamer::emitHandlerData() {} 57 void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, 58 int64_t Offset) {} 59 void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {} 60 void ARMTargetStreamer::emitPad(int64_t Offset) {} 61 void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, 62 bool isVector) {} 63 void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset, 64 const SmallVectorImpl<uint8_t> &Opcodes) { 65 } 66 void ARMTargetStreamer::switchVendor(StringRef Vendor) {} 67 void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} 68 void ARMTargetStreamer::emitTextAttribute(unsigned Attribute, 69 StringRef String) {} 70 void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute, 71 unsigned IntValue, 72 StringRef StringValue) {} 73 void ARMTargetStreamer::emitArch(unsigned Arch) {} 74 void ARMTargetStreamer::emitArchExtension(unsigned ArchExt) {} 75 void ARMTargetStreamer::emitObjectArch(unsigned Arch) {} 76 void ARMTargetStreamer::emitFPU(unsigned FPU) {} 77 void ARMTargetStreamer::finishAttributeSection() {} 78 void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {} 79 void 80 ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {} 81 void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {} 82 83 static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI) { 84 if (STI.getCPU() == "xscale") 85 return ARMBuildAttrs::v5TEJ; 86 87 if (STI.hasFeature(ARM::HasV8Ops)) { 88 if (STI.hasFeature(ARM::FeatureRClass)) 89 return ARMBuildAttrs::v8_R; 90 return ARMBuildAttrs::v8_A; 91 } else if (STI.hasFeature(ARM::HasV8MMainlineOps)) 92 return ARMBuildAttrs::v8_M_Main; 93 else if (STI.hasFeature(ARM::HasV7Ops)) { 94 if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP)) 95 return ARMBuildAttrs::v7E_M; 96 return ARMBuildAttrs::v7; 97 } else if (STI.hasFeature(ARM::HasV6T2Ops)) 98 return ARMBuildAttrs::v6T2; 99 else if (STI.hasFeature(ARM::HasV8MBaselineOps)) 100 return ARMBuildAttrs::v8_M_Base; 101 else if (STI.hasFeature(ARM::HasV6MOps)) 102 return ARMBuildAttrs::v6S_M; 103 else if (STI.hasFeature(ARM::HasV6Ops)) 104 return ARMBuildAttrs::v6; 105 else if (STI.hasFeature(ARM::HasV5TEOps)) 106 return ARMBuildAttrs::v5TE; 107 else if (STI.hasFeature(ARM::HasV5TOps)) 108 return ARMBuildAttrs::v5T; 109 else if (STI.hasFeature(ARM::HasV4TOps)) 110 return ARMBuildAttrs::v4T; 111 else 112 return ARMBuildAttrs::v4; 113 } 114 115 static bool isV8M(const MCSubtargetInfo &STI) { 116 // Note that v8M Baseline is a subset of v6T2! 117 return (STI.hasFeature(ARM::HasV8MBaselineOps) && 118 !STI.hasFeature(ARM::HasV6T2Ops)) || 119 STI.hasFeature(ARM::HasV8MMainlineOps); 120 } 121 122 /// Emit the build attributes that only depend on the hardware that we expect 123 // /to be available, and not on the ABI, or any source-language choices. 124 void ARMTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { 125 switchVendor("aeabi"); 126 127 const StringRef CPUString = STI.getCPU(); 128 if (!CPUString.empty() && !CPUString.startswith("generic")) { 129 // FIXME: remove krait check when GNU tools support krait cpu 130 if (STI.hasFeature(ARM::ProcKrait)) { 131 emitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a9"); 132 // We consider krait as a "cortex-a9" + hwdiv CPU 133 // Enable hwdiv through ".arch_extension idiv" 134 if (STI.hasFeature(ARM::FeatureHWDivThumb) || 135 STI.hasFeature(ARM::FeatureHWDivARM)) 136 emitArchExtension(ARM::AEK_HWDIVTHUMB | ARM::AEK_HWDIVARM); 137 } else { 138 emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString); 139 } 140 } 141 142 emitAttribute(ARMBuildAttrs::CPU_arch, getArchForCPU(STI)); 143 144 if (STI.hasFeature(ARM::FeatureAClass)) { 145 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 146 ARMBuildAttrs::ApplicationProfile); 147 } else if (STI.hasFeature(ARM::FeatureRClass)) { 148 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 149 ARMBuildAttrs::RealTimeProfile); 150 } else if (STI.hasFeature(ARM::FeatureMClass)) { 151 emitAttribute(ARMBuildAttrs::CPU_arch_profile, 152 ARMBuildAttrs::MicroControllerProfile); 153 } 154 155 emitAttribute(ARMBuildAttrs::ARM_ISA_use, STI.hasFeature(ARM::FeatureNoARM) 156 ? ARMBuildAttrs::Not_Allowed 157 : ARMBuildAttrs::Allowed); 158 159 if (isV8M(STI)) { 160 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 161 ARMBuildAttrs::AllowThumbDerived); 162 } else if (STI.hasFeature(ARM::FeatureThumb2)) { 163 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, 164 ARMBuildAttrs::AllowThumb32); 165 } else if (STI.hasFeature(ARM::HasV4TOps)) { 166 emitAttribute(ARMBuildAttrs::THUMB_ISA_use, ARMBuildAttrs::Allowed); 167 } 168 169 if (STI.hasFeature(ARM::FeatureNEON)) { 170 /* NEON is not exactly a VFP architecture, but GAS emit one of 171 * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */ 172 if (STI.hasFeature(ARM::FeatureFPARMv8)) { 173 if (STI.hasFeature(ARM::FeatureCrypto)) 174 emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8); 175 else 176 emitFPU(ARM::FK_NEON_FP_ARMV8); 177 } else if (STI.hasFeature(ARM::FeatureVFP4)) 178 emitFPU(ARM::FK_NEON_VFPV4); 179 else 180 emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16 181 : ARM::FK_NEON); 182 // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture 183 if (STI.hasFeature(ARM::HasV8Ops)) 184 emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, 185 STI.hasFeature(ARM::HasV8_1aOps) 186 ? ARMBuildAttrs::AllowNeonARMv8_1a 187 : ARMBuildAttrs::AllowNeonARMv8); 188 } else { 189 if (STI.hasFeature(ARM::FeatureFPARMv8)) 190 // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one 191 // FPU, but there are two different names for it depending on the CPU. 192 emitFPU(STI.hasFeature(ARM::FeatureD16) 193 ? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV5_SP_D16 194 : ARM::FK_FPV5_D16) 195 : ARM::FK_FP_ARMV8); 196 else if (STI.hasFeature(ARM::FeatureVFP4)) 197 emitFPU(STI.hasFeature(ARM::FeatureD16) 198 ? (STI.hasFeature(ARM::FeatureVFPOnlySP) ? ARM::FK_FPV4_SP_D16 199 : ARM::FK_VFPV4_D16) 200 : ARM::FK_VFPV4); 201 else if (STI.hasFeature(ARM::FeatureVFP3)) 202 emitFPU( 203 STI.hasFeature(ARM::FeatureD16) 204 // +d16 205 ? (STI.hasFeature(ARM::FeatureVFPOnlySP) 206 ? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16 207 : ARM::FK_VFPV3XD) 208 : (STI.hasFeature(ARM::FeatureFP16) 209 ? ARM::FK_VFPV3_D16_FP16 210 : ARM::FK_VFPV3_D16)) 211 // -d16 212 : (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16 213 : ARM::FK_VFPV3)); 214 else if (STI.hasFeature(ARM::FeatureVFP2)) 215 emitFPU(ARM::FK_VFPV2); 216 } 217 218 // ABI_HardFP_use attribute to indicate single precision FP. 219 if (STI.hasFeature(ARM::FeatureVFPOnlySP)) 220 emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 221 ARMBuildAttrs::HardFPSinglePrecision); 222 223 if (STI.hasFeature(ARM::FeatureFP16)) 224 emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP); 225 226 if (STI.hasFeature(ARM::FeatureMP)) 227 emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP); 228 229 // Hardware divide in ARM mode is part of base arch, starting from ARMv8. 230 // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M). 231 // It is not possible to produce DisallowDIV: if hwdiv is present in the base 232 // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits. 233 // AllowDIVExt is only emitted if hwdiv isn't available in the base arch; 234 // otherwise, the default value (AllowDIVIfExists) applies. 235 if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops)) 236 emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt); 237 238 if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI)) 239 emitAttribute(ARMBuildAttrs::DSP_extension, ARMBuildAttrs::Allowed); 240 241 if (STI.hasFeature(ARM::FeatureStrictAlign)) 242 emitAttribute(ARMBuildAttrs::CPU_unaligned_access, 243 ARMBuildAttrs::Not_Allowed); 244 else 245 emitAttribute(ARMBuildAttrs::CPU_unaligned_access, 246 ARMBuildAttrs::Allowed); 247 248 if (STI.hasFeature(ARM::FeatureTrustZone) && 249 STI.hasFeature(ARM::FeatureVirtualization)) 250 emitAttribute(ARMBuildAttrs::Virtualization_use, 251 ARMBuildAttrs::AllowTZVirtualization); 252 else if (STI.hasFeature(ARM::FeatureTrustZone)) 253 emitAttribute(ARMBuildAttrs::Virtualization_use, ARMBuildAttrs::AllowTZ); 254 else if (STI.hasFeature(ARM::FeatureVirtualization)) 255 emitAttribute(ARMBuildAttrs::Virtualization_use, 256 ARMBuildAttrs::AllowVirtualization); 257 } 258