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<const char *> &Features) {
+ SmallVector<StringRef, 8> 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<const char *> &Features,
const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> 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<const char *> &Features,
const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> 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);
}
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=.
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
MArch = Arch;
else
MArch = Triple.getArchName();
- MArch = StringRef(MArch).lower();
+ MArch = StringRef(MArch).split("+").first.lower();
// Handle -march=native.
if (MArch == "native") {
// 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();