From 576452b83025362d8020be8f38599ef828e205af Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 10 Feb 2012 20:37:10 +0000 Subject: [PATCH] Have the driver pass CPU and target feature information to cc1as. When creating the MCSubtargetInfo, the assembler driver uses the CPU and feature string to construct a more accurate model of what instructions are and are not legal. rdar://10840476 llvm-svn: 150273 --- clang/include/clang/Driver/CC1AsOptions.td | 4 ++ clang/lib/Driver/Tools.cpp | 61 ++++++++++++++++++++++ clang/lib/Driver/Tools.h | 1 + clang/test/lit.cfg | 2 +- clang/tools/driver/cc1as_main.cpp | 29 ++++++++-- 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Driver/CC1AsOptions.td b/clang/include/clang/Driver/CC1AsOptions.td index ac4d65c6625f..37ba6027e207 100644 --- a/clang/include/clang/Driver/CC1AsOptions.td +++ b/clang/include/clang/Driver/CC1AsOptions.td @@ -20,6 +20,10 @@ include "OptParser.td" def triple : Separate<"-triple">, HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">; +def target_cpu : Separate<"-target-cpu">, + HelpText<"Target a specific cpu type">; +def target_feature : Separate<"-target-feature">, + HelpText<"Target specific attributes">; //===----------------------------------------------------------------------===// // Language Options diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 714a21a61a3e..c963654de522 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -2545,6 +2545,56 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.ClaimAllArgs(options::OPT_emit_llvm); } +void ClangAs::AddARMTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + llvm::Triple Triple = getToolChain().getTriple(); + + // Set the CPU based on -march= and -mcpu=. + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + + // Honor -mfpu=. + // + // FIXME: Centralize feature selection, defaulting shouldn't be also in the + // frontend target. + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { + StringRef FPU = A->getValue(Args); + + // Set the target features based on the FPU. + if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { + // Disable any default FPU support. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+d16"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3" || FPU == "vfpv3") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neon"); + } else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + } +} + void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2581,6 +2631,17 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, if (UseRelaxAll(C, Args)) CmdArgs.push_back("-relax-all"); + // Add target specific cpu and features flags. + switch(getToolChain().getTriple().getArch()) { + default: + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + AddARMTargetArgs(Args, CmdArgs); + break; + } + // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index fac524d26555..e607acb68561 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -59,6 +59,7 @@ namespace tools { /// \brief Clang integrated assembler tool. class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool { + void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; public: ClangAs(const ToolChain &TC) : Tool("clang::as", "clang integrated assembler", TC) {} diff --git a/clang/test/lit.cfg b/clang/test/lit.cfg index 726e861b4a86..f7592757844a 100644 --- a/clang/test/lit.cfg +++ b/clang/test/lit.cfg @@ -32,7 +32,7 @@ execute_external = (platform.system() != 'Windows' config.test_format = lit.formats.ShTest(execute_external) # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl'] +config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s'] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 84aeced4115d..fc8c5dca997e 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -63,8 +63,17 @@ struct AssemblerInvocation { /// @name Target Options /// @{ + /// The name of the target triple to assemble for. std::string Triple; + /// If given, the name of the target CPU to determine which instructions + /// are legal. + std::string CPU; + + /// The list of target specific features to enable or disable -- this should + /// be a list of strings starting with '+' or '-'. + std::vector Features; + /// @} /// @name Language Options /// @{ @@ -158,9 +167,13 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Construct the invocation. // Target Options - Opts.Triple = Triple::normalize(Args->getLastArgValue(OPT_triple)); - if (Opts.Triple.empty()) // Use the default target triple if unspecified. - Opts.Triple = sys::getDefaultTargetTriple(); + Opts.Triple = llvm::Triple::normalize(Args->getLastArgValue(OPT_triple)); + Opts.CPU = Args->getLastArgValue(OPT_target_cpu); + Opts.Features = Args->getAllArgValues(OPT_target_feature); + + // Use the default target triple if unspecified. + if (Opts.Triple.empty()) + Opts.Triple = llvm::sys::getDefaultTargetTriple(); // Language Options Opts.IncludePaths = Args->getAllArgValues(OPT_I); @@ -293,11 +306,19 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, if (!Opts.DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(Opts.DwarfDebugFlags)); + // Build up the feature string from the target feature list. + std::string FS; + if (!Opts.Features.empty()) { + FS = Opts.Features[0]; + for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i) + FS += "," + Opts.Features[i]; + } + OwningPtr Str; OwningPtr MCII(TheTarget->createMCInstrInfo()); OwningPtr - STI(TheTarget->createMCSubtargetInfo(Opts.Triple, "", "")); + STI(TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS)); // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { -- GitLab