apazos updated this revision to Diff 142459.
apazos added a comment.
- Simplified hasOtherExtensions() now that we clarified non-standard extensions
are separated by '_'. We just need to find the first occurrence of the prefixes.
- updated error message, removed "unsupported" from some messages.
https://reviews.llvm.org/D45284
Files:
include/clang/Basic/DiagnosticDriverKinds.td
lib/Driver/ToolChains/Arch/RISCV.cpp
test/Driver/riscv-arch.c
Index: test/Driver/riscv-arch.c
===================================================================
--- test/Driver/riscv-arch.c
+++ test/Driver/riscv-arch.c
@@ -1,89 +1,245 @@
-// 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 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 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: unsupported 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: standard user-level extension with version number 'i20'
+
+// 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: standard user-level extension with version number 'c5'
Index: lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- lib/Driver/ToolChains/Arch/RISCV.cpp
+++ lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -20,31 +20,130 @@
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) {
+ // The other extensions have prefix 'sx', 's' or 'x'.
+ // Find the first occurrence of 's' or 'x'.
+ Pos = In.find_first_of("sx");
+ return Pos != StringRef::npos;
+}
+
+static bool isSupportedExtension(StringRef Prefix, StringRef Name) {
+ // LLVM does not support "sx", "s" nor "x" extensions.
+ return false;
+}
+
+static void getExtensionVersion(StringRef &In, std::string &Version) {
+ auto I = In.begin();
+ auto E = In.end();
+
+ while (I != E && isdigit(*I))
+ Version.append(1, *I++);
+}
+
+static void getExtensionFeatures(const Driver &D,
+ const ArgList &Args,
+ std::vector<StringRef> &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<StringRef, 8> 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_invalid_riscv_ext_arch_name)
+ << MArch << "invalid extension prefix" << Ext;
+ return;
+ }
+
+ if (Name.empty()) {
+ std::string Error = Type;
+ Error += " name missing after";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ if (!isSupportedExtension(Prefix, Name)) {
+ std::string Error = "unsupported ";
+ Error += Type;
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ // TODO: Hardware features to be handled in Support/TargetParser.cpp.
+ Features.push_back(Args.MakeArgString("+" + Ext));
+ }
+}
+
void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
std::vector<StringRef> &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;
}
// 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':
+ // Currently LLVM does not support 'e'.
+ D.Diag(diag::err_drv_invalid_riscv_arch_name)
+ << MArch << "unsupported standard user-level extension 'e'";
return;
case 'i':
break;
@@ -60,29 +159,84 @@
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.
+ StringRef OtherExts;
+ size_t Pos;
+ if (hasOtherExtensions(Exts, Pos)) {
+ OtherExts = Exts.substr(Pos);
+ Exts = Exts.substr(0, Pos);
+ }
+
+ // TODO: Handle extension version number.
+ // Standard extensions may have a version number,
+ // separated by '_' e.g.: rv32i2_m2.
+ std::string Version;
+ getExtensionVersion(Exts, Version);
+ if (!Version.empty()) {
+ std::string Ext;
+ Ext.append(1, Baseline);
+ Ext.append(Version);
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch
+ << "unsupported standard user-level extension with version number"
+ << Ext;
+ return;
+ }
+
+ 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;
- return;
+ if (StdExtsItr == StdExtsEnd) {
+ size_t Pos;
+ if (hasExtension(StdExts, std::string(1, c), Pos)) {
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << "standard extension not given in canonical order"
+ << std::string(1, c);
+ return;
+ }
}
// Move to next char to prevent repeated letter.
++StdExtsItr;
+ // TODO: Handle extension version number.
+ // Standard extensions may have a version number,
+ // separated by '_' e.g.: rv32i2_m2.
+ if (std::next(I) != E) {
+ // Skip c.
+ StringRef Next = std::string(std::next(I), E);
+ std::string Version;
+ getExtensionVersion(Next, Version);
+ if (!Version.empty()) {
+ std::string Ext;
+ Ext.append(1, c);
+ Ext.append(Version);
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch
+ << "unsupported standard user-level extension with version number"
+ << Ext;
+ return;
+ }
+ }
+
// 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");
@@ -108,9 +262,12 @@
// 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";
+
+ // TODO: Handle other types of extensions.
+ getExtensionFeatures(D, Args, Features, MArch, OtherExts);
}
}
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_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 "
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits