When targeting arm64-apple-ios, the target CPU is cyclone,

which provides the Neon feature.  Do all the necessary
plumbing to get this from the driver to the backend.

Also, support -arch arm64, and diagnose bad -arch values
instead of silently ignoring them.  It's not clear to me
that we really want to support -arch as an alternative
to -target, but unless we rip it out or establish some
sort of real policy about it, it really ought to do
something approximating the right thing.

It would be nice if we could abstract enough of clang's
driver that we could re-use some of its basic logic about
tool chains and targets instaed of iteratively
rediscovering everything it does that's actually
critically important.

Swift SVN r16447
This commit is contained in:
John McCall
2014-04-17 06:36:03 +00:00
parent 960a6f2892
commit 3cf3f42e98
7 changed files with 92 additions and 19 deletions

View File

@@ -69,6 +69,9 @@ ERROR(error_unable_to_make_temporary_file,driver,none,
ERROR(error_no_input_files,driver,none, ERROR(error_no_input_files,driver,none,
"no input files", ()) "no input files", ())
ERROR(error_invalid_arch,driver,none,
"invalid target architecture '%0'", (StringRef))
#ifndef DIAG_NO_UNDEF #ifndef DIAG_NO_UNDEF
# if defined(DIAG) # if defined(DIAG)
# undef DIAG # undef DIAG

View File

@@ -20,6 +20,7 @@
#include "swift/AST/LinkLibrary.h" #include "swift/AST/LinkLibrary.h"
#include <string> #include <string>
#include <vector>
namespace swift { namespace swift {
@@ -50,6 +51,9 @@ public:
std::string Triple; std::string Triple;
// The command line string that is to be stored in the DWARF debug info. // The command line string that is to be stored in the DWARF debug info.
std::string DWARFDebugFlags; std::string DWARFDebugFlags;
// The CPU and features.
std::string TargetCPU;
std::vector<std::string> TargetFeatures;
/// The libraries and frameworks specified on the command line. /// The libraries and frameworks specified on the command line.
SmallVector<LinkLibrary, 4> LinkLibraries; SmallVector<LinkLibrary, 4> LinkLibraries;

View File

@@ -273,6 +273,14 @@ def target : Joined<["--"], "target=">, Flags<[DriverOption, FrontendOption]>,
def target_legacy_spelling : Separate<["-"], "target">, def target_legacy_spelling : Separate<["-"], "target">,
Flags<[DriverOption, FrontendOption]>, Alias<target>; Flags<[DriverOption, FrontendOption]>, Alias<target>;
def target_cpu : Separate<["-"], "target-cpu">,
Flags<[DriverOption, FrontendOption]>,
HelpText<"Generate code for a particular CPU variant">;
def target_feature : Separate<["-"], "target-feature">,
Flags<[DriverOption, FrontendOption]>,
HelpText<"Generate code with a particular CPU feature enabled or disabled">,
MetaVarName<"[+-]<feature-name>">;
def working_directory : Separate<["-"], "working-directory">, def working_directory : Separate<["-"], "working-directory">,
Flags<[FrontendOption]>, Flags<[FrontendOption]>,
HelpText<"Resolve file paths relative to the specified directory">; HelpText<"Resolve file paths relative to the specified directory">;

View File

@@ -1095,39 +1095,45 @@ std::string Driver::getProgramPath(StringRef Name, const ToolChain &TC) const {
return Name; return Name;
} }
static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, static void setTargetFromArch(DiagnosticEngine &diags, llvm::Triple &target,
StringRef archName) {
llvm::Triple::ArchType archValue
= tools::darwin::getArchTypeForDarwinArchName(archName);
if (archValue != llvm::Triple::UnknownArch) {
target.setArch(archValue);
} else {
diags.diagnose(SourceLoc(), diag::error_invalid_arch, archName);
}
}
static llvm::Triple computeTargetTriple(DiagnosticEngine &diags,
StringRef DefaultTargetTriple,
const ArgList &Args, const ArgList &Args,
StringRef DarwinArchName) { StringRef DarwinArchName) {
// FIXME: need to check -target for overrides // FIXME: need to check -target for overrides
llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); llvm::Triple target(llvm::Triple::normalize(DefaultTargetTriple));
// Handle Darwin-specific options available here. // Handle Darwin-specific options available here.
if (Target.isOSDarwin()) { if (target.isOSDarwin()) {
// If an explict Darwin arch name is given, that trumps all. // If an explict Darwin arch name is given, that trumps all.
if (!DarwinArchName.empty()) { if (!DarwinArchName.empty()) {
Target.setArch( setTargetFromArch(diags, target, DarwinArchName);
tools::darwin::getArchTypeForDarwinArchName(DarwinArchName));
return Target;
}
// Handle the Darwin '-arch' flag. // Handle the Darwin '-arch' flag.
if (Arg *A = Args.getLastArg(options::OPT_arch)) { } else if (Arg *A = Args.getLastArg(options::OPT_arch)) {
llvm::Triple::ArchType DarwinArch setTargetFromArch(diags, target, A->getValue());
= tools::darwin::getArchTypeForDarwinArchName(A->getValue());
if (DarwinArch != llvm::Triple::UnknownArch)
Target.setArch(DarwinArch);
} }
} }
// TODO: handle other target/pseudo-target flags as necessary. // TODO: handle other target/pseudo-target flags as necessary.
return Target; return target;
} }
const ToolChain &Driver::getToolChain(const ArgList &Args, const ToolChain &Driver::getToolChain(const ArgList &Args,
StringRef DarwinArchName) const { StringRef DarwinArchName) const {
llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args, llvm::Triple Target = computeTargetTriple(Diags, DefaultTargetTriple, Args,
DarwinArchName); DarwinArchName);
ToolChain *&TC = ToolChains[Target.str()]; ToolChain *&TC = ToolChains[Target.str()];

View File

@@ -132,6 +132,17 @@ static void addCommonFrontendArgs(const ToolChain &TC,
} }
} }
// Should this be done by the tool chain?
static void configureDefaultCPU(const llvm::Triple &triple,
ArgStringList &args) {
if (triple.isOSDarwin() && triple.getArch() == llvm::Triple::arm64) {
args.push_back("-target-cpu");
args.push_back("cyclone");
args.push_back("-target-feature");
args.push_back("+neon");
}
}
Job *Swift::constructJob(const JobAction &JA, std::unique_ptr<JobList> Inputs, Job *Swift::constructJob(const JobAction &JA, std::unique_ptr<JobList> Inputs,
std::unique_ptr<CommandOutput> Output, std::unique_ptr<CommandOutput> Output,
const ActionList &InputActions, const ArgList &Args, const ActionList &InputActions, const ArgList &Args,
@@ -264,6 +275,14 @@ Job *Swift::constructJob(const JobAction &JA, std::unique_ptr<JobList> Inputs,
// Pass the optimization level down to the frontend. // Pass the optimization level down to the frontend.
Args.AddLastArg(Arguments, options::OPT_O_Group); Args.AddLastArg(Arguments, options::OPT_O_Group);
// Handle the CPU and its preferences.
if (auto arg = Args.getLastArg(options::OPT_target_cpu)) {
arg->render(Args, Arguments);
} else {
configureDefaultCPU(getToolChain().getTriple(), Arguments);
}
Args.AddAllArgs(Arguments, options::OPT_target_feature);
if (Args.hasArg(options::OPT_parse_as_library) || if (Args.hasArg(options::OPT_parse_as_library) ||
Args.hasArg(options::OPT_emit_library)) Args.hasArg(options::OPT_emit_library))
Arguments.push_back("-parse-as-library"); Arguments.push_back("-parse-as-library");
@@ -371,6 +390,8 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Arch) {
.Case("x86_64", llvm::Triple::x86_64) .Case("x86_64", llvm::Triple::x86_64)
.Case("arm64", llvm::Triple::arm64)
.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
.Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm) .Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", llvm::Triple::arm)
.Cases("armv7s", "xscale", llvm::Triple::arm) .Cases("armv7s", "xscale", llvm::Triple::arm)

View File

@@ -764,6 +764,29 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
Opts.OptLevel = 0; Opts.OptLevel = 0;
} }
if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
if (A->getOption().matches(OPT_O0)) {
Opts.OptLevel = 0;
}
else {
unsigned OptLevel;
if (StringRef(A->getValue()).getAsInteger(10, OptLevel) || OptLevel > 3) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
A->getAsString(Args), A->getValue());
return true;
}
Opts.OptLevel = OptLevel;
}
} else {
Opts.OptLevel = 0;
}
if (const Arg *A = Args.getLastArg(OPT_target_cpu)) {
Opts.TargetCPU = A->getValue();
}
Opts.TargetFeatures = Args.getAllArgValues(OPT_target_feature);
if (Args.hasArg(OPT_disable_all_runtime_checks)) { if (Args.hasArg(OPT_disable_all_runtime_checks)) {
Opts.DisableAllRuntimeChecks = true; Opts.DisableAllRuntimeChecks = true;
} }

View File

@@ -29,6 +29,7 @@
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h" #include "llvm/IR/Verifier.h"
#include "llvm/Linker/Linker.h" #include "llvm/Linker/Linker.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/PassManager.h" #include "llvm/PassManager.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@@ -90,17 +91,24 @@ static std::unique_ptr<llvm::Module> performIRGeneration(IRGenOptions &Opts,
// Set up TargetOptions. // Set up TargetOptions.
// Things that maybe we should collect from the command line: // Things that maybe we should collect from the command line:
// - CPU
// - features
// - relocation model // - relocation model
// - code model // - code model
TargetOptions TargetOpts; TargetOptions TargetOpts;
TargetOpts.NoFramePointerElim = Opts.DisableFPElim; TargetOpts.NoFramePointerElim = Opts.DisableFPElim;
// Create the target features string.
std::string targetFeatures;
if (!Opts.TargetFeatures.empty()) {
llvm::SubtargetFeatures features;
for (std::string &feature : Opts.TargetFeatures)
features.AddFeature(feature);
targetFeatures = features.getString();
}
// Create a target machine. // Create a target machine.
llvm::TargetMachine *TargetMachine llvm::TargetMachine *TargetMachine
= Target->createTargetMachine(Opts.Triple, /*cpu*/ "generic", = Target->createTargetMachine(Opts.Triple, Opts.TargetCPU,
/*features*/ "", std::move(targetFeatures),
TargetOpts, Reloc::PIC_, TargetOpts, Reloc::PIC_,
CodeModel::Default, OptLevel); CodeModel::Default, OptLevel);
if (!TargetMachine) { if (!TargetMachine) {