diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -541,3 +541,14 @@ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-D-ZDINX-ER %s // RV32-D-ZDINX-ER: error: invalid arch name 'rv32idzdinx', // RV32-D-ZFINX-ER: 'f' and 'zfinx' extensions are incompatible + +// RUN: %clang --target=riscv32-unknown-elf -march=rv32ef -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EF-BADVARS %s +// RV32-EF-BADVARS: error: invalid arch name 'rv32ef', +// RV32-EF-BADVARS: 'e' extension is incompatible with 'f' extension + +// RUN: %clang --target=riscv32-unknown-elf -march=rv32ed -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ED-BADVARS %s +// RV32-ED-BADVARS: error: invalid arch name 'rv32ed', +// RV32-ED-BADVARS: 'e' extension is incompatible with 'f' extension and 'd' extension + diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -895,6 +895,7 @@ Error RISCVISAInfo::checkDependency() { bool HasC = Exts.count("c") != 0; bool HasF = Exts.count("f") != 0; + bool HasD = Exts.count("d") != 0; bool HasZfinx = Exts.count("zfinx") != 0; bool HasVector = Exts.count("zve32x") != 0; bool HasZvl = MinVLen != 0; @@ -931,7 +932,7 @@ errc::invalid_argument, "'zvknhb' requires 'v' or 'zve64*' extension to also be specified"); - if ((HasZcmt || Exts.count("zcmp")) && Exts.count("d") && + if ((HasZcmt || Exts.count("zcmp")) && HasD && (HasC || Exts.count("zcd"))) return createStringError( errc::invalid_argument, @@ -944,8 +945,17 @@ "'zcf' is only supported for 'rv32'"); // Additional dependency checks. - // TODO: The 'q' extension requires rv64. - // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. + // The 'q' extension requires rv64. + if (XLen != 64 && Exts.count("q")) + return createStringError(errc::invalid_argument, + "'q' extension is only supported for 'rv64'"); + + // It is illegal to specify 'e' extensions with 'f' and 'd'. + if (Exts.count("e") && (HasF || HasD)) + return createStringError( + errc::invalid_argument, + Twine("'e' extension is incompatible with ") + + (HasD ? "'f' extension and 'd' extension" : "'f' extension")); return Error::success(); } diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp --- a/llvm/unittests/Support/RISCVISAInfoTest.cpp +++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp @@ -474,6 +474,17 @@ EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), "'zcf' is only supported for 'rv32'"); } + + for (StringRef Input : {"rv64efd", "rv32efd", "rv64ed", "rv32ed"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "'e' extension is incompatible with 'f' extension" + " and 'd' extension"); + } + + for (StringRef Input : {"rv64ef", "rv32ef"}) { + EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), + "'e' extension is incompatible with 'f' extension"); + } } TEST(ToFeatureVector, IIsDroppedAndExperimentalExtensionsArePrefixed) {