Index: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td @@ -24,6 +24,10 @@ def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_invalid_riscv_arch_name : Error< + "invalid arch name '%0', %1">; +def err_drv_invalid_riscv_ext_arch_name : Error< + "invalid arch name '%0', %1 '%2'">; def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">; def err_drv_no_cuda_installation : Error< "cannot find CUDA installation. Provide its path via --cuda-path, or pass " Index: cfe/trunk/lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains/Arch/RISCV.cpp +++ cfe/trunk/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -20,32 +20,232 @@ using namespace clang; using namespace llvm::opt; +static StringRef getExtensionTypeDesc(StringRef Ext) { + if (Ext.startswith("sx")) + return "non-standard supervisor-level extension"; + if (Ext.startswith("s")) + return "standard supervisor-level extension"; + if (Ext.startswith("x")) + return "non-standard user-level extension"; + return StringRef(); +} + +static StringRef getExtensionType(StringRef Ext) { + if (Ext.startswith("sx")) + return "sx"; + if (Ext.startswith("s")) + return "s"; + if (Ext.startswith("x")) + return "x"; + return StringRef(); +} + +static bool isSupportedExtension(StringRef Ext) { + // LLVM does not support "sx", "s" nor "x" extensions. + return false; +} + +// Extensions may have a version number, and may be separated by +// an underscore '_' e.g.: rv32i2_m2. +// Version number is divided into major and minor version numbers, +// separated by a 'p'. If the minor version is 0 then 'p0' can be +// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. +static bool getExtensionVersion(const Driver &D, StringRef MArch, + StringRef Ext, StringRef In, + std::string &Major, std::string &Minor) { + auto I = In.begin(); + auto E = In.end(); + + while (I != E && isdigit(*I)) + Major.append(1, *I++); + + if (Major.empty()) + return true; + + if (I != E && *I == 'p') { + ++I; + + while (I != E && isdigit(*I)) + Minor.append(1, *I++); + + // Expected 'p' to be followed by minor version number. + if (Minor.empty()) { + std::string Error = + "minor version number missing after 'p' for extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } + } + + // TODO: Handle extensions with version number. + std::string Error = "unsupported version number " + Major; + if (!Minor.empty()) + Error += "." + Minor; + Error += " for extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext; + + return false; +} + +// Handle other types of extensions other than the standard +// general purpose and standard user-level extensions. +// Parse the ISA string containing non-standard user-level +// extensions, standard supervisor-level extensions and +// non-standard supervisor-level extensions. +// These extensions start with 'x', 's', 'sx' prefixes, follow a +// canonical order, might have a version number (major, minor) +// and are separated by a single underscore '_'. +// Set the hardware features for the extensions that are supported. +static void getExtensionFeatures(const Driver &D, + const ArgList &Args, + std::vector &Features, + StringRef &MArch, StringRef &Exts) { + if (Exts.empty()) + return; + + // Multi-letter extensions are seperated by a single underscore + // as described in RISC-V User-Level ISA V2.2. + SmallVector Split; + Exts.split(Split, StringRef("_")); + + SmallVector Prefix; + Prefix.push_back("x"); + Prefix.push_back("s"); + Prefix.push_back("sx"); + auto I = Prefix.begin(); + auto E = Prefix.end(); + + SmallVector AllExts; + + for (StringRef Ext : Split) { + + if (Ext.empty()) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch + << "extension name missing after separator '_'"; + return; + } + + StringRef Type = getExtensionType(Ext); + StringRef Name(Ext.substr(Type.size())); + StringRef Desc = getExtensionTypeDesc(Ext); + + if (Type.empty()) { + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << "invalid extension prefix" << Ext; + return; + } + + // Check ISA extensions are specified in the canonical order. + while (I != E && *I != Type) + ++I; + + if (I == E) { + std::string Error = Desc; + Error += " not given in canonical order"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return; + } + + // The order is OK, do not advance I to the next prefix + // to allow repeated extension type, e.g.: rv32ixabc_xdef. + + if (Name.empty()) { + std::string Error = Desc; + Error += " name missing after"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return; + } + + std::string Major, Minor; + auto Pos = Name.find_if(std::isdigit); + if (Pos != StringRef::npos) { + auto Next = Name.substr(Pos); + Name = Name.substr(0, Pos); + if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor)) + return; + } + + // Check if duplicated extension. + if (std::find(AllExts.begin(), AllExts.end(), Ext) != AllExts.end()) { + std::string Error = "duplicated "; + Error += Desc; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return; + } + + // Extension format is correct, keep parsing the extensions. + // TODO: Save Type, Name, Major, Minor to avoid parsing them later. + AllExts.push_back(Ext); + } + + // Set target features. + // TODO: Hardware features to be handled in Support/TargetParser.cpp. + // TODO: Use version number when setting target features. + for (auto Ext : AllExts) { + if (!isSupportedExtension(Ext)) { + StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); + std::string Error = "unsupported "; + Error += Desc; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return; + } + Features.push_back(Args.MakeArgString("+" + Ext)); + } +} + void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { StringRef MArch = A->getValue(); + + // RISC-V ISA strings must be lowercase. + if (std::any_of(std::begin(MArch), std::end(MArch), + [](char c) { return isupper(c); })) { + + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch + << "string must be lowercase"; + return; + } + + // ISA string must begin with rv32 or rv64. if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || (MArch.size() < 5)) { - // ISA string must begin with rv32 or rv64. - // TODO: Improve diagnostic message. - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch + << "string must begin with rv32{i,e,g} or rv64{i,g}"; return; } + bool HasRV64 = MArch.startswith("rv64") ? true : false; + // The canonical order specified in ISA manual. // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 - StringRef StdExts = "mafdc"; - + StringRef StdExts = "mafdqlcbjtpvn"; bool HasF = false, HasD = false; char Baseline = MArch[4]; - // TODO: Add 'e' once backend supported. + // First letter should be 'e', 'i' or 'g'. switch (Baseline) { default: - // First letter should be 'e', 'i' or 'g'. - // TODO: Improve diagnostic message. - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch + << "first letter should be 'e', 'i' or 'g'"; return; + case 'e': { + StringRef Error; + // Currently LLVM does not support 'e'. + // Extension 'e' is not allowed in rv64. + if (HasRV64) + Error = "standard user-level extension 'e' requires 'rv32'"; + else + Error = "unsupported standard user-level extension 'e'"; + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << Error; + return; + } case 'i': break; case 'g': @@ -60,29 +260,72 @@ break; } - auto StdExtsItr = StdExts.begin(); // Skip rvxxx StringRef Exts = MArch.substr(5); - for (char c : Exts) { + // Remove non-standard extensions and supervisor-level extensions. + // They have 'x', 's', 'sx' prefixes. Parse them at the end. + // Find the very first occurrence of 's' or 'x'. + StringRef OtherExts; + size_t Pos = Exts.find_first_of("sx"); + if (Pos != StringRef::npos) { + OtherExts = Exts.substr(Pos); + Exts = Exts.substr(0, Pos); + } + + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, Baseline), + Exts, Major, Minor)) + return; + + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + + auto StdExtsItr = StdExts.begin(); + auto StdExtsEnd = StdExts.end(); + + for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { + char c = *I; + // Check ISA extensions are specified in the canonical order. - while (StdExtsItr != StdExts.end() && *StdExtsItr != c) + while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) ++StdExtsItr; - if (StdExtsItr == StdExts.end()) { - // TODO: Improve diagnostic message. - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + if (StdExtsItr == StdExtsEnd) { + // Either c contains a valid extension but it was not given in + // canonical order or it is an invalid extension. + StringRef Error; + if (StdExts.contains(c)) + Error = "standard user-level extension not given in canonical order"; + else + Error = "invalid standard user-level extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << std::string(1, c); return; } // Move to next char to prevent repeated letter. ++StdExtsItr; + if (std::next(I) != E) { + // Skip c. + std::string Next = std::string(std::next(I), E); + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, c), + Next, Major, Minor)) + return; + + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + } + // The order is OK, then push it into features. switch (c) { default: - // TODO: Improve diagnostic message. - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + // Currently LLVM supports only "mafdc". + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << "unsupported standard user-level extension" + << std::string(1, c); return; case 'm': Features.push_back("+m"); @@ -104,13 +347,20 @@ } } - // Dependency check + // Dependency check. // It's illegal to specify the 'd' (double-precision floating point) // extension without also specifying the 'f' (single precision // floating-point) extension. - // TODO: Improve diagnostic message. if (HasD && !HasF) - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch + << "d requires f extension to also be specified"; + + // Additional dependency checks. + // TODO: The 'q' extension requires rv64. + // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. + + // Handle all other types of extensions. + getExtensionFeatures(D, Args, Features, MArch, OtherExts); } } Index: cfe/trunk/test/Driver/riscv-arch.c =================================================================== --- cfe/trunk/test/Driver/riscv-arch.c +++ cfe/trunk/test/Driver/riscv-arch.c @@ -1,89 +1,317 @@ -// RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32ima -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imafd -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv32-unknown-elf -march=rv32ic -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imac -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imafc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32imafdc -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv32-unknown-elf -march=rv32ia -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32iaf -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32iafd -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv32-unknown-elf -march=rv32iac -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32iafc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32iafdc -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv32-unknown-elf -march=rv32g -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv32-unknown-elf -march=rv32gc -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64im -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64ima -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imaf -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imafd -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv64-unknown-elf -march=rv64ic -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imac -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imafc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64imafdc -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv64-unknown-elf -march=rv64ia -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64iaf -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64iafd -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv64-unknown-elf -march=rv64iac -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64iafc -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64iafdc -### %s -fsyntax-only 2>&1 | FileCheck %s - -// RUN: %clang -target riscv64-unknown-elf -march=rv64g -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang -target riscv64-unknown-elf -march=rv64gc -### %s -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32ima -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imafd -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ic -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imac -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imafc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imafdc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ia -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32iaf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32iafd -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv32-unknown-elf -march=rv32iac -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32iafc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32iafdc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv32-unknown-elf -march=rv32g -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32gc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64im -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64ima -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imaf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imafd -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv64-unknown-elf -march=rv64ic -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imac -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imafc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imafdc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv64-unknown-elf -march=rv64ia -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64iaf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64iafd -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv64-unknown-elf -march=rv64iac -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64iafc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64iafdc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s + +// RUN: %clang -target riscv64-unknown-elf -march=rv64g -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64gc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck %s // CHECK-NOT: error: invalid arch name ' -// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32 %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32 %s // RV32: error: invalid arch name 'rv32' -// RUN: %clang -target riscv32-unknown-elf -march=rv32m -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32M %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32m -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32M %s // RV32M: error: invalid arch name 'rv32m' -// RUN: %clang -target riscv32-unknown-elf -march=rv32id -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ID %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32id -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ID %s // RV32ID: error: invalid arch name 'rv32id' -// RUN: %clang -target riscv32-unknown-elf -march=rv32l -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32L %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32l -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32L %s // RV32L: error: invalid arch name 'rv32l' -// RUN: %clang -target riscv32-unknown-elf -march=rv32imadf -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMADF %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imadf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMADF %s // RV32IMADF: error: invalid arch name 'rv32imadf' -// RUN: %clang -target riscv32-unknown-elf -march=rv32imm -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMM %s +// RUN: %clang -target riscv32-unknown-elf -march=rv32imm -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32IMM %s // RV32IMM: error: invalid arch name 'rv32imm' -// RUN: %clang -target riscv32-unknown-elf -march=RV32I -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32I-UPPER %s +// RUN: %clang -target riscv32-unknown-elf -march=RV32I -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32I-UPPER %s // RV32I-UPPER: error: invalid arch name 'RV32I' -// RUN: %clang -target riscv64-unknown-elf -march=rv64 -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64 %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64 %s // RV64: error: invalid arch name 'rv64' -// RUN: %clang -target riscv64-unknown-elf -march=rv64m -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64M %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64m -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64M %s // RV64M: error: invalid arch name 'rv64m' -// RUN: %clang -target riscv64-unknown-elf -march=rv64id -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64ID %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64id -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64ID %s // RV64ID: error: invalid arch name 'rv64id' -// RUN: %clang -target riscv64-unknown-elf -march=rv64l -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64L %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64l -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64L %s // RV64L: error: invalid arch name 'rv64l' -// RUN: %clang -target riscv64-unknown-elf -march=rv64imadf -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMADF %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imadf -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMADF %s // RV64IMADF: error: invalid arch name 'rv64imadf' -// RUN: %clang -target riscv64-unknown-elf -march=rv64imm -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMM %s +// RUN: %clang -target riscv64-unknown-elf -march=rv64imm -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64IMM %s // RV64IMM: error: invalid arch name 'rv64imm' -// RUN: %clang -target riscv64-unknown-elf -march=RV64I -### %s -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64I-UPPER %s +// RUN: %clang -target riscv64-unknown-elf -march=RV64I -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64I-UPPER %s // RV64I-UPPER: error: invalid arch name 'RV64I' + + +// Testing specific messages and unsupported extensions. + +// RUN: %clang -target riscv32-unknown-elf -march=rv32e -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32E %s +// RV32E: error: invalid arch name 'rv32e', +// RV32E: standard user-level extension 'e' + +// RUN: %clang -target riscv64-unknown-elf -march=rv64e -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64E %s +// RV64E: error: invalid arch name 'rv64e', +// RV64E: standard user-level extension 'e' requires 'rv32' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imC -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LOWER %s +// RV32-LOWER: error: invalid arch name 'rv32imC', +// RV32-LOWER: string must be lowercase + +// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STR %s +// RV32-STR: error: invalid arch name 'rv32', +// RV32-STR: string must begin with rv32{i,e,g} or rv64{i,g} + +// RUN: %clang -target riscv32-unknown-elf -march=rv32q -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LETTER %s +// RV32-LETTER: error: invalid arch name 'rv32q', +// RV32-LETTER: first letter should be 'e', 'i' or 'g' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imcq -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ORDER %s +// RV32-ORDER: error: invalid arch name 'rv32imcq', +// RV32-ORDER: standard user-level extension not given in canonical order 'q' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imw -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD-INVAL %s +// RV32-STD-INVAL: error: invalid arch name 'rv32imw', +// RV32-STD-INVAL: invalid standard user-level extension 'w' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imqc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD %s +// RV32-STD: error: invalid arch name 'rv32imqc', +// RV32-STD: unsupported standard user-level extension 'q' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32xabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X %s +// RV32X: error: invalid arch name 'rv32xabc', +// RV32X: first letter should be 'e', 'i' or 'g' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32sxabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX %s +// RV32SX: error: invalid arch name 'rv32sxabc', +// RV32SX: first letter should be 'e', 'i' or 'g' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32sabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S %s +// RV32S: error: invalid arch name 'rv32sabc', +// RV32S: first letter should be 'e', 'i' or 'g' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ix -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X-NAME %s +// RV32X-NAME: error: invalid arch name 'rv32ix', +// RV32X-NAME: non-standard user-level extension name missing after 'x' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isx -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX-NAME %s +// RV32SX-NAME: error: invalid arch name 'rv32isx', +// RV32SX-NAME: non-standard supervisor-level extension +// RV32SX-NAME: name missing after 'sx' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32is -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S-NAME %s +// RV32S-NAME: error: invalid arch name 'rv32is', +// RV32S-NAME: standard supervisor-level extension +// RV32S-NAME: name missing after 's' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ix_s_sx -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ALL-NAME %s +// RV32ALL-NAME: error: invalid arch name 'rv32ix_s_sx', +// RV32ALL-NAME: non-standard user-level extension +// RV32ALL-NAME: name missing after 'x' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32X-UNS %s +// RV32X-UNS: error: invalid arch name 'rv32ixabc', +// RV32X-UNS: unsupported non-standard user-level extension 'xabc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isa -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32S-UNS %s +// RV32S-UNS: error: invalid arch name 'rv32isa', +// RV32S-UNS: unsupported standard supervisor-level extension 'sa' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isxabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32SX-UNS %s +// RV32SX-UNS: error: invalid arch name 'rv32isxabc', +// RV32SX-UNS: unsupported non-standard supervisor-level extension 'sxabc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_sp_sxlw -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ALL %s +// RV32ALL: error: invalid arch name 'rv32ixabc_sp_sxlw', +// RV32ALL: unsupported non-standard user-level extension 'xabc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32i20 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IVER %s +// RV32-IVER: error: invalid arch name 'rv32i20', unsupported +// RV32-IVER: version number 20 for extension 'i' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imc5 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-CVER %s +// RV32-CVER: error: invalid arch name 'rv32imc5', unsupported +// RV32-CVER: version number 5 for extension 'c' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR-MISS %s +// RV32-IMINOR-MISS: error: invalid arch name 'rv32i2p', +// RV32-IMINOR-MISS: minor version number missing after 'p' for extension 'i' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p0 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR0 %s +// RV32-IMINOR0: error: invalid arch name 'rv32i2p0', +// RV32-IMINOR0: unsupported version number 2.0 for extension 'i' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32i2p1 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-IMINOR1 %s +// RV32-IMINOR1: error: invalid arch name 'rv32i2p1', unsupported +// RV32-IMINOR1: version number 2.1 for extension 'i' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ix2p -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XMINOR-MISS %s +// RV32-XMINOR-MISS: error: invalid arch name 'rv32ix2p', +// RV32-XMINOR-MISS: minor version number missing after 'p' for extension 'x2p' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32is2p0 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-SMINOR0 %s +// RV32-SMINOR0: error: invalid arch name 'rv32is2p0', +// RV32-SMINOR0: unsupported version number 2.0 for extension 's2p0' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isx2p1 -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-SXMINOR1 %s +// RV32-SXMINOR1: error: invalid arch name 'rv32isx2p1', unsupported +// RV32-SXMINOR1: version number 2.1 for extension 'sx2p1' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_ -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XSEP %s +// RV32-XSEP: error: invalid arch name 'rv32ixabc_', +// RV32-XSEP: extension name missing after separator '_' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_a -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-PREFIX %s +// RV32-PREFIX: error: invalid arch name 'rv32ixabc_a', +// RV32-PREFIX: invalid extension prefix 'a' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isabc_xdef -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-ORDER %s +// RV32-X-ORDER: error: invalid arch name 'rv32isabc_xdef', +// RV32-X-ORDER: non-standard user-level extension not given +// RV32-X-ORDER: in canonical order 'xdef' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32isxabc_sdef -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-S-ORDER %s +// RV32-S-ORDER: error: invalid arch name 'rv32isxabc_sdef', +// RV32-S-ORDER: standard supervisor-level extension not given +// RV32-S-ORDER: in canonical order 'sdef' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_xabc -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XDUP %s +// RV32-XDUP: error: invalid arch name 'rv32ixabc_xabc', +// RV32-XDUP: duplicated non-standard user-level extension 'xabc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_xdef -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-X-INVAL %s +// RV32-X-X-INVAL: error: invalid arch name 'rv32ixabc_xdef', unsupported +// RV32-X-X-INVAL: non-standard user-level extension 'xabc' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixabc_sdef_sxghi -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-X-S-SX-INVAL %s +// RV32-X-S-SX-INVAL: error: invalid arch name 'rv32ixabc_sdef_sxghi', +// RV32-X-S-SX-INVAL: unsupported non-standard user-level extension 'xabc'