Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -574,23 +574,47 @@ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } +// Decode ARM features from string like +[no]featureA+[no]featureB+... +static bool DecodeARMFeatures(const Driver &D, StringRef text, + std::vector &Features) { + SmallVector Split; + text.split(Split, StringRef("+"), -1, false); + + for (StringRef Feature : Split) { + const char *FeatureName = llvm::ARM::getArchExtFeature(Feature); + if (FeatureName) + Features.push_back(FeatureName); + else + return false; + } + return true; +} + // Check if -march is valid by checking if it can be canonicalised and parsed. // getARMArch is used here instead of just checking the -march value in order // to handle -march=native correctly. static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, llvm::StringRef ArchName, + std::vector &Features, const llvm::Triple &Triple) { + std::pair Split = ArchName.split("+"); + std::string MArch = arm::getARMArch(ArchName, Triple); - if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID) + if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID || + (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Check -mcpu=. Needs ArchName to handle -mcpu=generic. static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, llvm::StringRef CPUName, llvm::StringRef ArchName, + std::vector &Features, const llvm::Triple &Triple) { + std::pair Split = CPUName.split("+"); + std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); - if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty()) + if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() || + (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } @@ -756,12 +780,12 @@ D.Diag(clang::diag::warn_drv_unused_argument) << ArchArg->getAsString(Args); ArchName = StringRef(WaArch->getValue()).substr(7); - checkARMArchName(D, WaArch, Args, ArchName, Triple); + checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); // FIXME: Set Arch. D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); } else if (ArchArg) { ArchName = ArchArg->getValue(); - checkARMArchName(D, ArchArg, Args, ArchName, Triple); + checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); } // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. @@ -772,10 +796,10 @@ D.Diag(clang::diag::warn_drv_unused_argument) << CPUArg->getAsString(Args); CPUName = StringRef(WaCPU->getValue()).substr(6); - checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Triple); + checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); } else if (CPUArg) { CPUName = CPUArg->getValue(); - checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Triple); + checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); } // Add CPU features for generic CPUs @@ -6241,7 +6265,7 @@ MArch = Arch; else MArch = Triple.getArchName(); - MArch = StringRef(MArch).lower(); + MArch = StringRef(MArch).split("+").first.lower(); // Handle -march=native. if (MArch == "native") { @@ -6280,7 +6304,7 @@ // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (!CPU.empty()) { - std::string MCPU = StringRef(CPU).lower(); + std::string MCPU = StringRef(CPU).split("+").first.lower(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); Index: test/Driver/arm-features.c =================================================================== --- /dev/null +++ test/Driver/arm-features.c @@ -0,0 +1,7 @@ +// RUN: %clang -target arm -mcpu=generic+crc -march=armv8a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRC %s +// RUN: %clang -target arm -mcpu=generic -march=armv8a+crc -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CRC %s +// CHECK-CRC: "-cc1"{{.*}} "-triple" "armv8-{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "+crc" + +// RUN: %clang -target arm -mcpu=generic+nocrc -march=armv8a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRC %s +// RUN: %clang -target arm -mcpu=generic -march=armv8a+nocrc -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-NOCRC %s +// CHECK-NOCRC: "-cc1"{{.*}} "-triple" "armv8-{{.*}} "-target-cpu" "generic"{{.*}} "-target-feature" "-crc"