Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -333,6 +333,10 @@ "ignoring '-mabicalls' option as it cannot be used with " "non position-independent code and the N64 ABI">, InGroup; +def err_drv_unsupported_indirect_jump_opt : Error< + "'-mindirect-jump=%0' is unsupported with the '%1' architecture">; +def err_drv_unknown_indirect_jump_opt : Error< + "unknown '-mindirect-jump=' option '%0'">; def warn_drv_unable_to_find_directory_expected : Warning< "unable to find %0 directory, expected to be in '%1'">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -2022,6 +2022,9 @@ IgnoredGCCCompat; def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group, IgnoredGCCCompat; +def mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">, + Group, + HelpText<"Change indirect jump instructions to inhibit speculation">; def mdsp : Flag<["-"], "mdsp">, Group; def mno_dsp : Flag<["-"], "mno-dsp">, Group; def mdspr2 : Flag<["-"], "mdspr2">, Group; Index: lib/Basic/Targets/Mips.h =================================================================== --- lib/Basic/Targets/Mips.h +++ lib/Basic/Targets/Mips.h @@ -54,6 +54,7 @@ enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; bool HasMSA; bool DisableMadd4; + bool UseIndirectJumpHazard; protected: bool HasFP64; @@ -64,7 +65,8 @@ : TargetInfo(Triple), IsMips16(false), IsMicromips(false), IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), - DspRev(NoDSP), HasMSA(false), DisableMadd4(false), HasFP64(false) { + DspRev(NoDSP), HasMSA(false), DisableMadd4(false), + UseIndirectJumpHazard(false), HasFP64(false) { TheCXXABI.set(TargetCXXABI::GenericMIPS); setABI((getTriple().getArch() == llvm::Triple::mips || @@ -339,6 +341,8 @@ IsAbs2008 = false; else if (Feature == "+noabicalls") IsNoABICalls = true; + else if (Feature == "+use-indirect-jump-hazard") + UseIndirectJumpHazard = true; } setDataLayout(); Index: lib/Driver/ToolChains/Arch/Mips.h =================================================================== --- lib/Driver/ToolChains/Arch/Mips.h +++ lib/Driver/ToolChains/Arch/Mips.h @@ -53,6 +53,7 @@ bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName, mips::FloatABI FloatABI); +bool supportsIndirectJumpHazardBarrier(StringRef &CPU); } // end namespace mips } // end namespace target Index: lib/Driver/ToolChains/Arch/Mips.cpp =================================================================== --- lib/Driver/ToolChains/Arch/Mips.cpp +++ lib/Driver/ToolChains/Arch/Mips.cpp @@ -343,6 +343,28 @@ AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, "nomadd4"); AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt"); + + 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 +469,20 @@ return UseFPXX; } + +bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) { + // Supporting the hazard barrier method of dealing with indirect + // jumps requires MIPSR2 support. + return llvm::StringSwitch(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); +} Index: test/Driver/mips-features.c =================================================================== --- test/Driver/mips-features.c +++ test/Driver/mips-features.c @@ -402,3 +402,9 @@ // RUN: %clang -target -mips-mti-linux-gnu -### -c %s -mno-branch-likely 2>&1 \ // RUN: | FileCheck --check-prefix=NO-BRANCH-LIKELY %s // NO-BRANCH-LIKELY: argument unused during compilation: '-mno-branch-likely' + +// -mindirect-jump=hazard +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mindirect-jump=hazard 2>&1 \ +// RUN: | FileCheck --check-prefix=INDIRECT-BH %s +// INDIRECT-BH: "-target-feature" "+use-indirect-jump-hazard" Index: test/Driver/mips-indirect-branch.c =================================================================== --- /dev/null +++ test/Driver/mips-indirect-branch.c @@ -0,0 +1,23 @@ +// REQUIRES: mips-registered-target +// -mindirect-jump=hazard -mips32 +// RUN: %clang -target mips-unknown-linux-gnu -mips32 -### -c %s \ +// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MIPS32 +// MIPS32: error: '-mindirect-jump=hazard' is unsupported with the 'mips32' architecture + +// -mindirect-jump=hazard -mmicromips +// RUN: %clang -target mips-unknown-linux-gnu -mmicromips -### -c %s \ +// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MICROMIPS +// MICROMIPS: error: '-mindirect-jump=hazard' is unsupported with the 'micromips' architecture + +// -mindirect-jump=hazard -mips16 +// RUN: %clang -target mips-unknown-linux-gnu -mips16 -### -c %s \ +// RUN: -mindirect-jump=hazard 2>&1 | FileCheck %s --check-prefix=MIPS16 +// MIPS16: error: '-mindirect-jump=hazard' is unsupported with the 'mips16' architecture + +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mindirect-jump=retopline 2>&1 | FileCheck %s --check-prefix=RETOPLINE +// RETOPLINE: error: unknown '-mindirect-jump=' option 'retopline' + +// RUN: %clang -target mips-unknown-linux-gnu -### -mips32 -c %s \ +// RUN: -mindirect-jump=retopline 2>&1 | FileCheck %s --check-prefix=MIXED +// MIXED: error: unknown '-mindirect-jump=' option 'retopline'