aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/ToolChains/Arch/Mips.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/ToolChains/Arch/Mips.cpp')
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.cpp78
1 files changed, 65 insertions, 13 deletions
diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp
index 61481a92d0b7..6d814631d05f 100644
--- a/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -20,11 +20,6 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-bool tools::isMipsArch(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
- Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
-}
-
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
@@ -50,6 +45,13 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (Triple.getOS() == llvm::Triple::OpenBSD)
DefMips64CPU = "mips3";
+ // MIPS2 is the default for mips(el)?-unknown-freebsd.
+ // MIPS3 is the default for mips64(el)?-unknown-freebsd.
+ if (Triple.getOS() == llvm::Triple::FreeBSD) {
+ DefMips32CPU = "mips2";
+ DefMips64CPU = "mips3";
+ }
+
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
options::OPT_mcpu_EQ))
CPUName = A->getValue();
@@ -106,11 +108,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (ABIName.empty()) {
// Deduce ABI name from the target triple.
- if (Triple.getArch() == llvm::Triple::mips ||
- Triple.getArch() == llvm::Triple::mipsel)
- ABIName = "o32";
- else
- ABIName = "n64";
+ ABIName = Triple.isMIPS32() ? "o32" : "n64";
}
if (CPUName.empty()) {
@@ -214,6 +212,7 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// For case (a) we need to add +noabicalls for N64.
bool IsN64 = ABIName == "64";
+ bool IsPIC = false;
bool NonPIC = false;
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
@@ -225,6 +224,9 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
NonPIC =
(O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
+ IsPIC =
+ (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));
}
bool UseAbiCalls = false;
@@ -234,9 +236,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
UseAbiCalls =
!ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
- if (UseAbiCalls && IsN64 && NonPIC) {
- D.Diag(diag::warn_drv_unsupported_abicalls);
- UseAbiCalls = false;
+ if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
+ D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
+ << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
+ NonPIC = false;
+ }
+
+ if (ABICallsArg && !UseAbiCalls && IsPIC) {
+ D.Diag(diag::err_drv_unsupported_noabicalls_pic);
}
if (!UseAbiCalls)
@@ -343,6 +350,34 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
"nomadd4");
AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
+ AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
+ "crc");
+ AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
+ "virt");
+ AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
+ "ginv");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
+ StringRef Val = StringRef(A->getValue());
+ if (Val == "hazard") {
+ Arg *B =
+ Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
+ Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
+
+ if (B && B->getOption().matches(options::OPT_mmicromips))
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << "micromips";
+ else if (C && C->getOption().matches(options::OPT_mips16))
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << "mips16";
+ else if (mips::supportsIndirectJumpHazardBarrier(CPUName))
+ Features.push_back("+use-indirect-jump-hazard");
+ else
+ D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
+ << "hazard" << CPUName;
+ } else
+ D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
+ }
}
mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
@@ -447,3 +482,20 @@ bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
return UseFPXX;
}
+
+bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
+ // Supporting the hazard barrier method of dealing with indirect
+ // jumps requires MIPSR2 support.
+ return llvm::StringSwitch<bool>(CPU)
+ .Case("mips32r2", true)
+ .Case("mips32r3", true)
+ .Case("mips32r5", true)
+ .Case("mips32r6", true)
+ .Case("mips64r2", true)
+ .Case("mips64r3", true)
+ .Case("mips64r5", true)
+ .Case("mips64r6", true)
+ .Case("octeon", true)
+ .Case("p5600", true)
+ .Default(false);
+}