Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ 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_unsupported_riscv_ext_arch_name : Error< + "invalid arch name '%0', unsupported %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: lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- lib/Driver/ToolChains/Arch/RISCV.cpp +++ lib/Driver/ToolChains/Arch/RISCV.cpp @@ -20,6 +20,113 @@ using namespace clang; using namespace llvm::opt; +static bool hasExtension(StringRef In, StringRef Ext, size_t &Pos) { + Pos = In.find(Ext); + return Pos != StringRef::npos; +} + +static StringRef getExtensionPrefix(StringRef Ext) { + if (Ext.startswith("sx")) + return "sx"; + if (Ext.startswith("s")) + return "s"; + if (Ext.startswith("x")) + return "x"; + return StringRef(); +} + +static bool hasOtherExtensions(StringRef In, size_t &Pos) { + size_t PosSX, PosS, PosX; + Pos = PosSX = PosS = PosX = StringRef::npos; + + bool Found = hasExtension(In, "sx", PosSX); + Found |= hasExtension(In, "s", PosS); + Found |= hasExtension(In, "x", PosX); + + if (!Found) + return false; + + auto getMinPos = [](size_t &Pos, size_t &minPos) { + if (Pos == StringRef::npos) + return; + if (minPos == StringRef::npos) { + minPos = Pos; + return; + } + minPos = std::min(minPos, Pos); + }; + + getMinPos(PosSX, Pos); + getMinPos(PosS, Pos); + getMinPos(PosX, Pos); + + assert(Pos != StringRef::npos && "Expected an unsupported extension!"); + + return true; +} + +// TODO: Hardware features to be handled in Support/TargetParser.cpp. +static bool isSupportedExtension(std::vector &Features, + StringRef Prefix, StringRef Name) { + return false; +} + +static void getExtensionFeatures(const Driver &D, + 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("_"), -1, false); + + for (StringRef Ext : Split) { + StringRef Prefix = getExtensionPrefix(Ext); + StringRef Name(Ext.substr(Prefix.size())); + + StringRef Type; + if (Prefix == "sx") + Type = "non-standard supervisor-level extension"; + else if (Prefix == "s") + Type = "standard supervisor-level extension"; + else if (Prefix == "x") + Type = "non-standard user-level extension"; + else { + Type = "invalid extension prefix"; + D.Diag(diag::err_drv_unsupported_riscv_ext_arch_name) + << MArch << Type << Ext; + return; + } + + size_t Pos; + if (hasOtherExtensions(Name, Pos)) { + std::string Error = "_"; + Error += Name.substr(Pos); + D.Diag(diag::err_drv_unsupported_riscv_ext_arch_name) + << MArch + << "multi-letter extensions, separate by a single underscore" + << Error; + return; + } + + if (Name.empty()) { + std::string Error = Type; + Error += " name missing"; + D.Diag(diag::err_drv_unsupported_riscv_ext_arch_name) + << MArch << Error << Ext; + return; + } + + if (!isSupportedExtension(Features, Prefix, Name)) { + D.Diag(diag::err_drv_unsupported_riscv_ext_arch_name) + << MArch << Type << Ext; + return; + } + } +} + void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, std::vector &Features) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { @@ -27,14 +134,14 @@ 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 or rv64"; return; } // 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]; @@ -43,8 +150,8 @@ 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 'i': break; @@ -61,17 +168,31 @@ } auto StdExtsItr = StdExts.begin(); + // Skip rvxxx StringRef Exts = MArch.substr(5); + // Remove non-standard extensions (user-level and supervisor-level) and + // supervisor-level extensions to parse them at the end. + StringRef OtherExts; + size_t Pos; + if (hasOtherExtensions(Exts, Pos)) { + OtherExts = Exts.substr(Pos); + Exts = Exts.substr(0, Pos); + } + for (char c : Exts) { // Check ISA extensions are specified in the canonical order. while (StdExtsItr != StdExts.end() && *StdExtsItr != c) ++StdExtsItr; if (StdExtsItr == StdExts.end()) { - // TODO: Improve diagnostic message. - D.Diag(diag::err_drv_invalid_arch_name) << MArch; + size_t Pos; + StringRef Error = "standard user-level extension"; + if (hasExtension(StdExts, std::string(1, c), Pos)) + Error = "canonical order of extension"; + D.Diag(diag::err_drv_unsupported_riscv_ext_arch_name) + << MArch << Error << std::string(1, c); return; } @@ -81,8 +202,10 @@ // 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_unsupported_riscv_ext_arch_name) + << MArch << "standard user-level extension" + << std::string(1, c); return; case 'm': Features.push_back("+m"); @@ -108,9 +231,11 @@ // 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"; + + getExtensionFeatures(D, Features, MArch, OtherExts); } } Index: test/Driver/riscv-arch.c =================================================================== --- test/Driver/riscv-arch.c +++ test/Driver/riscv-arch.c @@ -1,89 +1,229 @@ -// 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=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 or rv64 + +// RUN: %clang -target riscv32-unknown-elf -march=rv32e -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-LETTER %s +// RV32-LETTER: error: invalid arch name 'rv32e', +// 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: unsupported canonical order of extension 'q' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32imC -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STD-INVAL %s +// RV32-STD-INVAL: error: invalid arch name 'rv32imC', +// RV32-STD-INVAL: unsupported standard user-level extension 'C' + +// 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', unsupported +// RV32X-NAME: non-standard user-level extension name missing '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: unsupported non-standard supervisor-level extension +// RV32SX-NAME: name missing '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:unsupported standard supervisor-level extension name missing '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: unsupported non-standard user-level extension name missing '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=rv32ixabcslw -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32ALL-SEP %s +// RV32ALL-SEP: error: invalid arch name 'rv32ixabcslw', +// RV32ALL-SEP: unsupported multi-letter extensions, separate by +// RV32ALL-SEP: a single underscore '_slw'