| 1 | //===--- Sparc.cpp - Tools Implementations ----------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "Sparc.h" |
| 10 | #include "clang/Driver/Driver.h" |
| 11 | #include "clang/Driver/Options.h" |
| 12 | #include "llvm/ADT/StringSwitch.h" |
| 13 | #include "llvm/Option/ArgList.h" |
| 14 | #include "llvm/TargetParser/Host.h" |
| 15 | |
| 16 | using namespace clang::driver; |
| 17 | using namespace clang::driver::tools; |
| 18 | using namespace clang; |
| 19 | using namespace llvm::opt; |
| 20 | |
| 21 | const char *sparc::getSparcAsmModeForCPU(StringRef Name, |
| 22 | const llvm::Triple &Triple) { |
| 23 | if (Triple.getArch() == llvm::Triple::sparcv9) { |
| 24 | const char *DefV9CPU; |
| 25 | |
| 26 | if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) |
| 27 | DefV9CPU = "-Av9a" ; |
| 28 | else |
| 29 | DefV9CPU = "-Av9" ; |
| 30 | |
| 31 | return llvm::StringSwitch<const char *>(Name) |
| 32 | .Case(S: "niagara" , Value: "-Av9b" ) |
| 33 | .Case(S: "niagara2" , Value: "-Av9b" ) |
| 34 | .Case(S: "niagara3" , Value: "-Av9d" ) |
| 35 | .Case(S: "niagara4" , Value: "-Av9d" ) |
| 36 | .Default(Value: DefV9CPU); |
| 37 | } else { |
| 38 | return llvm::StringSwitch<const char *>(Name) |
| 39 | .Case(S: "v8" , Value: "-Av8" ) |
| 40 | .Case(S: "supersparc" , Value: "-Av8" ) |
| 41 | .Case(S: "sparclite" , Value: "-Asparclite" ) |
| 42 | .Case(S: "f934" , Value: "-Asparclite" ) |
| 43 | .Case(S: "hypersparc" , Value: "-Av8" ) |
| 44 | .Case(S: "sparclite86x" , Value: "-Asparclite" ) |
| 45 | .Case(S: "sparclet" , Value: "-Asparclet" ) |
| 46 | .Case(S: "tsc701" , Value: "-Asparclet" ) |
| 47 | .Case(S: "v9" , Value: "-Av8plus" ) |
| 48 | .Case(S: "ultrasparc" , Value: "-Av8plus" ) |
| 49 | .Case(S: "ultrasparc3" , Value: "-Av8plus" ) |
| 50 | .Case(S: "niagara" , Value: "-Av8plusb" ) |
| 51 | .Case(S: "niagara2" , Value: "-Av8plusb" ) |
| 52 | .Case(S: "niagara3" , Value: "-Av8plusd" ) |
| 53 | .Case(S: "niagara4" , Value: "-Av8plusd" ) |
| 54 | .Case(S: "ma2100" , Value: "-Aleon" ) |
| 55 | .Case(S: "ma2150" , Value: "-Aleon" ) |
| 56 | .Case(S: "ma2155" , Value: "-Aleon" ) |
| 57 | .Case(S: "ma2450" , Value: "-Aleon" ) |
| 58 | .Case(S: "ma2455" , Value: "-Aleon" ) |
| 59 | .Case(S: "ma2x5x" , Value: "-Aleon" ) |
| 60 | .Case(S: "ma2080" , Value: "-Aleon" ) |
| 61 | .Case(S: "ma2085" , Value: "-Aleon" ) |
| 62 | .Case(S: "ma2480" , Value: "-Aleon" ) |
| 63 | .Case(S: "ma2485" , Value: "-Aleon" ) |
| 64 | .Case(S: "ma2x8x" , Value: "-Aleon" ) |
| 65 | .Case(S: "leon2" , Value: "-Av8" ) |
| 66 | .Case(S: "at697e" , Value: "-Av8" ) |
| 67 | .Case(S: "at697f" , Value: "-Av8" ) |
| 68 | .Case(S: "leon3" , Value: "-Aleon" ) |
| 69 | .Case(S: "ut699" , Value: "-Av8" ) |
| 70 | .Case(S: "gr712rc" , Value: "-Aleon" ) |
| 71 | .Case(S: "leon4" , Value: "-Aleon" ) |
| 72 | .Case(S: "gr740" , Value: "-Aleon" ) |
| 73 | .Default(Value: "-Av8" ); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, |
| 78 | const ArgList &Args) { |
| 79 | sparc::FloatABI ABI = sparc::FloatABI::Invalid; |
| 80 | if (Arg *A = Args.getLastArg(Ids: options::OPT_msoft_float, Ids: options::OPT_mno_fpu, |
| 81 | Ids: options::OPT_mhard_float, Ids: options::OPT_mfpu, |
| 82 | Ids: options::OPT_mfloat_abi_EQ)) { |
| 83 | if (A->getOption().matches(ID: options::OPT_msoft_float) || |
| 84 | A->getOption().matches(ID: options::OPT_mno_fpu)) |
| 85 | ABI = sparc::FloatABI::Soft; |
| 86 | else if (A->getOption().matches(ID: options::OPT_mhard_float) || |
| 87 | A->getOption().matches(ID: options::OPT_mfpu)) |
| 88 | ABI = sparc::FloatABI::Hard; |
| 89 | else { |
| 90 | ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue()) |
| 91 | .Case(S: "soft" , Value: sparc::FloatABI::Soft) |
| 92 | .Case(S: "hard" , Value: sparc::FloatABI::Hard) |
| 93 | .Default(Value: sparc::FloatABI::Invalid); |
| 94 | if (ABI == sparc::FloatABI::Invalid && |
| 95 | !StringRef(A->getValue()).empty()) { |
| 96 | D.Diag(DiagID: clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
| 97 | ABI = sparc::FloatABI::Hard; |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | // If unspecified, choose the default based on the platform. |
| 103 | // Only the hard-float ABI on Sparc is standardized, and it is the |
| 104 | // default. GCC also supports a nonstandard soft-float ABI mode, also |
| 105 | // implemented in LLVM. However as this is not standard we set the default |
| 106 | // to be hard-float. |
| 107 | if (ABI == sparc::FloatABI::Invalid) { |
| 108 | ABI = sparc::FloatABI::Hard; |
| 109 | } |
| 110 | |
| 111 | return ABI; |
| 112 | } |
| 113 | |
| 114 | std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, |
| 115 | const llvm::Triple &Triple) { |
| 116 | if (const Arg *A = Args.getLastArg(Ids: clang::driver::options::OPT_mcpu_EQ)) { |
| 117 | StringRef CPUName = A->getValue(); |
| 118 | if (CPUName == "native" ) { |
| 119 | std::string CPU = std::string(llvm::sys::getHostCPUName()); |
| 120 | if (!CPU.empty() && CPU != "generic" ) |
| 121 | return CPU; |
| 122 | return "" ; |
| 123 | } |
| 124 | return std::string(CPUName); |
| 125 | } |
| 126 | |
| 127 | if (Triple.getArch() == llvm::Triple::sparc && |
| 128 | (Triple.isOSSolaris() || Triple.isOSLinux())) |
| 129 | return "v9" ; |
| 130 | return "" ; |
| 131 | } |
| 132 | |
| 133 | void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, |
| 134 | std::vector<StringRef> &Features) { |
| 135 | sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); |
| 136 | if (FloatABI == sparc::FloatABI::Soft) |
| 137 | Features.push_back(x: "+soft-float" ); |
| 138 | |
| 139 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mfsmuld, Ids: options::OPT_mno_fsmuld)) { |
| 140 | if (A->getOption().matches(ID: options::OPT_mfsmuld)) |
| 141 | Features.push_back(x: "+fsmuld" ); |
| 142 | else |
| 143 | Features.push_back(x: "-fsmuld" ); |
| 144 | } |
| 145 | |
| 146 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mpopc, Ids: options::OPT_mno_popc)) { |
| 147 | if (A->getOption().matches(ID: options::OPT_mpopc)) |
| 148 | Features.push_back(x: "+popc" ); |
| 149 | else |
| 150 | Features.push_back(x: "-popc" ); |
| 151 | } |
| 152 | |
| 153 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mvis, Ids: options::OPT_mno_vis)) { |
| 154 | if (A->getOption().matches(ID: options::OPT_mvis)) |
| 155 | Features.push_back(x: "+vis" ); |
| 156 | else |
| 157 | Features.push_back(x: "-vis" ); |
| 158 | } |
| 159 | |
| 160 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mvis2, Ids: options::OPT_mno_vis2)) { |
| 161 | if (A->getOption().matches(ID: options::OPT_mvis2)) |
| 162 | Features.push_back(x: "+vis2" ); |
| 163 | else |
| 164 | Features.push_back(x: "-vis2" ); |
| 165 | } |
| 166 | |
| 167 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mvis3, Ids: options::OPT_mno_vis3)) { |
| 168 | if (A->getOption().matches(ID: options::OPT_mvis3)) |
| 169 | Features.push_back(x: "+vis3" ); |
| 170 | else |
| 171 | Features.push_back(x: "-vis3" ); |
| 172 | } |
| 173 | |
| 174 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mhard_quad_float, |
| 175 | Ids: options::OPT_msoft_quad_float)) { |
| 176 | if (A->getOption().matches(ID: options::OPT_mhard_quad_float)) |
| 177 | Features.push_back(x: "+hard-quad-float" ); |
| 178 | else |
| 179 | Features.push_back(x: "-hard-quad-float" ); |
| 180 | } |
| 181 | |
| 182 | if (Arg *A = Args.getLastArg(Ids: options::OPT_mv8plus, Ids: options::OPT_mno_v8plus)) { |
| 183 | if (A->getOption().matches(ID: options::OPT_mv8plus)) |
| 184 | Features.push_back(x: "+v8plus" ); |
| 185 | } |
| 186 | |
| 187 | if (Args.hasArg(Ids: options::OPT_ffixed_g1)) |
| 188 | Features.push_back(x: "+reserve-g1" ); |
| 189 | |
| 190 | if (Args.hasArg(Ids: options::OPT_ffixed_g2)) |
| 191 | Features.push_back(x: "+reserve-g2" ); |
| 192 | |
| 193 | if (Args.hasArg(Ids: options::OPT_ffixed_g3)) |
| 194 | Features.push_back(x: "+reserve-g3" ); |
| 195 | |
| 196 | if (Args.hasArg(Ids: options::OPT_ffixed_g4)) |
| 197 | Features.push_back(x: "+reserve-g4" ); |
| 198 | |
| 199 | if (Args.hasArg(Ids: options::OPT_ffixed_g5)) |
| 200 | Features.push_back(x: "+reserve-g5" ); |
| 201 | |
| 202 | if (Args.hasArg(Ids: options::OPT_ffixed_g6)) |
| 203 | Features.push_back(x: "+reserve-g6" ); |
| 204 | |
| 205 | if (Args.hasArg(Ids: options::OPT_ffixed_g7)) |
| 206 | Features.push_back(x: "+reserve-g7" ); |
| 207 | |
| 208 | if (Args.hasArg(Ids: options::OPT_ffixed_o0)) |
| 209 | Features.push_back(x: "+reserve-o0" ); |
| 210 | |
| 211 | if (Args.hasArg(Ids: options::OPT_ffixed_o1)) |
| 212 | Features.push_back(x: "+reserve-o1" ); |
| 213 | |
| 214 | if (Args.hasArg(Ids: options::OPT_ffixed_o2)) |
| 215 | Features.push_back(x: "+reserve-o2" ); |
| 216 | |
| 217 | if (Args.hasArg(Ids: options::OPT_ffixed_o3)) |
| 218 | Features.push_back(x: "+reserve-o3" ); |
| 219 | |
| 220 | if (Args.hasArg(Ids: options::OPT_ffixed_o4)) |
| 221 | Features.push_back(x: "+reserve-o4" ); |
| 222 | |
| 223 | if (Args.hasArg(Ids: options::OPT_ffixed_o5)) |
| 224 | Features.push_back(x: "+reserve-o5" ); |
| 225 | |
| 226 | if (Args.hasArg(Ids: options::OPT_ffixed_l0)) |
| 227 | Features.push_back(x: "+reserve-l0" ); |
| 228 | |
| 229 | if (Args.hasArg(Ids: options::OPT_ffixed_l1)) |
| 230 | Features.push_back(x: "+reserve-l1" ); |
| 231 | |
| 232 | if (Args.hasArg(Ids: options::OPT_ffixed_l2)) |
| 233 | Features.push_back(x: "+reserve-l2" ); |
| 234 | |
| 235 | if (Args.hasArg(Ids: options::OPT_ffixed_l3)) |
| 236 | Features.push_back(x: "+reserve-l3" ); |
| 237 | |
| 238 | if (Args.hasArg(Ids: options::OPT_ffixed_l4)) |
| 239 | Features.push_back(x: "+reserve-l4" ); |
| 240 | |
| 241 | if (Args.hasArg(Ids: options::OPT_ffixed_l5)) |
| 242 | Features.push_back(x: "+reserve-l5" ); |
| 243 | |
| 244 | if (Args.hasArg(Ids: options::OPT_ffixed_l6)) |
| 245 | Features.push_back(x: "+reserve-l6" ); |
| 246 | |
| 247 | if (Args.hasArg(Ids: options::OPT_ffixed_l7)) |
| 248 | Features.push_back(x: "+reserve-l7" ); |
| 249 | |
| 250 | if (Args.hasArg(Ids: options::OPT_ffixed_i0)) |
| 251 | Features.push_back(x: "+reserve-i0" ); |
| 252 | |
| 253 | if (Args.hasArg(Ids: options::OPT_ffixed_i1)) |
| 254 | Features.push_back(x: "+reserve-i1" ); |
| 255 | |
| 256 | if (Args.hasArg(Ids: options::OPT_ffixed_i2)) |
| 257 | Features.push_back(x: "+reserve-i2" ); |
| 258 | |
| 259 | if (Args.hasArg(Ids: options::OPT_ffixed_i3)) |
| 260 | Features.push_back(x: "+reserve-i3" ); |
| 261 | |
| 262 | if (Args.hasArg(Ids: options::OPT_ffixed_i4)) |
| 263 | Features.push_back(x: "+reserve-i4" ); |
| 264 | |
| 265 | if (Args.hasArg(Ids: options::OPT_ffixed_i5)) |
| 266 | Features.push_back(x: "+reserve-i5" ); |
| 267 | |
| 268 | if (Args.hasArg(Ids: options::OPT_mfix_gr712rc)) { |
| 269 | Features.push_back(x: "+fix-tn0009" ); |
| 270 | Features.push_back(x: "+fix-tn0011" ); |
| 271 | Features.push_back(x: "+fix-tn0012" ); |
| 272 | Features.push_back(x: "+fix-tn0013" ); |
| 273 | } |
| 274 | |
| 275 | if (Args.hasArg(Ids: options::OPT_mfix_ut700)) { |
| 276 | Features.push_back(x: "+fix-tn0009" ); |
| 277 | Features.push_back(x: "+fix-tn0010" ); |
| 278 | Features.push_back(x: "+fix-tn0013" ); |
| 279 | } |
| 280 | } |
| 281 | |