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,
"no input files", ())
ERROR(error_invalid_arch,driver,none,
"invalid target architecture '%0'", (StringRef))
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG

View File

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

View File

@@ -273,6 +273,14 @@ def target : Joined<["--"], "target=">, Flags<[DriverOption, FrontendOption]>,
def target_legacy_spelling : Separate<["-"], "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">,
Flags<[FrontendOption]>,
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;
}
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,
StringRef DarwinArchName) {
// 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.
if (Target.isOSDarwin()) {
if (target.isOSDarwin()) {
// If an explict Darwin arch name is given, that trumps all.
if (!DarwinArchName.empty()) {
Target.setArch(
tools::darwin::getArchTypeForDarwinArchName(DarwinArchName));
return Target;
}
setTargetFromArch(diags, target, DarwinArchName);
// Handle the Darwin '-arch' flag.
if (Arg *A = Args.getLastArg(options::OPT_arch)) {
llvm::Triple::ArchType DarwinArch
= tools::darwin::getArchTypeForDarwinArchName(A->getValue());
if (DarwinArch != llvm::Triple::UnknownArch)
Target.setArch(DarwinArch);
} else if (Arg *A = Args.getLastArg(options::OPT_arch)) {
setTargetFromArch(diags, target, A->getValue());
}
}
// TODO: handle other target/pseudo-target flags as necessary.
return Target;
return target;
}
const ToolChain &Driver::getToolChain(const ArgList &Args,
StringRef DarwinArchName) const {
llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args,
llvm::Triple Target = computeTargetTriple(Diags, DefaultTargetTriple, Args,
DarwinArchName);
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,
std::unique_ptr<CommandOutput> Output,
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.
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) ||
Args.hasArg(options::OPT_emit_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("arm64", llvm::Triple::arm64)
.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
.Cases("armv7", "armv7em", "armv7f", "armv7k", "armv7m", 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;
}
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)) {
Opts.DisableAllRuntimeChecks = true;
}

View File

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