|
| 1 | +//===--- Mips.cpp - Tools Implementations -----------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// The LLVM Compiler Infrastructure |
| 4 | +// |
| 5 | +// This file is distributed under the University of Illinois Open Source |
| 6 | +// License. See LICENSE.TXT for details. |
| 7 | +// |
| 8 | +//===----------------------------------------------------------------------===// |
| 9 | + |
| 10 | +#include "Tools.h" |
| 11 | +#include "clang/Driver/Driver.h" |
| 12 | +#include "clang/Driver/DriverDiagnostic.h" |
| 13 | +#include "clang/Driver/Options.h" |
| 14 | +#include "llvm/ADT/StringSwitch.h" |
| 15 | +#include "llvm/Option/ArgList.h" |
| 16 | + |
| 17 | +using namespace clang::driver; |
| 18 | +using namespace clang::driver::tools; |
| 19 | +using namespace clang; |
| 20 | +using namespace llvm::opt; |
| 21 | + |
| 22 | +// Get CPU and ABI names. They are not independent |
| 23 | +// so we have to calculate them together. |
| 24 | +void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, |
| 25 | + StringRef &CPUName, StringRef &ABIName) { |
| 26 | + const char *DefMips32CPU = "mips32r2"; |
| 27 | + const char *DefMips64CPU = "mips64r2"; |
| 28 | + |
| 29 | + // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the |
| 30 | + // default for mips64(el)?-img-linux-gnu. |
| 31 | + if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && |
| 32 | + Triple.getEnvironment() == llvm::Triple::GNU) { |
| 33 | + DefMips32CPU = "mips32r6"; |
| 34 | + DefMips64CPU = "mips64r6"; |
| 35 | + } |
| 36 | + |
| 37 | + // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android). |
| 38 | + if (Triple.isAndroid()) { |
| 39 | + DefMips32CPU = "mips32"; |
| 40 | + DefMips64CPU = "mips64r6"; |
| 41 | + } |
| 42 | + |
| 43 | + // MIPS3 is the default for mips64*-unknown-openbsd. |
| 44 | + if (Triple.getOS() == llvm::Triple::OpenBSD) |
| 45 | + DefMips64CPU = "mips3"; |
| 46 | + |
| 47 | + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, |
| 48 | + options::OPT_mcpu_EQ)) |
| 49 | + CPUName = A->getValue(); |
| 50 | + |
| 51 | + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
| 52 | + ABIName = A->getValue(); |
| 53 | + // Convert a GNU style Mips ABI name to the name |
| 54 | + // accepted by LLVM Mips backend. |
| 55 | + ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName) |
| 56 | + .Case("32", "o32") |
| 57 | + .Case("64", "n64") |
| 58 | + .Default(ABIName); |
| 59 | + } |
| 60 | + |
| 61 | + // Setup default CPU and ABI names. |
| 62 | + if (CPUName.empty() && ABIName.empty()) { |
| 63 | + switch (Triple.getArch()) { |
| 64 | + default: |
| 65 | + llvm_unreachable("Unexpected triple arch name"); |
| 66 | + case llvm::Triple::mips: |
| 67 | + case llvm::Triple::mipsel: |
| 68 | + CPUName = DefMips32CPU; |
| 69 | + break; |
| 70 | + case llvm::Triple::mips64: |
| 71 | + case llvm::Triple::mips64el: |
| 72 | + CPUName = DefMips64CPU; |
| 73 | + break; |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + if (ABIName.empty() && |
| 78 | + (Triple.getVendor() == llvm::Triple::MipsTechnologies || |
| 79 | + Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { |
| 80 | + ABIName = llvm::StringSwitch<const char *>(CPUName) |
| 81 | + .Case("mips1", "o32") |
| 82 | + .Case("mips2", "o32") |
| 83 | + .Case("mips3", "n64") |
| 84 | + .Case("mips4", "n64") |
| 85 | + .Case("mips5", "n64") |
| 86 | + .Case("mips32", "o32") |
| 87 | + .Case("mips32r2", "o32") |
| 88 | + .Case("mips32r3", "o32") |
| 89 | + .Case("mips32r5", "o32") |
| 90 | + .Case("mips32r6", "o32") |
| 91 | + .Case("mips64", "n64") |
| 92 | + .Case("mips64r2", "n64") |
| 93 | + .Case("mips64r3", "n64") |
| 94 | + .Case("mips64r5", "n64") |
| 95 | + .Case("mips64r6", "n64") |
| 96 | + .Case("octeon", "n64") |
| 97 | + .Case("p5600", "o32") |
| 98 | + .Default(""); |
| 99 | + } |
| 100 | + |
| 101 | + if (ABIName.empty()) { |
| 102 | + // Deduce ABI name from the target triple. |
| 103 | + if (Triple.getArch() == llvm::Triple::mips || |
| 104 | + Triple.getArch() == llvm::Triple::mipsel) |
| 105 | + ABIName = "o32"; |
| 106 | + else |
| 107 | + ABIName = "n64"; |
| 108 | + } |
| 109 | + |
| 110 | + if (CPUName.empty()) { |
| 111 | + // Deduce CPU name from ABI name. |
| 112 | + CPUName = llvm::StringSwitch<const char *>(ABIName) |
| 113 | + .Case("o32", DefMips32CPU) |
| 114 | + .Cases("n32", "n64", DefMips64CPU) |
| 115 | + .Default(""); |
| 116 | + } |
| 117 | + |
| 118 | + // FIXME: Warn on inconsistent use of -march and -mabi. |
| 119 | +} |
| 120 | + |
| 121 | +std::string mips::getMipsABILibSuffix(const ArgList &Args, |
| 122 | + const llvm::Triple &Triple) { |
| 123 | + StringRef CPUName, ABIName; |
| 124 | + tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
| 125 | + return llvm::StringSwitch<std::string>(ABIName) |
| 126 | + .Case("o32", "") |
| 127 | + .Case("n32", "32") |
| 128 | + .Case("n64", "64"); |
| 129 | +} |
| 130 | + |
| 131 | +// Convert ABI name to the GNU tools acceptable variant. |
| 132 | +StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { |
| 133 | + return llvm::StringSwitch<llvm::StringRef>(ABI) |
| 134 | + .Case("o32", "32") |
| 135 | + .Case("n64", "64") |
| 136 | + .Default(ABI); |
| 137 | +} |
| 138 | + |
| 139 | +// Select the MIPS float ABI as determined by -msoft-float, -mhard-float, |
| 140 | +// and -mfloat-abi=. |
| 141 | +mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { |
| 142 | + mips::FloatABI ABI = mips::FloatABI::Invalid; |
| 143 | + if (Arg *A = |
| 144 | + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
| 145 | + options::OPT_mfloat_abi_EQ)) { |
| 146 | + if (A->getOption().matches(options::OPT_msoft_float)) |
| 147 | + ABI = mips::FloatABI::Soft; |
| 148 | + else if (A->getOption().matches(options::OPT_mhard_float)) |
| 149 | + ABI = mips::FloatABI::Hard; |
| 150 | + else { |
| 151 | + ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue()) |
| 152 | + .Case("soft", mips::FloatABI::Soft) |
| 153 | + .Case("hard", mips::FloatABI::Hard) |
| 154 | + .Default(mips::FloatABI::Invalid); |
| 155 | + if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { |
| 156 | + D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
| 157 | + ABI = mips::FloatABI::Hard; |
| 158 | + } |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + // If unspecified, choose the default based on the platform. |
| 163 | + if (ABI == mips::FloatABI::Invalid) { |
| 164 | + // Assume "hard", because it's a default value used by gcc. |
| 165 | + // When we start to recognize specific target MIPS processors, |
| 166 | + // we will be able to select the default more correctly. |
| 167 | + ABI = mips::FloatABI::Hard; |
| 168 | + } |
| 169 | + |
| 170 | + assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); |
| 171 | + return ABI; |
| 172 | +} |
| 173 | + |
| 174 | +void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
| 175 | + const ArgList &Args, |
| 176 | + std::vector<StringRef> &Features) { |
| 177 | + StringRef CPUName; |
| 178 | + StringRef ABIName; |
| 179 | + getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
| 180 | + ABIName = getGnuCompatibleMipsABIName(ABIName); |
| 181 | + |
| 182 | + // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a |
| 183 | + // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI |
| 184 | + // extension was developed by Richard Sandiford & Code Sourcery to support |
| 185 | + // static code calling PIC code (CPIC). For O32 and N32 this means we have |
| 186 | + // several combinations of PIC/static and abicalls. Pure static, static |
| 187 | + // with the CPIC extension, and pure PIC code. |
| 188 | + |
| 189 | + // At final link time, O32 and N32 with CPIC will have another section |
| 190 | + // added to the binary which contains the stub functions to perform |
| 191 | + // any fixups required for PIC code. |
| 192 | + |
| 193 | + // For N64, the situation is more regular: code can either be static |
| 194 | + // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code |
| 195 | + // code for N64. Since Clang has already built the relocation model portion |
| 196 | + // of the commandline, we pick add +noabicalls feature in the N64 static |
| 197 | + // case. |
| 198 | + |
| 199 | + // The is another case to be accounted for: -msym32, which enforces that all |
| 200 | + // symbols have 32 bits in size. In this case, N64 can in theory use CPIC |
| 201 | + // but it is unsupported. |
| 202 | + |
| 203 | + // The combinations for N64 are: |
| 204 | + // a) Static without abicalls and 64bit symbols. |
| 205 | + // b) Static with abicalls and 32bit symbols. |
| 206 | + // c) PIC with abicalls and 64bit symbols. |
| 207 | + |
| 208 | + // For case (a) we need to add +noabicalls for N64. |
| 209 | + |
| 210 | + bool IsN64 = ABIName == "64"; |
| 211 | + bool NonPIC = false; |
| 212 | + |
| 213 | + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
| 214 | + options::OPT_fpic, options::OPT_fno_pic, |
| 215 | + options::OPT_fPIE, options::OPT_fno_PIE, |
| 216 | + options::OPT_fpie, options::OPT_fno_pie); |
| 217 | + if (LastPICArg) { |
| 218 | + Option O = LastPICArg->getOption(); |
| 219 | + NonPIC = |
| 220 | + (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) || |
| 221 | + O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie)); |
| 222 | + } |
| 223 | + |
| 224 | + if (IsN64 && NonPIC) { |
| 225 | + Features.push_back("+noabicalls"); |
| 226 | + } else { |
| 227 | + AddTargetFeature(Args, Features, options::OPT_mno_abicalls, |
| 228 | + options::OPT_mabicalls, "noabicalls"); |
| 229 | + } |
| 230 | + |
| 231 | + mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args); |
| 232 | + if (FloatABI == mips::FloatABI::Soft) { |
| 233 | + // FIXME: Note, this is a hack. We need to pass the selected float |
| 234 | + // mode to the MipsTargetInfoBase to define appropriate macros there. |
| 235 | + // Now it is the only method. |
| 236 | + Features.push_back("+soft-float"); |
| 237 | + } |
| 238 | + |
| 239 | + if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { |
| 240 | + StringRef Val = StringRef(A->getValue()); |
| 241 | + if (Val == "2008") { |
| 242 | + if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008) |
| 243 | + Features.push_back("+nan2008"); |
| 244 | + else { |
| 245 | + Features.push_back("-nan2008"); |
| 246 | + D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; |
| 247 | + } |
| 248 | + } else if (Val == "legacy") { |
| 249 | + if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy) |
| 250 | + Features.push_back("-nan2008"); |
| 251 | + else { |
| 252 | + Features.push_back("+nan2008"); |
| 253 | + D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; |
| 254 | + } |
| 255 | + } else |
| 256 | + D.Diag(diag::err_drv_unsupported_option_argument) |
| 257 | + << A->getOption().getName() << Val; |
| 258 | + } |
| 259 | + |
| 260 | + AddTargetFeature(Args, Features, options::OPT_msingle_float, |
| 261 | + options::OPT_mdouble_float, "single-float"); |
| 262 | + AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, |
| 263 | + "mips16"); |
| 264 | + AddTargetFeature(Args, Features, options::OPT_mmicromips, |
| 265 | + options::OPT_mno_micromips, "micromips"); |
| 266 | + AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, |
| 267 | + "dsp"); |
| 268 | + AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, |
| 269 | + "dspr2"); |
| 270 | + AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, |
| 271 | + "msa"); |
| 272 | + |
| 273 | + // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 |
| 274 | + // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and |
| 275 | + // nooddspreg. |
| 276 | + if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, |
| 277 | + options::OPT_mfp64)) { |
| 278 | + if (A->getOption().matches(options::OPT_mfp32)) |
| 279 | + Features.push_back(Args.MakeArgString("-fp64")); |
| 280 | + else if (A->getOption().matches(options::OPT_mfpxx)) { |
| 281 | + Features.push_back(Args.MakeArgString("+fpxx")); |
| 282 | + Features.push_back(Args.MakeArgString("+nooddspreg")); |
| 283 | + } else |
| 284 | + Features.push_back(Args.MakeArgString("+fp64")); |
| 285 | + } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { |
| 286 | + Features.push_back(Args.MakeArgString("+fpxx")); |
| 287 | + Features.push_back(Args.MakeArgString("+nooddspreg")); |
| 288 | + } else if (mips::isFP64ADefault(Triple, CPUName)) { |
| 289 | + Features.push_back(Args.MakeArgString("+fp64")); |
| 290 | + Features.push_back(Args.MakeArgString("+nooddspreg")); |
| 291 | + } |
| 292 | + |
| 293 | + AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, |
| 294 | + options::OPT_modd_spreg, "nooddspreg"); |
| 295 | +} |
| 296 | + |
| 297 | +mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { |
| 298 | + // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008 |
| 299 | + // was first introduced in Release 3. However, other compilers have |
| 300 | + // traditionally allowed it for Release 2 so we should do the same. |
| 301 | + return (NanEncoding)llvm::StringSwitch<int>(CPU) |
| 302 | + .Case("mips1", NanLegacy) |
| 303 | + .Case("mips2", NanLegacy) |
| 304 | + .Case("mips3", NanLegacy) |
| 305 | + .Case("mips4", NanLegacy) |
| 306 | + .Case("mips5", NanLegacy) |
| 307 | + .Case("mips32", NanLegacy) |
| 308 | + .Case("mips32r2", NanLegacy | Nan2008) |
| 309 | + .Case("mips32r3", NanLegacy | Nan2008) |
| 310 | + .Case("mips32r5", NanLegacy | Nan2008) |
| 311 | + .Case("mips32r6", Nan2008) |
| 312 | + .Case("mips64", NanLegacy) |
| 313 | + .Case("mips64r2", NanLegacy | Nan2008) |
| 314 | + .Case("mips64r3", NanLegacy | Nan2008) |
| 315 | + .Case("mips64r5", NanLegacy | Nan2008) |
| 316 | + .Case("mips64r6", Nan2008) |
| 317 | + .Default(NanLegacy); |
| 318 | +} |
| 319 | + |
| 320 | +bool mips::hasCompactBranches(StringRef &CPU) { |
| 321 | + // mips32r6 and mips64r6 have compact branches. |
| 322 | + return llvm::StringSwitch<bool>(CPU) |
| 323 | + .Case("mips32r6", true) |
| 324 | + .Case("mips64r6", true) |
| 325 | + .Default(false); |
| 326 | +} |
| 327 | + |
| 328 | +bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { |
| 329 | + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
| 330 | + return A && (A->getValue() == StringRef(Value)); |
| 331 | +} |
| 332 | + |
| 333 | +bool mips::isUCLibc(const ArgList &Args) { |
| 334 | + Arg *A = Args.getLastArg(options::OPT_m_libc_Group); |
| 335 | + return A && A->getOption().matches(options::OPT_muclibc); |
| 336 | +} |
| 337 | + |
| 338 | +bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) { |
| 339 | + if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) |
| 340 | + return llvm::StringSwitch<bool>(NaNArg->getValue()) |
| 341 | + .Case("2008", true) |
| 342 | + .Case("legacy", false) |
| 343 | + .Default(false); |
| 344 | + |
| 345 | + // NaN2008 is the default for MIPS32r6/MIPS64r6. |
| 346 | + return llvm::StringSwitch<bool>(getCPUName(Args, Triple)) |
| 347 | + .Cases("mips32r6", "mips64r6", true) |
| 348 | + .Default(false); |
| 349 | + |
| 350 | + return false; |
| 351 | +} |
| 352 | + |
| 353 | +bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { |
| 354 | + if (!Triple.isAndroid()) |
| 355 | + return false; |
| 356 | + |
| 357 | + // Android MIPS32R6 defaults to FP64A. |
| 358 | + return llvm::StringSwitch<bool>(CPUName) |
| 359 | + .Case("mips32r6", true) |
| 360 | + .Default(false); |
| 361 | +} |
| 362 | + |
| 363 | +bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, |
| 364 | + StringRef ABIName, mips::FloatABI FloatABI) { |
| 365 | + if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && |
| 366 | + Triple.getVendor() != llvm::Triple::MipsTechnologies && |
| 367 | + !Triple.isAndroid()) |
| 368 | + return false; |
| 369 | + |
| 370 | + if (ABIName != "32") |
| 371 | + return false; |
| 372 | + |
| 373 | + // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is |
| 374 | + // present. |
| 375 | + if (FloatABI == mips::FloatABI::Soft) |
| 376 | + return false; |
| 377 | + |
| 378 | + return llvm::StringSwitch<bool>(CPUName) |
| 379 | + .Cases("mips2", "mips3", "mips4", "mips5", true) |
| 380 | + .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) |
| 381 | + .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) |
| 382 | + .Default(false); |
| 383 | +} |
| 384 | + |
| 385 | +bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, |
| 386 | + StringRef CPUName, StringRef ABIName, |
| 387 | + mips::FloatABI FloatABI) { |
| 388 | + bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); |
| 389 | + |
| 390 | + // FPXX shouldn't be used if -msingle-float is present. |
| 391 | + if (Arg *A = Args.getLastArg(options::OPT_msingle_float, |
| 392 | + options::OPT_mdouble_float)) |
| 393 | + if (A->getOption().matches(options::OPT_msingle_float)) |
| 394 | + UseFPXX = false; |
| 395 | + |
| 396 | + return UseFPXX; |
| 397 | +} |
0 commit comments