simoncook created this revision. simoncook added reviewers: asb, lenary, PaoloS, s.egerton. Herald added subscribers: cfe-commits, luismarques, apazos, sameer.abuasal, pzheng, Jim, benna, psnobl, jocewei, PkmX, rkruppe, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, MaskRay, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, johnrusso, rbar. Herald added a project: clang. simoncook added a parent revision: D65649: [RISCV] Add MC encodings and tests of the Bit Manipulation extension.
This adds support for enabling experimental/unratified RISC-V ISA extensions in the -march string in the case where an explicit version number has been declared, and the -menable-experimental-extensions flag has been provided. This follows the design as discussed on the mailing lists in the following RFC: http://lists.llvm.org/pipermail/llvm-dev/2020-January/138364.html Since the RISCV ToolChain definition currently rejects any extension with an explicit version number, the parsing logic has been tweaked to support this, and to allow standard extensions to have their versions checked in future patches. Support for the bitmanip 'b' extension has been added as a first example, it should be clear how to extend this should vector 'v' land first. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D73891 Files: clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Arch/RISCV.cpp clang/test/Driver/riscv-arch.c
Index: clang/test/Driver/riscv-arch.c =================================================================== --- clang/test/Driver/riscv-arch.c +++ clang/test/Driver/riscv-arch.c @@ -327,3 +327,22 @@ // RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s \ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64-TARGET %s // RV64-TARGET: "-triple" "riscv64-unknown-unknown-elf" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ib -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOFLAG %s +// RV32-EXPERIMENTAL-NOFLAG: error: invalid arch name 'rv32ib' +// RV32-EXPERIMENTAL-NOFLAG: requires '-menable-experimental-extensions' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ib -menable-experimental-extensions -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOVERS %s +// RV32-EXPERIMENTAL-NOVERS: error: invalid arch name 'rv32ib' +// RV32-EXPERIMENTAL-NOVERS: experimental extension requires explicit version number + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ib0p1 -menable-experimental-extensions -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-BADVERS %s +// RV32-EXPERIMENTAL-BADVERS: error: invalid arch name 'rv32ib0p1' +// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.1 for experimental extension + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ib0p92 -menable-experimental-extensions -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-GOODVERS %s +// RV32-EXPERIMENTAL-GOODVERS: "-target-feature" "+b" Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -47,20 +47,32 @@ return false; } +static bool isExperimentalExtension(StringRef Ext) { + // Currently 'b' is the only supported experimental extension + if (Ext == "b") + return true; + return false; +} + +static std::pair<StringRef, StringRef> +getExperimentalExtensionVersion(StringRef Ext) { + if (Ext == "b") + return {"0", "92"}; + return {"", ""}; +} + // 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, +static bool getExtensionVersion(const Driver &D, const ArgList &Args, + StringRef MArch, StringRef Ext, StringRef In, std::string &Major, std::string &Minor) { Major = std::string(In.take_while(isDigit)); In = In.substr(Major.size()); - if (Major.empty()) - return true; - if (In.consume_front("p")) { + if (Major.size() && In.consume_front("p")) { Minor = std::string(In.take_while(isDigit)); In = In.substr(Major.size()); @@ -74,7 +86,43 @@ } } - // TODO: Handle extensions with version number. + // If experimental extension, require use of current version number number + if (isExperimentalExtension(Ext)) { + if (!Args.hasArg(options::OPT_menable_experimental_extensions)) { + std::string Error = + "requires '-menable-experimental-extensions' for experimental extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } else if (Major.empty() && Minor.empty()) { + std::string Error = + "experimental extension requires explicit version number"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } + auto SupportedVers = getExperimentalExtensionVersion(Ext); + if (Major != SupportedVers.first || Minor != SupportedVers.second) { + std::string Error = + "unsupported version number " + Major; + if (!Minor.empty()) + Error += "." + Minor; + Error += " for experimental extension (this compiler supports " + + SupportedVers.first.str() + "." + + SupportedVers.second.str() + ")"; + + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } + return true; + } + + // Allow extensions to declare no version number + if (Major.empty() && Minor.empty()) + return true; + + // TODO: Handle supported extensions with version number. std::string Error = "unsupported version number " + Major; if (!Minor.empty()) Error += "." + Minor; @@ -156,7 +204,7 @@ if (Pos != StringRef::npos) { auto Next = Name.substr(Pos); Name = Name.substr(0, Pos); - if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor)) + if (!getExtensionVersion(D, Args, MArch, Ext, Next, Major, Minor)) return; } @@ -262,17 +310,23 @@ } std::string Major, Minor; - if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major, - Minor)) + if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts, + Major, Minor)) return false; + // Consume the base ISA version number and any '_' between rvxxx and the + // first extension + Exts = Exts.drop_front(Major.size()); + if (!Minor.empty()) + Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/); + Exts.consume_front("_"); + // 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) { + for (auto I = Exts.begin(), E = Exts.end(); I != E; ) { char c = *I; // Check ISA extensions are specified in the canonical order. @@ -295,18 +349,15 @@ // 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 false; - - // TODO: Use version number when setting target features - // and consume the underscore '_' that might follow. - } + std::string Next, Major, Minor; + if (std::next(I) != E) + Next = std::string(std::next(I), E); + if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major, + Minor)) + return false; // The order is OK, then push it into features. + // TODO: Use version number when setting target features switch (c) { default: // Currently LLVM supports only "mafdc". @@ -331,7 +382,19 @@ case 'c': Features.push_back("+c"); break; + case 'b': + Features.push_back("+b"); + break; } + + // Consume full extension name and version, including any optional '_' + // between this extension and the next + ++I; + I += Major.size(); + if (Minor.size()) + I += Minor.size() + 1 /*'p'*/; + if (*I == '_') + ++I; } // Dependency check. Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2291,6 +2291,8 @@ def mcmodel_EQ_medany : Flag<["-"], "mcmodel=medany">, Group<m_riscv_Features_Group>, Flags<[CC1Option]>, Alias<mcmodel_EQ>, AliasArgs<["medium"]>, HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">; +def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_riscv_Features_Group>, + HelpText<"Enable use of experimental RISC-V extensions.">; def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits