diff options
author | Renato Golin <renato.golin@linaro.org> | 2015-07-30 09:57:20 +0000 |
---|---|---|
committer | Renato Golin <renato.golin@linaro.org> | 2015-07-30 09:57:20 +0000 |
commit | 510a6b1563a731618960cf29c751e3d66040af77 (patch) | |
tree | 6edd3991059a34c7ec3befca94a174bea52e0f1a | |
parent | 907f5e5a319aaba3e36e7634220e87059a7f56bf (diff) |
Merging r243352, r243353:
[ARM] Changes to Arch/CPU handling to help with -Wa,-mfpu etc. (nfc)
[ARM] Implement -Wa,-mfpu and friends for assemblers
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_37@243629 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Driver/ToolChain.cpp | 11 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 231 | ||||
-rw-r--r-- | lib/Driver/Tools.h | 6 | ||||
-rw-r--r-- | test/Driver/arm-ias-Wa.s | 64 |
4 files changed, 237 insertions, 75 deletions
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index e6a1bc9685..d40bb951e5 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -305,12 +305,17 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, // Thumb2 is the default for V7 on Darwin. // // FIXME: Thumb should just be another -target-feaure, not in the triple. + StringRef MCPU, MArch; + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + MCPU = A->getValue(); + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + MArch = A->getValue(); std::string CPU = Triple.isOSBinFormatMachO() - ? tools::arm::getARMCPUForMArch(Args, Triple) - : tools::arm::getARMTargetCPU(Args, Triple); + ? tools::arm::getARMCPUForMArch(MArch, Triple) + : tools::arm::getARMTargetCPU(MCPU, MArch, Triple); StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, - tools::arm::getARMArch(Args, Triple)); + tools::arm::getARMArch(MArch, Triple)); bool ThumbDefault = Suffix.startswith("v6m") || Suffix.startswith("v7m") || Suffix.startswith("v7em") || (Suffix.startswith("v7") && getTriple().isOSBinFormatMachO()); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 0871ce446e..d46f4672bf 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -502,11 +502,46 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { } } +// ARM tools start. + +// Get SubArch (vN). +static int getARMSubArchVersionNumber(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + return llvm::ARMTargetParser::parseArchVersion(Arch); +} + +// True if M-profile. +static bool isARMMProfile(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + unsigned Profile = llvm::ARMTargetParser::parseArchProfile(Arch); + return Profile == llvm::ARM::PK_M; +} + +// Get Arch/CPU from args. +static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, + llvm::StringRef &CPU, bool FromAs = false) { + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + CPU = A->getValue(); + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + Arch = A->getValue(); + if (!FromAs) + return; + + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { + StringRef Value = A->getValue(); + if (Value.startswith("-mcpu=")) + CPU = Value.substr(6); + if (Value.startswith("-march=")) + Arch = Value.substr(7); + } +} + // Handle -mhwdiv=. +// FIXME: Use ARMTargetParser. static void getARMHWDivFeatures(const Driver &D, const Arg *A, - const ArgList &Args, + const ArgList &Args, StringRef HWDiv, std::vector<const char *> &Features) { - StringRef HWDiv = A->getValue(); if (HWDiv == "arm") { Features.push_back("+hwdiv-arm"); Features.push_back("-hwdiv"); @@ -525,23 +560,32 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A, // Handle -mfpu=. static void getARMFPUFeatures(const Driver &D, const Arg *A, - const ArgList &Args, + const ArgList &Args, StringRef FPU, std::vector<const char *> &Features) { - StringRef FPU = A->getValue(); unsigned FPUID = llvm::ARMTargetParser::parseFPU(FPU); if (!llvm::ARMTargetParser::getFPUFeatures(FPUID, Features)) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } -static int getARMSubArchVersionNumber(const llvm::Triple &Triple) { - llvm::StringRef Arch = Triple.getArchName(); - return llvm::ARMTargetParser::parseArchVersion(Arch); +// 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, + const llvm::Triple &Triple) { + std::string MArch = arm::getARMArch(ArchName, Triple); + if (llvm::ARMTargetParser::parseArch(MArch) == llvm::ARM::AK_INVALID) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } -static bool isARMMProfile(const llvm::Triple &Triple) { - llvm::StringRef Arch = Triple.getArchName(); - unsigned Profile = llvm::ARMTargetParser::parseArchProfile(Arch); - return Profile == llvm::ARM::PK_M; +// 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, + const llvm::Triple &Triple) { + std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); + std::string Arch = arm::getARMArch(ArchName, Triple); + if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } // Select the float ABI as determined by -msoft-float, -mhard-float, and @@ -641,6 +685,9 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple); + const Arg *WaCPU = nullptr, *WaFPU = nullptr; + const Arg *WaHDiv = nullptr, *WaArch = nullptr; + if (!ForAS) { // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these // yet (it uses the -mfloat-abi and -msoft-float options), and it is @@ -661,31 +708,75 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, // Use software floating point argument passing? if (FloatABI != "hard") Features.push_back("+soft-float-abi"); + } else { + // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down + // to the assembler correctly. + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { + StringRef Value = A->getValue(); + if (Value.startswith("-mfpu=")) { + WaFPU = A; + } else if (Value.startswith("-mcpu=")) { + WaCPU = A; + } else if (Value.startswith("-mhwdiv=")) { + WaHDiv = A; + } else if (Value.startswith("-march=")) { + WaArch = A; + } + } } - // Honor -mfpu=. - if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) - getARMFPUFeatures(D, A, Args, Features); - if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ)) - getARMHWDivFeatures(D, A, Args, Features); - - // 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. - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - std::string Arch = arm::getARMArch(Args, Triple); - if (llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_INVALID) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); - } - - // We do a similar thing with -mcpu, but here things are complicated because - // the only function we have to check if a cpu is valid is - // getLLVMArchSuffixForARM which also needs an architecture. - if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - std::string CPU = arm::getARMTargetCPU(Args, Triple); - std::string Arch = arm::getARMArch(Args, Triple); - if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. + const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); + if (WaFPU) { + if (FPUArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << FPUArg->getAsString(Args); + getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), + Features); + } else if (FPUArg) { + getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); + } + + // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. + const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); + if (WaHDiv) { + if (HDivArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << HDivArg->getAsString(Args); + getARMHWDivFeatures(D, WaHDiv, Args, + StringRef(WaHDiv->getValue()).substr(8), Features); + } else if (HDivArg) + getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); + + // Check -march. ClangAs gives preference to -Wa,-march=. + const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); + StringRef ArchName; + if (WaArch) { + if (ArchArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << ArchArg->getAsString(Args); + ArchName = StringRef(WaArch->getValue()).substr(7); + checkARMArchName(D, WaArch, Args, ArchName, 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); + } + + // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. + const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); + StringRef CPUName; + if (WaCPU) { + if (CPUArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << CPUArg->getAsString(Args); + CPUName = StringRef(WaCPU->getValue()).substr(6); + checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Triple); + } else if (CPUArg) { + CPUName = CPUArg->getValue(); + checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Triple); } // Setting -msoft-float effectively disables NEON because of the GCC @@ -836,6 +927,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs, CmdArgs.push_back("-arm-reserve-r9"); } } +// ARM tools end. /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are /// targeting. @@ -1463,7 +1555,8 @@ static const char *getX86TargetCPU(const ArgList &Args, } } -static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { +static std::string getCPUName(const ArgList &Args, const llvm::Triple &T, + bool FromAs = false) { switch (T.getArch()) { default: return ""; @@ -1475,9 +1568,11 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - return arm::getARMTargetCPU(Args, T); - + case llvm::Triple::thumbeb: { + StringRef MArch, MCPU; + getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); + return arm::getARMTargetCPU(MCPU, MArch, T); + } case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -2198,12 +2293,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { A->claim(); - for (const StringRef Value : A->getValues()) { - if (TakeNextArg) { - CmdArgs.push_back(Value.data()); - TakeNextArg = false; - continue; - } + for (const StringRef Value : A->getValues()) { + if (TakeNextArg) { + CmdArgs.push_back(Value.data()); + TakeNextArg = false; + continue; + } if (Value == "-force_cpusubtype_ALL") { // Do nothing, this is the default and we don't support anything else. @@ -2227,6 +2322,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, TakeNextArg = true; } else if (Value.startswith("-gdwarf-")) { CmdArgs.push_back(Value.data()); + } else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") || + Value.startswith("-mhwdiv") || Value.startswith("-march")) { + // Do nothing, we'll validate it later. } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -2751,8 +2849,7 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, if (ProfileGenerateArg && ProfileUseArg) D.Diag(diag::err_drv_argument_not_allowed_with) - << ProfileGenerateArg->getSpelling() - << ProfileUseArg->getSpelling(); + << ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling(); if (ProfileGenerateArg && ProfileGenerateArg->getOption().matches( @@ -2908,8 +3005,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && "Invalid action for clang tool."); - if (JA.getType() == types::TY_LTO_IR || - JA.getType() == types::TY_LTO_BC) { + if (JA.getType() == types::TY_LTO_IR || JA.getType() == types::TY_LTO_BC) { CmdArgs.push_back("-flto"); } if (JA.getType() == types::TY_Nothing) { @@ -3435,7 +3531,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Add the target cpu - std::string CPU = getCPUName(Args, Triple); + std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(CPU)); @@ -4235,8 +4331,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::append(Path, "modules"); } else if (Path.empty()) { // No module path was provided: use the default. - llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, - Path); + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Path); llvm::sys::path::append(Path, "org.llvm.clang."); appendUserToPath(Path); llvm::sys::path::append(Path, "ModuleCache"); @@ -5271,7 +5366,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Add the target cpu const llvm::Triple Triple(TripleStr); - std::string CPU = getCPUName(Args, Triple); + std::string CPU = getCPUName(Args, Triple, /*FromAs*/ true); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(CPU)); @@ -5776,16 +5871,12 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, } // Hexagon tools end. -const std::string arm::getARMArch(const ArgList &Args, - const llvm::Triple &Triple) { +const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { std::string MArch; - if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - // Otherwise, if we have -march= choose the base CPU for that arch. - MArch = A->getValue(); - } else { - // Otherwise, use the Arch from the triple. + if (!Arch.empty()) + MArch = Arch; + else MArch = Triple.getArchName(); - } MArch = StringRef(MArch).lower(); // Handle -march=native. @@ -5806,9 +5897,8 @@ const std::string arm::getARMArch(const ArgList &Args, return MArch; } /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. -const char *arm::getARMCPUForMArch(const ArgList &Args, - const llvm::Triple &Triple) { - std::string MArch = getARMArch(Args, Triple); +const char *arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) { + std::string MArch = getARMArch(Arch, Triple); // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch // here means an -march=native that we can't handle, so instead return no CPU. if (MArch.empty()) @@ -5824,12 +5914,12 @@ const char *arm::getARMCPUForMArch(const ArgList &Args, } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. -std::string arm::getARMTargetCPU(const ArgList &Args, +std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, const llvm::Triple &Triple) { // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - std::string MCPU = StringRef(A->getValue()).lower(); + if (!CPU.empty()) { + std::string MCPU = StringRef(CPU).lower(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); @@ -5837,7 +5927,7 @@ std::string arm::getARMTargetCPU(const ArgList &Args, return MCPU; } - return getARMCPUForMArch(Args, Triple); + return getARMCPUForMArch(Arch, Triple); } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular @@ -7336,8 +7426,11 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: { - std::string MArch = arm::getARMTargetCPU(Args, getToolChain().getTriple()); - CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch)); + StringRef MArch, MCPU; + getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true); + std::string Arch = + arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple()); + CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch)); break; } diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 52ab731cbc..651ddc8ff5 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -231,11 +231,11 @@ public: } // end namespace hexagon. namespace arm { - std::string getARMTargetCPU(const llvm::opt::ArgList &Args, + std::string getARMTargetCPU(StringRef CPU, StringRef Arch, const llvm::Triple &Triple); - const std::string getARMArch(const llvm::opt::ArgList &Args, + const std::string getARMArch(StringRef Arch, const llvm::Triple &Triple); - const char* getARMCPUForMArch(const llvm::opt::ArgList &Args, + const char* getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple); const char* getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch); diff --git a/test/Driver/arm-ias-Wa.s b/test/Driver/arm-ias-Wa.s new file mode 100644 index 0000000000..6eadd3b841 --- /dev/null +++ b/test/Driver/arm-ias-Wa.s @@ -0,0 +1,64 @@ +// Test that different values of -Wa,-mcpu/mfpu/march/mhwdiv pick correct ARM target-feature(s). +// Complete tests about -mcpu/mfpu/march/mhwdiv on other files. + +// CHECK-DUP-CPU: warning: argument unused during compilation: '-mcpu=cortex-a8' +// CHECK-DUP-FPU: warning: argument unused during compilation: '-mfpu=vfpv3' +// CHECK-DUP-ARCH: warning: argument unused during compilation: '-march=armv7' +// CHECK-DUP-HDIV: warning: argument unused during compilation: '-mhwdiv=arm' + +// CHECK: "cc1as" +// ================================================================= CPU +// RUN: %clang -target arm-linux-gnueabi -Wa,-mcpu=cortex-a15 -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-CPU %s +// CHECK-CPU: "-target-cpu" "cortex-a15" + +// RUN: %clang -target arm -Wa,-mcpu=bogus -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-BOGUS-CPU %s +// CHECK-BOGUS-CPU: error: {{.*}} does not support '-Wa,-mcpu=bogus' + +// RUN: %clang -target arm -mcpu=cortex-a8 -Wa,-mcpu=cortex-a15 -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-DUP-CPU %s +// CHECK-DUP-CPU: "-target-cpu" "cortex-a15" + +// ================================================================= FPU +// RUN: %clang -target arm-linux-eabi -Wa,-mfpu=neon -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NEON %s +// CHECK-NEON: "-target-feature" "+neon" + +// RUN: %clang -target arm-linux-eabi -Wa,-mfpu=bogus -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-BOGUS-FPU %s +// CHECK-BOGUS-FPU: error: {{.*}} does not support '-Wa,-mfpu=bogus' + +// RUN: %clang -target arm-linux-eabi -mfpu=vfpv3 -Wa,-mfpu=neon -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-DUP-FPU %s +// CHECK-DUP-FPU: "-target-feature" "+neon" + +// ================================================================= Arch +// Arch validation only for now, in case we're passing to an external asm + +// RUN: %clang -target arm -Wa,-march=armbogusv6 -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-BOGUS-ARCH %s +// CHECK-BOGUS-ARCH: error: {{.*}} does not support '-Wa,-march=armbogusv6' + +// RUN: %clang -target arm -march=armv7 -Wa,-march=armv6 -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-DUP-ARCH %s + +// ================================================================= HD Div +// RUN: %clang -target arm -Wa,-mhwdiv=arm -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ARM %s +// CHECK-ARM: "-target-feature" "+hwdiv-arm" +// CHECK-ARM: "-target-feature" "-hwdiv" + +// RUN: %clang -target arm -Wa,-mhwdiv=thumb -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-THUMB %s +// CHECK-THUMB: "-target-feature" "-hwdiv-arm" +// CHECK-THUMB: "-target-feature" "+hwdiv" + +// RUN: %clang -target arm -Wa,-mhwdiv=bogus -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-BOGUS-HDIV %s +// CHECK-BOGUS-HDIV: error: {{.*}} does not support '-Wa,-mhwdiv=bogus' + +// RUN: %clang -target arm -mhwdiv=arm -Wa,-mhwdiv=thumb -c %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-DUP-HDIV %s +// CHECK-DUP-HDIV: "-target-feature" "-hwdiv-arm" +// CHECK-DUP-HDIV: "-target-feature" "+hwdiv" |