Add support for MIPS' floating ABIs (hard, soft and single) to clang driver.

Patch by Simon Atanasyan.

llvm-svn: 153348
This commit is contained in:
Akira Hatanaka 2012-03-23 23:07:09 +00:00
parent 190e7b6e18
commit 6976ec8551
2 changed files with 91 additions and 11 deletions

View File

@ -3440,11 +3440,19 @@ namespace {
namespace {
class MipsTargetInfoBase : public TargetInfo {
std::string CPU;
bool SoftFloat;
bool SingleFloat;
protected:
std::string ABI;
public:
MipsTargetInfoBase(const std::string& triple, const std::string& ABIStr)
: TargetInfo(triple), ABI(ABIStr) {}
: TargetInfo(triple),
SoftFloat(false), SingleFloat(false),
ABI(ABIStr)
{}
virtual const char *getABI() const { return ABI.c_str(); }
virtual bool setABI(const std::string &Name) = 0;
virtual bool setCPU(const std::string &Name) {
@ -3455,8 +3463,19 @@ public:
Features[ABI] = true;
Features[CPU] = true;
}
virtual void getArchDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0;
MacroBuilder &Builder) const {
if (SoftFloat)
Builder.defineMacro("__mips_soft_float", Twine(1));
else if (SingleFloat)
Builder.defineMacro("__mips_single_float", Twine(1));
else if (!SoftFloat && !SingleFloat)
Builder.defineMacro("__mips_hard_float", Twine(1));
else
llvm_unreachable("Invalid float ABI for Mips.");
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0;
virtual void getTargetBuiltins(const Builtin::Info *&Records,
@ -3507,6 +3526,37 @@ public:
// FIXME: Implement!
return "";
}
virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
if (Name == "soft-float" || Name == "single-float") {
Features[Name] = Enabled;
return true;
}
return false;
}
virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
SoftFloat = false;
SingleFloat = false;
for (std::vector<std::string>::iterator it = Features.begin(),
ie = Features.end(); it != ie; ++it) {
if (*it == "+single-float") {
SingleFloat = true;
break;
}
if (*it == "+soft-float") {
SoftFloat = true;
// This option is front-end specific.
// Do not need to pass it to the backend.
Features.erase(it);
break;
}
}
}
};
class Mips32TargetInfoBase : public MipsTargetInfoBase {
@ -3525,6 +3575,8 @@ public:
}
virtual void getArchDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
MipsTargetInfoBase::getArchDefines(Opts, Builder);
Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(0)));
Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
@ -3642,6 +3694,8 @@ public:
}
virtual void getArchDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
MipsTargetInfoBase::getArchDefines(Opts, Builder);
if (ABI == "n32") {
Builder.defineMacro("__mips_n32");
Builder.defineMacro("_ABIN32", "2");

View File

@ -787,31 +787,57 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// Select the float ABI as determined by -msoft-float, -mhard-float,
// and -mfloat-abi=.
StringRef FloatABI;
if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
options::OPT_mhard_float)) {
options::OPT_mhard_float,
options::OPT_mfloat_abi_EQ)) {
if (A->getOption().matches(options::OPT_msoft_float))
FloatABI = "soft";
else if (A->getOption().matches(options::OPT_mhard_float))
FloatABI = "hard";
else {
FloatABI = A->getValue(Args);
if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") {
D.Diag(diag::err_drv_invalid_mfloat_abi)
<< A->getAsString(Args);
FloatABI = "hard";
}
}
}
// If unspecified, choose the default based on the platform.
if (FloatABI.empty()) {
// Assume "soft", but warn the user we are guessing.
FloatABI = "soft";
D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
// Assume "hard", because it's a default value used by gcc.
// When we start to recognize specific target MIPS processors,
// we will be able to select the default more correctly.
FloatABI = "hard";
}
if (FloatABI == "soft") {
// Floating point operations and argument passing are soft.
//
// FIXME: This changes CPP defines, we need -target-soft-float.
CmdArgs.push_back("-msoft-float");
} else {
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
// FIXME: Note, this is a hack. We need to pass the selected float
// mode to the MipsTargetInfoBase to define appropriate macros there.
// Now it is the only method.
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+soft-float");
}
else if (FloatABI == "single") {
// Restrict the use of hardware floating-point
// instructions to 32-bit operations.
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+single-float");
}
else {
// Floating point operations and argument passing are hard.
assert(FloatABI == "hard" && "Invalid float abi!");
CmdArgs.push_back("-mhard-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
}