1 //===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- 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 #include "AArch64.h" 11 #include "clang/Driver/Driver.h" 12 #include "clang/Driver/DriverDiagnostic.h" 13 #include "clang/Driver/Options.h" 14 #include "llvm/Option/ArgList.h" 15 #include "llvm/Support/TargetParser.h" 16 17 using namespace clang::driver; 18 using namespace clang::driver::tools; 19 using namespace clang; 20 using namespace llvm::opt; 21 22 /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are 23 /// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is 24 /// provided, or to nullptr otherwise. 25 std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) { 26 std::string CPU; 27 // If we have -mcpu, use that. 28 if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) { 29 StringRef Mcpu = A->getValue(); 30 CPU = Mcpu.split("+").first.lower(); 31 } 32 33 // Handle CPU name is 'native'. 34 if (CPU == "native") 35 return llvm::sys::getHostCPUName(); 36 else if (CPU.size()) 37 return CPU; 38 39 // Make sure we pick "cyclone" if -arch is used. 40 // FIXME: Should this be picked by checking the target triple instead? 41 if (Args.getLastArg(options::OPT_arch)) 42 return "cyclone"; 43 44 return "generic"; 45 } 46 47 // Decode AArch64 features from string like +[no]featureA+[no]featureB+... 48 static bool DecodeAArch64Features(const Driver &D, StringRef text, 49 std::vector<StringRef> &Features) { 50 SmallVector<StringRef, 8> Split; 51 text.split(Split, StringRef("+"), -1, false); 52 53 for (StringRef Feature : Split) { 54 StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature); 55 if (!FeatureName.empty()) 56 Features.push_back(FeatureName); 57 else if (Feature == "neon" || Feature == "noneon") 58 D.Diag(clang::diag::err_drv_no_neon_modifier); 59 else 60 return false; 61 } 62 return true; 63 } 64 65 // Check if the CPU name and feature modifiers in -mcpu are legal. If yes, 66 // decode CPU and feature. 67 static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, 68 std::vector<StringRef> &Features) { 69 std::pair<StringRef, StringRef> Split = Mcpu.split("+"); 70 CPU = Split.first; 71 72 if (CPU == "generic") { 73 Features.push_back("+neon"); 74 } else { 75 llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseCPUArch(CPU); 76 if (!llvm::AArch64::getArchFeatures(ArchKind, Features)) 77 return false; 78 79 unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind); 80 if (!llvm::AArch64::getExtensionFeatures(Extension, Features)) 81 return false; 82 } 83 84 if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) 85 return false; 86 87 return true; 88 } 89 90 static bool 91 getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, 92 const ArgList &Args, 93 std::vector<StringRef> &Features) { 94 std::string MarchLowerCase = March.lower(); 95 std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+"); 96 97 llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first); 98 if (ArchKind == llvm::AArch64::ArchKind::INVALID || 99 !llvm::AArch64::getArchFeatures(ArchKind, Features) || 100 (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))) 101 return false; 102 103 return true; 104 } 105 106 static bool 107 getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, 108 const ArgList &Args, 109 std::vector<StringRef> &Features) { 110 StringRef CPU; 111 std::string McpuLowerCase = Mcpu.lower(); 112 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features)) 113 return false; 114 115 return true; 116 } 117 118 static bool 119 getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune, 120 const ArgList &Args, 121 std::vector<StringRef> &Features) { 122 std::string MtuneLowerCase = Mtune.lower(); 123 // Check CPU name is valid 124 std::vector<StringRef> MtuneFeatures; 125 StringRef Tune; 126 if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures)) 127 return false; 128 129 // Handle CPU name is 'native'. 130 if (MtuneLowerCase == "native") 131 MtuneLowerCase = llvm::sys::getHostCPUName(); 132 if (MtuneLowerCase == "cyclone") { 133 Features.push_back("+zcm"); 134 Features.push_back("+zcz"); 135 } 136 return true; 137 } 138 139 static bool 140 getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, 141 const ArgList &Args, 142 std::vector<StringRef> &Features) { 143 StringRef CPU; 144 std::vector<StringRef> DecodedFeature; 145 std::string McpuLowerCase = Mcpu.lower(); 146 if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature)) 147 return false; 148 149 return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features); 150 } 151 152 void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, 153 std::vector<StringRef> &Features) { 154 Arg *A; 155 bool success = true; 156 // Enable NEON by default. 157 Features.push_back("+neon"); 158 if ((A = Args.getLastArg(options::OPT_march_EQ))) 159 success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); 160 else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) 161 success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); 162 else if (Args.hasArg(options::OPT_arch)) 163 success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A), 164 Args, Features); 165 166 if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))) 167 success = 168 getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features); 169 else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) 170 success = 171 getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); 172 else if (success && Args.hasArg(options::OPT_arch)) 173 success = getAArch64MicroArchFeaturesFromMcpu( 174 D, getAArch64TargetCPU(Args, A), Args, Features); 175 176 if (!success) 177 D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); 178 179 if (Args.getLastArg(options::OPT_mgeneral_regs_only)) { 180 Features.push_back("-fp-armv8"); 181 Features.push_back("-crypto"); 182 Features.push_back("-neon"); 183 } 184 185 // En/disable crc 186 if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { 187 if (A->getOption().matches(options::OPT_mcrc)) 188 Features.push_back("+crc"); 189 else 190 Features.push_back("-crc"); 191 } 192 193 if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, 194 options::OPT_munaligned_access)) 195 if (A->getOption().matches(options::OPT_mno_unaligned_access)) 196 Features.push_back("+strict-align"); 197 198 if (Args.hasArg(options::OPT_ffixed_x18)) 199 Features.push_back("+reserve-x18"); 200 201 if (Args.hasArg(options::OPT_mno_neg_immediates)) 202 Features.push_back("+no-neg-immediates"); 203 } 204