1 //===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- 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 "RISCV.h" 10 #include "clang/Basic/CharInfo.h" 11 #include "clang/Driver/Driver.h" 12 #include "clang/Driver/DriverDiagnostic.h" 13 #include "clang/Driver/Options.h" 14 #include "llvm/Option/ArgList.h" 15 #include "llvm/Support/TargetParser.h" 16 #include "llvm/Support/raw_ostream.h" 17 #include "ToolChains/CommonArgs.h" 18 19 using namespace clang::driver; 20 using namespace clang::driver::tools; 21 using namespace clang; 22 using namespace llvm::opt; 23 24 static StringRef getExtensionTypeDesc(StringRef Ext) { 25 if (Ext.startswith("sx")) 26 return "non-standard supervisor-level extension"; 27 if (Ext.startswith("s")) 28 return "standard supervisor-level extension"; 29 if (Ext.startswith("x")) 30 return "non-standard user-level extension"; 31 return StringRef(); 32 } 33 34 static StringRef getExtensionType(StringRef Ext) { 35 if (Ext.startswith("sx")) 36 return "sx"; 37 if (Ext.startswith("s")) 38 return "s"; 39 if (Ext.startswith("x")) 40 return "x"; 41 return StringRef(); 42 } 43 44 static bool isSupportedExtension(StringRef Ext) { 45 // LLVM does not support "sx", "s" nor "x" extensions. 46 return false; 47 } 48 49 // Extensions may have a version number, and may be separated by 50 // an underscore '_' e.g.: rv32i2_m2. 51 // Version number is divided into major and minor version numbers, 52 // separated by a 'p'. If the minor version is 0 then 'p0' can be 53 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 54 static bool getExtensionVersion(const Driver &D, StringRef MArch, 55 StringRef Ext, StringRef In, 56 std::string &Major, std::string &Minor) { 57 auto I = In.begin(); 58 auto E = In.end(); 59 60 while (I != E && isDigit(*I)) 61 Major.append(1, *I++); 62 63 if (Major.empty()) 64 return true; 65 66 if (I != E && *I == 'p') { 67 ++I; 68 69 while (I != E && isDigit(*I)) 70 Minor.append(1, *I++); 71 72 // Expected 'p' to be followed by minor version number. 73 if (Minor.empty()) { 74 std::string Error = 75 "minor version number missing after 'p' for extension"; 76 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 77 << MArch << Error << Ext; 78 return false; 79 } 80 } 81 82 // TODO: Handle extensions with version number. 83 std::string Error = "unsupported version number " + Major; 84 if (!Minor.empty()) 85 Error += "." + Minor; 86 Error += " for extension"; 87 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext; 88 89 return false; 90 } 91 92 // Handle other types of extensions other than the standard 93 // general purpose and standard user-level extensions. 94 // Parse the ISA string containing non-standard user-level 95 // extensions, standard supervisor-level extensions and 96 // non-standard supervisor-level extensions. 97 // These extensions start with 'x', 's', 'sx' prefixes, follow a 98 // canonical order, might have a version number (major, minor) 99 // and are separated by a single underscore '_'. 100 // Set the hardware features for the extensions that are supported. 101 static void getExtensionFeatures(const Driver &D, 102 const ArgList &Args, 103 std::vector<StringRef> &Features, 104 StringRef &MArch, StringRef &Exts) { 105 if (Exts.empty()) 106 return; 107 108 // Multi-letter extensions are seperated by a single underscore 109 // as described in RISC-V User-Level ISA V2.2. 110 SmallVector<StringRef, 8> Split; 111 Exts.split(Split, StringRef("_")); 112 113 SmallVector<StringRef, 3> Prefix; 114 Prefix.push_back("x"); 115 Prefix.push_back("s"); 116 Prefix.push_back("sx"); 117 auto I = Prefix.begin(); 118 auto E = Prefix.end(); 119 120 SmallVector<StringRef, 8> AllExts; 121 122 for (StringRef Ext : Split) { 123 124 if (Ext.empty()) { 125 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 126 << "extension name missing after separator '_'"; 127 return; 128 } 129 130 StringRef Type = getExtensionType(Ext); 131 StringRef Name(Ext.substr(Type.size())); 132 StringRef Desc = getExtensionTypeDesc(Ext); 133 134 if (Type.empty()) { 135 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 136 << MArch << "invalid extension prefix" << Ext; 137 return; 138 } 139 140 // Check ISA extensions are specified in the canonical order. 141 while (I != E && *I != Type) 142 ++I; 143 144 if (I == E) { 145 std::string Error = Desc; 146 Error += " not given in canonical order"; 147 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 148 << MArch << Error << Ext; 149 return; 150 } 151 152 // The order is OK, do not advance I to the next prefix 153 // to allow repeated extension type, e.g.: rv32ixabc_xdef. 154 155 if (Name.empty()) { 156 std::string Error = Desc; 157 Error += " name missing after"; 158 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 159 << MArch << Error << Ext; 160 return; 161 } 162 163 std::string Major, Minor; 164 auto Pos = Name.find_if(isDigit); 165 if (Pos != StringRef::npos) { 166 auto Next = Name.substr(Pos); 167 Name = Name.substr(0, Pos); 168 if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor)) 169 return; 170 } 171 172 // Check if duplicated extension. 173 if (llvm::is_contained(AllExts, Ext)) { 174 std::string Error = "duplicated "; 175 Error += Desc; 176 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 177 << MArch << Error << Ext; 178 return; 179 } 180 181 // Extension format is correct, keep parsing the extensions. 182 // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 183 AllExts.push_back(Ext); 184 } 185 186 // Set target features. 187 // TODO: Hardware features to be handled in Support/TargetParser.cpp. 188 // TODO: Use version number when setting target features. 189 for (auto Ext : AllExts) { 190 if (!isSupportedExtension(Ext)) { 191 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 192 std::string Error = "unsupported "; 193 Error += Desc; 194 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 195 << MArch << Error << Ext; 196 return; 197 } 198 Features.push_back(Args.MakeArgString("+" + Ext)); 199 } 200 } 201 202 void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, 203 std::vector<StringRef> &Features) { 204 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 205 StringRef MArch = A->getValue(); 206 207 // RISC-V ISA strings must be lowercase. 208 if (std::any_of(std::begin(MArch), std::end(MArch), 209 [](char c) { return isupper(c); })) { 210 211 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 212 << "string must be lowercase"; 213 return; 214 } 215 216 // ISA string must begin with rv32 or rv64. 217 if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || 218 (MArch.size() < 5)) { 219 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 220 << "string must begin with rv32{i,e,g} or rv64{i,g}"; 221 return; 222 } 223 224 bool HasRV64 = MArch.startswith("rv64") ? true : false; 225 226 // The canonical order specified in ISA manual. 227 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 228 StringRef StdExts = "mafdqlcbjtpvn"; 229 bool HasF = false, HasD = false; 230 char Baseline = MArch[4]; 231 232 // First letter should be 'e', 'i' or 'g'. 233 switch (Baseline) { 234 default: 235 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 236 << "first letter should be 'e', 'i' or 'g'"; 237 return; 238 case 'e': { 239 StringRef Error; 240 // Currently LLVM does not support 'e'. 241 // Extension 'e' is not allowed in rv64. 242 if (HasRV64) 243 Error = "standard user-level extension 'e' requires 'rv32'"; 244 else 245 Error = "unsupported standard user-level extension 'e'"; 246 D.Diag(diag::err_drv_invalid_riscv_arch_name) 247 << MArch << Error; 248 return; 249 } 250 case 'i': 251 break; 252 case 'g': 253 // g = imafd 254 StdExts = StdExts.drop_front(4); 255 Features.push_back("+m"); 256 Features.push_back("+a"); 257 Features.push_back("+f"); 258 Features.push_back("+d"); 259 HasF = true; 260 HasD = true; 261 break; 262 } 263 264 // Skip rvxxx 265 StringRef Exts = MArch.substr(5); 266 267 // Remove non-standard extensions and supervisor-level extensions. 268 // They have 'x', 's', 'sx' prefixes. Parse them at the end. 269 // Find the very first occurrence of 's' or 'x'. 270 StringRef OtherExts; 271 size_t Pos = Exts.find_first_of("sx"); 272 if (Pos != StringRef::npos) { 273 OtherExts = Exts.substr(Pos); 274 Exts = Exts.substr(0, Pos); 275 } 276 277 std::string Major, Minor; 278 if (!getExtensionVersion(D, MArch, std::string(1, Baseline), 279 Exts, Major, Minor)) 280 return; 281 282 // TODO: Use version number when setting target features 283 // and consume the underscore '_' that might follow. 284 285 auto StdExtsItr = StdExts.begin(); 286 auto StdExtsEnd = StdExts.end(); 287 288 for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { 289 char c = *I; 290 291 // Check ISA extensions are specified in the canonical order. 292 while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) 293 ++StdExtsItr; 294 295 if (StdExtsItr == StdExtsEnd) { 296 // Either c contains a valid extension but it was not given in 297 // canonical order or it is an invalid extension. 298 StringRef Error; 299 if (StdExts.contains(c)) 300 Error = "standard user-level extension not given in canonical order"; 301 else 302 Error = "invalid standard user-level extension"; 303 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 304 << MArch << Error << std::string(1, c); 305 return; 306 } 307 308 // Move to next char to prevent repeated letter. 309 ++StdExtsItr; 310 311 if (std::next(I) != E) { 312 // Skip c. 313 std::string Next = std::string(std::next(I), E); 314 std::string Major, Minor; 315 if (!getExtensionVersion(D, MArch, std::string(1, c), 316 Next, Major, Minor)) 317 return; 318 319 // TODO: Use version number when setting target features 320 // and consume the underscore '_' that might follow. 321 } 322 323 // The order is OK, then push it into features. 324 switch (c) { 325 default: 326 // Currently LLVM supports only "mafdc". 327 D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) 328 << MArch << "unsupported standard user-level extension" 329 << std::string(1, c); 330 return; 331 case 'm': 332 Features.push_back("+m"); 333 break; 334 case 'a': 335 Features.push_back("+a"); 336 break; 337 case 'f': 338 Features.push_back("+f"); 339 HasF = true; 340 break; 341 case 'd': 342 Features.push_back("+d"); 343 HasD = true; 344 break; 345 case 'c': 346 Features.push_back("+c"); 347 break; 348 } 349 } 350 351 // Dependency check. 352 // It's illegal to specify the 'd' (double-precision floating point) 353 // extension without also specifying the 'f' (single precision 354 // floating-point) extension. 355 if (HasD && !HasF) 356 D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch 357 << "d requires f extension to also be specified"; 358 359 // Additional dependency checks. 360 // TODO: The 'q' extension requires rv64. 361 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. 362 363 // Handle all other types of extensions. 364 getExtensionFeatures(D, Args, Features, MArch, OtherExts); 365 } 366 367 // -mrelax is default, unless -mno-relax is specified. 368 bool Relax = true; 369 if (auto *A = Args.getLastArg(options::OPT_mrelax, options::OPT_mno_relax)) { 370 if (A->getOption().matches(options::OPT_mno_relax)) { 371 Relax = false; 372 Features.push_back("-relax"); 373 } 374 } 375 376 if (Relax) 377 Features.push_back("+relax"); 378 379 // Now add any that the user explicitly requested on the command line, 380 // which may override the defaults. 381 handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group); 382 } 383 384 StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { 385 if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) 386 return A->getValue(); 387 388 return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; 389 } 390