mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 20:26:06 +00:00

These two extensions add addtional instructions for carryless multiplication with 32-bits elements and Vector-Scalar GCM instructions. Please see https://github.com/riscv/riscv-isa-manual/pull/1306.
1104 lines
43 KiB
C++
1104 lines
43 KiB
C++
//===-- unittests/RISCVISAInfoTest.cpp ------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/TargetParser/RISCVISAInfo.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using namespace llvm;
|
|
|
|
bool operator==(const RISCVISAUtils::ExtensionVersion &A,
|
|
const RISCVISAUtils::ExtensionVersion &B) {
|
|
return A.Major == B.Major && A.Minor == B.Minor;
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsInvalidChars) {
|
|
for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0",
|
|
"rv32e2.0", "rva20u64+zbc"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"string may only contain [a-z0-9_]");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsInvalidBaseISA) {
|
|
for (StringRef Input : {"rv32", "rv64", "rv32j", "rv65i"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"arch string must begin with valid base ISA");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsMalformedInputs) {
|
|
for (StringRef Input : {"rv64e2p", "rv32i", "rv64ip1"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"extension lacks version in expected format");
|
|
}
|
|
|
|
for (StringRef Input : {"rv64i2p0_", "rv32i2p0__a2p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"extension name missing after separator '_'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsOnlyVersion) {
|
|
for (StringRef Input : {"rv64i2p0_1p0", "rv32i2p0_1p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"missing extension name");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsBadZ) {
|
|
for (StringRef Input : {"rv64i2p0_z1p0", "rv32i2p0_z2a1p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"'z' must be followed by a letter");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsBadS) {
|
|
for (StringRef Input : {"rv64i2p0_s1p0", "rv32i2p0_s2a1p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"'s' must be followed by a letter");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, RejectsBadX) {
|
|
for (StringRef Input : {"rv64i2p0_x1p0", "rv32i2p0_x2a1p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"'x' must be followed by a letter");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, DuplicateExtension) {
|
|
for (StringRef Input : {"rv64i2p0_a2p0_a1p0"}) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
|
|
"duplicate extension 'a'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, AcceptsValidBaseISAsAndSetsXLen) {
|
|
auto MaybeRV32I = RISCVISAInfo::parseNormalizedArchString("rv32i2p0");
|
|
ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
|
|
RISCVISAInfo &InfoRV32I = **MaybeRV32I;
|
|
EXPECT_EQ(InfoRV32I.getExtensions().size(), 1UL);
|
|
EXPECT_TRUE(InfoRV32I.getExtensions().at("i") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV32I.getXLen(), 32U);
|
|
|
|
auto MaybeRV32E = RISCVISAInfo::parseNormalizedArchString("rv32e2p0");
|
|
ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
|
|
RISCVISAInfo &InfoRV32E = **MaybeRV32E;
|
|
EXPECT_EQ(InfoRV32E.getExtensions().size(), 1UL);
|
|
EXPECT_TRUE(InfoRV32E.getExtensions().at("e") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV32E.getXLen(), 32U);
|
|
|
|
auto MaybeRV64I = RISCVISAInfo::parseNormalizedArchString("rv64i2p0");
|
|
ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
|
|
RISCVISAInfo &InfoRV64I = **MaybeRV64I;
|
|
EXPECT_EQ(InfoRV64I.getExtensions().size(), 1UL);
|
|
EXPECT_TRUE(InfoRV64I.getExtensions().at("i") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV64I.getXLen(), 64U);
|
|
|
|
auto MaybeRV64E = RISCVISAInfo::parseNormalizedArchString("rv64e2p0");
|
|
ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
|
|
RISCVISAInfo &InfoRV64E = **MaybeRV64E;
|
|
EXPECT_EQ(InfoRV64E.getExtensions().size(), 1UL);
|
|
EXPECT_TRUE(InfoRV64E.getExtensions().at("e") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV64E.getXLen(), 64U);
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, AcceptsArbitraryExtensionsAndVersions) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
|
|
"rv64i5p1_m3p2_zmadeup11p12_sfoo2p0_xbar3p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
RISCVISAInfo &Info = **MaybeISAInfo;
|
|
EXPECT_EQ(Info.getExtensions().size(), 5UL);
|
|
EXPECT_TRUE(Info.getExtensions().at("i") ==
|
|
(RISCVISAUtils::ExtensionVersion{5, 1}));
|
|
EXPECT_TRUE(Info.getExtensions().at("m") ==
|
|
(RISCVISAUtils::ExtensionVersion{3, 2}));
|
|
EXPECT_TRUE(Info.getExtensions().at("zmadeup") ==
|
|
(RISCVISAUtils::ExtensionVersion{11, 12}));
|
|
EXPECT_TRUE(Info.getExtensions().at("sfoo") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(Info.getExtensions().at("xbar") ==
|
|
(RISCVISAUtils::ExtensionVersion{3, 0}));
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, UpdatesFLenMinVLenMaxELen) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
|
|
"rv64i2p0_d2p0_zvl64b1p0_zve64d1p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
RISCVISAInfo &Info = **MaybeISAInfo;
|
|
EXPECT_EQ(Info.getXLen(), 64U);
|
|
EXPECT_EQ(Info.getFLen(), 64U);
|
|
EXPECT_EQ(Info.getMinVLen(), 64U);
|
|
EXPECT_EQ(Info.getMaxELen(), 64U);
|
|
EXPECT_EQ(Info.getMaxELenFp(), 64U);
|
|
}
|
|
|
|
TEST(ParseNormalizedArchString, AcceptsUnknownMultiletter) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
|
|
"rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
RISCVISAInfo &Info = **MaybeISAInfo;
|
|
EXPECT_EQ(Info.toString(), "rv64i2p0_f2p0_d2p0_zicsr2p0_ykk1p0");
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsInvalidChars) {
|
|
for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"string may only contain [a-z0-9_]");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsInvalidBaseISA) {
|
|
for (StringRef Input : {"rv32", "rv64", "rv65i"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
|
|
"profile name");
|
|
}
|
|
|
|
for (StringRef Input : {"rv32j", "rv32_i"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"first letter after 'rv32' should be 'e', 'i' or 'g'");
|
|
}
|
|
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64k", true).takeError()),
|
|
"first letter after 'rv64' should be 'e', 'i' or 'g'");
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsUnsupportedBaseISA) {
|
|
for (StringRef Input : {"rv128i", "rv128g"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
|
|
"profile name");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsSupportedBaseISAsAndSetsXLenAndFLen) {
|
|
auto MaybeRV32I = RISCVISAInfo::parseArchString("rv32i", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
|
|
RISCVISAInfo &InfoRV32I = **MaybeRV32I;
|
|
const auto &ExtsRV32I = InfoRV32I.getExtensions();
|
|
EXPECT_EQ(ExtsRV32I.size(), 1UL);
|
|
EXPECT_TRUE(ExtsRV32I.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_EQ(InfoRV32I.getXLen(), 32U);
|
|
EXPECT_EQ(InfoRV32I.getFLen(), 0U);
|
|
EXPECT_EQ(InfoRV32I.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV32I.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV32I.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV32E = RISCVISAInfo::parseArchString("rv32e", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
|
|
RISCVISAInfo &InfoRV32E = **MaybeRV32E;
|
|
const auto &ExtsRV32E = InfoRV32E.getExtensions();
|
|
EXPECT_EQ(ExtsRV32E.size(), 1UL);
|
|
EXPECT_TRUE(ExtsRV32E.at("e") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV32E.getXLen(), 32U);
|
|
EXPECT_EQ(InfoRV32E.getFLen(), 0U);
|
|
EXPECT_EQ(InfoRV32E.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV32E.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV32E.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV32G = RISCVISAInfo::parseArchString("rv32g", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32G, Succeeded());
|
|
RISCVISAInfo &InfoRV32G = **MaybeRV32G;
|
|
const auto &ExtsRV32G = InfoRV32G.getExtensions();
|
|
EXPECT_EQ(ExtsRV32G.size(), 8UL);
|
|
EXPECT_TRUE(ExtsRV32G.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV32G.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV32G.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV32G.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV32G.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV32G.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV32G.at("zifencei") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_EQ(InfoRV32G.getXLen(), 32U);
|
|
EXPECT_EQ(InfoRV32G.getFLen(), 64U);
|
|
EXPECT_EQ(InfoRV32G.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV32G.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV32G.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV64I = RISCVISAInfo::parseArchString("rv64i", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
|
|
RISCVISAInfo &InfoRV64I = **MaybeRV64I;
|
|
const auto &ExtsRV64I = InfoRV64I.getExtensions();
|
|
EXPECT_EQ(ExtsRV64I.size(), 1UL);
|
|
EXPECT_TRUE(ExtsRV64I.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_EQ(InfoRV64I.getXLen(), 64U);
|
|
EXPECT_EQ(InfoRV64I.getFLen(), 0U);
|
|
EXPECT_EQ(InfoRV64I.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV64I.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV64I.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV64E = RISCVISAInfo::parseArchString("rv64e", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
|
|
RISCVISAInfo &InfoRV64E = **MaybeRV64E;
|
|
const auto &ExtsRV64E = InfoRV64E.getExtensions();
|
|
EXPECT_EQ(ExtsRV64E.size(), 1UL);
|
|
EXPECT_TRUE(ExtsRV64E.at("e") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_EQ(InfoRV64E.getXLen(), 64U);
|
|
EXPECT_EQ(InfoRV64E.getFLen(), 0U);
|
|
EXPECT_EQ(InfoRV64E.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV64E.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV64E.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV64G = RISCVISAInfo::parseArchString("rv64g", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64G, Succeeded());
|
|
RISCVISAInfo &InfoRV64G = **MaybeRV64G;
|
|
const auto &ExtsRV64G = InfoRV64G.getExtensions();
|
|
EXPECT_EQ(ExtsRV64G.size(), 8UL);
|
|
EXPECT_TRUE(ExtsRV64G.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV64G.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV64G.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV64G.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV64G.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV64G.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV64G.at("zifencei") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_EQ(InfoRV64G.getXLen(), 64U);
|
|
EXPECT_EQ(InfoRV64G.getFLen(), 64U);
|
|
EXPECT_EQ(InfoRV64G.getMinVLen(), 0U);
|
|
EXPECT_EQ(InfoRV64G.getMaxELen(), 0U);
|
|
EXPECT_EQ(InfoRV64G.getMaxELenFp(), 0U);
|
|
|
|
auto MaybeRV64GCV = RISCVISAInfo::parseArchString("rv64gcv", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64GCV, Succeeded());
|
|
RISCVISAInfo &InfoRV64GCV = **MaybeRV64GCV;
|
|
const auto &ExtsRV64GCV = InfoRV64GCV.getExtensions();
|
|
EXPECT_EQ(ExtsRV64GCV.size(), 18UL);
|
|
EXPECT_TRUE(ExtsRV64GCV.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("m") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("a") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("f") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("d") == (RISCVISAUtils::ExtensionVersion{2, 2}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("c") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zicsr") == (RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zifencei") ==
|
|
(RISCVISAUtils::ExtensionVersion{2, 0}));
|
|
EXPECT_TRUE(ExtsRV32G.at("zmmul") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("v") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zve32x") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zve32f") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zve64x") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zve64f") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zve64d") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zvl32b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zvl64b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_TRUE(ExtsRV64GCV.at("zvl128b") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
EXPECT_EQ(InfoRV64GCV.getXLen(), 64U);
|
|
EXPECT_EQ(InfoRV64GCV.getFLen(), 64U);
|
|
EXPECT_EQ(InfoRV64GCV.getMinVLen(), 128U);
|
|
EXPECT_EQ(InfoRV64GCV.getMaxELen(), 64U);
|
|
EXPECT_EQ(InfoRV64GCV.getMaxELenFp(), 64U);
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsUnrecognizedExtensionNamesByDefault) {
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv32i_zmadeup", true).takeError()),
|
|
"unsupported standard user-level extension 'zmadeup'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv64g_smadeup", true).takeError()),
|
|
"unsupported standard supervisor-level extension 'smadeup'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv64g_xmadeup", true).takeError()),
|
|
"unsupported non-standard user-level extension 'xmadeup'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv32i_zmadeup1p0", true).takeError()),
|
|
"unsupported standard user-level extension 'zmadeup'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv64g_smadeup1p0", true).takeError()),
|
|
"unsupported standard supervisor-level extension 'smadeup'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv64g_xmadeup1p0", true).takeError()),
|
|
"unsupported non-standard user-level extension 'xmadeup'");
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsVersionInLongOrShortForm) {
|
|
for (StringRef Input : {"rv64i2p1"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_TRUE(Exts.at("i") == (RISCVISAUtils::ExtensionVersion{2, 1}));
|
|
}
|
|
for (StringRef Input : {"rv32i_zfinx1", "rv32i_zfinx1p0"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_TRUE(Exts.at("zfinx") == (RISCVISAUtils::ExtensionVersion{1, 0}));
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsUnrecognizedExtensionVersionsByDefault) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64i2p", true).takeError()),
|
|
"minor version number missing after 'p' for extension 'i'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64i1p0", true).takeError()),
|
|
"unsupported version number 1.0 for extension 'i'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64i9p9", true).takeError()),
|
|
"unsupported version number 9.9 for extension 'i'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv32im0p1", true).takeError()),
|
|
"unsupported version number 0.1 for extension 'm'");
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32izifencei10p10", true)
|
|
.takeError()),
|
|
"unsupported version number 10.10 for extension 'zifencei'");
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsUnderscoreSplittingExtensions) {
|
|
for (StringRef Input : {"rv32imafdczifencei", "rv32i_m_a_f_d_c_zifencei"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 9UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("a"), 1U);
|
|
EXPECT_EQ(Exts.count("f"), 1U);
|
|
EXPECT_EQ(Exts.count("d"), 1U);
|
|
EXPECT_EQ(Exts.count("c"), 1U);
|
|
EXPECT_EQ(Exts.count("zicsr"), 1U);
|
|
EXPECT_EQ(Exts.count("zifencei"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsRelaxSingleLetterExtensions) {
|
|
for (StringRef Input :
|
|
{"rv32imfad", "rv32im_fa_d", "rv32im2p0fad", "rv32i2p1m2p0fad"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 7UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("f"), 1U);
|
|
EXPECT_EQ(Exts.count("a"), 1U);
|
|
EXPECT_EQ(Exts.count("d"), 1U);
|
|
EXPECT_EQ(Exts.count("zicsr"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsRelaxMixedLetterExtensions) {
|
|
for (StringRef Input :
|
|
{"rv32i_zihintntl_m_a_f_d_svinval", "rv32izihintntl_mafdsvinval",
|
|
"rv32i_zihintntl_mafd_svinval"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 9UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("a"), 1U);
|
|
EXPECT_EQ(Exts.count("f"), 1U);
|
|
EXPECT_EQ(Exts.count("d"), 1U);
|
|
EXPECT_EQ(Exts.count("zihintntl"), 1U);
|
|
EXPECT_EQ(Exts.count("svinval"), 1U);
|
|
EXPECT_EQ(Exts.count("zicsr"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsAmbiguousFromRelaxExtensions) {
|
|
for (StringRef Input : {"rv32i_zba_m", "rv32izba_m", "rv32izba1p0_m2p0"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 4UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("zba"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
for (StringRef Input :
|
|
{"rv32ia_zba_m", "rv32iazba_m", "rv32ia2p1zba1p0_m2p0"}) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString(Input, true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 5UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("zba"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("a"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsRelaxExtensionsNotStartWithEorIorG) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv32zba_im", true).takeError()),
|
|
"first letter after 'rv32' should be 'e', 'i' or 'g'");
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
RejectsMultiLetterExtensionFollowBySingleLetterExtensions) {
|
|
for (StringRef Input : {"rv32izbam", "rv32i_zbam"})
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"unsupported standard user-level extension 'zbam'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv32izbai_m", true).takeError()),
|
|
"unsupported standard user-level extension 'zbai'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv32izbaim", true).takeError()),
|
|
"unsupported standard user-level extension 'zbaim'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv32i_zba1p0m", true).takeError()),
|
|
"unsupported standard user-level extension 'zba1p0m'");
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsDoubleOrTrailingUnderscore) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64i__m", true).takeError()),
|
|
"extension name missing after separator '_'");
|
|
|
|
for (StringRef Input :
|
|
{"rv32ezicsr__zifencei", "rv32i_", "rv32izicsr_", "rv64im_"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"extension name missing after separator '_'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsDuplicateExtensionNames) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64ii", true).takeError()),
|
|
"invalid standard user-level extension 'i'");
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv32ee", true).takeError()),
|
|
"invalid standard user-level extension 'e'");
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64imm", true).takeError()),
|
|
"duplicated standard user-level extension 'm'");
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv32i_zicsr_zicsr", true).takeError()),
|
|
"duplicated standard user-level extension 'zicsr'");
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
RejectsExperimentalExtensionsIfNotEnableExperimentalExtension) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64izalasr", false).takeError()),
|
|
"requires '-menable-experimental-extensions' for experimental extension "
|
|
"'zalasr'");
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
AcceptsExperimentalExtensionsIfEnableExperimentalExtension) {
|
|
// Note: If zalasr becomes none-experimental, this test will need
|
|
// updating (and unfortunately, it will still pass). The failure of
|
|
// RejectsExperimentalExtensionsIfNotEnableExperimentalExtension will
|
|
// hopefully serve as a reminder to update.
|
|
auto MaybeISAInfo = RISCVISAInfo::parseArchString("rv64izalasr", true, false);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 2UL);
|
|
EXPECT_EQ(Exts.count("zalasr"), 1U);
|
|
auto MaybeISAInfo2 = RISCVISAInfo::parseArchString("rv64izalasr0p1", true);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
|
|
const auto &Exts2 = (*MaybeISAInfo2)->getExtensions();
|
|
EXPECT_EQ(Exts2.size(), 2UL);
|
|
EXPECT_EQ(Exts2.count("zalasr"), 1U);
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
RequiresExplicitVersionNumberForExperimentalExtensionByDefault) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rv64izalasr", true).takeError()),
|
|
"experimental extension requires explicit version number `zalasr`");
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
AcceptsUnrecognizedVersionIfNotExperimentalExtensionVersionCheck) {
|
|
auto MaybeISAInfo =
|
|
RISCVISAInfo::parseArchString("rv64izalasr9p9", true, false);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
const auto &Exts = (*MaybeISAInfo)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 2UL);
|
|
EXPECT_TRUE(Exts.at("zalasr") == (RISCVISAUtils::ExtensionVersion{9, 9}));
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsUnrecognizedVersionForExperimentalExtension) {
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rv64izalasr9p9", true).takeError()),
|
|
"unsupported version number 9.9 for experimental extension 'zalasr' "
|
|
"(this compiler supports 0.1)");
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsExtensionVersionForG) {
|
|
for (StringRef Input : {"rv32g1c", "rv64g2p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"version not supported for 'g'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AddsImpliedExtensions) {
|
|
// Does not attempt to exhaustively test all implications.
|
|
auto MaybeRV64ID = RISCVISAInfo::parseArchString("rv64id", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64ID, Succeeded());
|
|
const auto &ExtsRV64ID = (*MaybeRV64ID)->getExtensions();
|
|
EXPECT_EQ(ExtsRV64ID.size(), 4UL);
|
|
EXPECT_EQ(ExtsRV64ID.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV64ID.count("f"), 1U);
|
|
EXPECT_EQ(ExtsRV64ID.count("d"), 1U);
|
|
EXPECT_EQ(ExtsRV64ID.count("zicsr"), 1U);
|
|
|
|
auto MaybeRV32IZKN = RISCVISAInfo::parseArchString("rv64izkn", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32IZKN, Succeeded());
|
|
const auto &ExtsRV32IZKN = (*MaybeRV32IZKN)->getExtensions();
|
|
EXPECT_EQ(ExtsRV32IZKN.size(), 8UL);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zbkb"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zbkc"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zbkx"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zkne"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zknd"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zknh"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZKN.count("zkn"), 1U);
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsConflictingExtensions) {
|
|
for (StringRef Input : {"rv32ifzfinx", "rv64gzdinx"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'f' and 'zfinx' extensions are incompatible");
|
|
}
|
|
|
|
for (StringRef Input : {"rv32idc_zcmp1p0", "rv64idc_zcmp1p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'zcmp' extension is incompatible with 'c' extension when 'd' "
|
|
"extension is enabled");
|
|
}
|
|
|
|
for (StringRef Input : {"rv32id_zcd1p0_zcmp1p0", "rv64id_zcd1p0_zcmp1p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'zcmp' extension is incompatible with 'zcd' extension when 'd' "
|
|
"extension is enabled");
|
|
}
|
|
|
|
for (StringRef Input : {"rv32idc_zcmt1p0", "rv64idc_zcmt1p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'zcmt' extension is incompatible with 'c' extension when 'd' "
|
|
"extension is enabled");
|
|
}
|
|
|
|
for (StringRef Input : {"rv32id_zcd1p0_zcmt1p0", "rv64id_zcd1p0_zcmt1p0"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'zcmt' extension is incompatible with 'zcd' extension when 'd' "
|
|
"extension is enabled");
|
|
}
|
|
|
|
for (StringRef Input : {"rv64if_zcf"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"'zcf' is only supported for 'rv32'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsUnrecognizedProfileNames) {
|
|
for (StringRef Input : {"rvi23u99", "rvz23u64", "rva99u32"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported "
|
|
"profile name");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, RejectsProfilesWithUnseparatedExtraExtensions) {
|
|
for (StringRef Input : {"rvi20u32m", "rvi20u64c"}) {
|
|
EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
|
|
"additional extensions must be after separator '_'");
|
|
}
|
|
}
|
|
|
|
TEST(ParseArchString, AcceptsBareProfileNames) {
|
|
auto MaybeRVA20U64 = RISCVISAInfo::parseArchString("rva20u64", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRVA20U64, Succeeded());
|
|
const auto &Exts = (*MaybeRVA20U64)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 14UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("f"), 1U);
|
|
EXPECT_EQ(Exts.count("a"), 1U);
|
|
EXPECT_EQ(Exts.count("d"), 1U);
|
|
EXPECT_EQ(Exts.count("c"), 1U);
|
|
EXPECT_EQ(Exts.count("za128rs"), 1U);
|
|
EXPECT_EQ(Exts.count("zicntr"), 1U);
|
|
EXPECT_EQ(Exts.count("ziccif"), 1U);
|
|
EXPECT_EQ(Exts.count("zicsr"), 1U);
|
|
EXPECT_EQ(Exts.count("ziccrse"), 1U);
|
|
EXPECT_EQ(Exts.count("ziccamoa"), 1U);
|
|
EXPECT_EQ(Exts.count("zicclsm"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
|
|
auto MaybeRVA23U64 = RISCVISAInfo::parseArchString("rva23u64", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRVA23U64, Succeeded());
|
|
EXPECT_GT((*MaybeRVA23U64)->getExtensions().size(), 13UL);
|
|
}
|
|
|
|
TEST(ParseArchSTring, AcceptsProfileNamesWithSeparatedAdditionalExtensions) {
|
|
auto MaybeRVI20U64 = RISCVISAInfo::parseArchString("rvi20u64_m_zba", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRVI20U64, Succeeded());
|
|
const auto &Exts = (*MaybeRVI20U64)->getExtensions();
|
|
EXPECT_EQ(Exts.size(), 4UL);
|
|
EXPECT_EQ(Exts.count("i"), 1U);
|
|
EXPECT_EQ(Exts.count("m"), 1U);
|
|
EXPECT_EQ(Exts.count("zba"), 1U);
|
|
EXPECT_EQ(Exts.count("zmmul"), 1U);
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
RejectsProfilesWithAdditionalExtensionsGivenAlreadyInProfile) {
|
|
// This test was added to document the current behaviour. Discussion isn't
|
|
// believed to have taken place about if this is desirable or not.
|
|
EXPECT_EQ(
|
|
toString(
|
|
RISCVISAInfo::parseArchString("rva20u64_zicntr", true).takeError()),
|
|
"duplicated standard user-level extension 'zicntr'");
|
|
}
|
|
|
|
TEST(ParseArchString,
|
|
RejectsExperimentalProfilesIfEnableExperimentalExtensionsNotSet) {
|
|
EXPECT_EQ(
|
|
toString(RISCVISAInfo::parseArchString("rva23u64", false).takeError()),
|
|
"requires '-menable-experimental-extensions' for profile 'rva23u64'");
|
|
}
|
|
|
|
TEST(ToFeatures, IIsDroppedAndExperimentalExtensionsArePrefixed) {
|
|
auto MaybeISAInfo1 =
|
|
RISCVISAInfo::parseArchString("rv64im_zalasr", true, false);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo1, Succeeded());
|
|
EXPECT_THAT((*MaybeISAInfo1)->toFeatures(),
|
|
ElementsAre("+m", "+zmmul", "+experimental-zalasr"));
|
|
|
|
auto MaybeISAInfo2 = RISCVISAInfo::parseArchString(
|
|
"rv32e_zalasr_xventanacondops", true, false);
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo2, Succeeded());
|
|
EXPECT_THAT((*MaybeISAInfo2)->toFeatures(),
|
|
ElementsAre("+e", "+experimental-zalasr", "+xventanacondops"));
|
|
}
|
|
|
|
TEST(ToFeatures, UnsupportedExtensionsAreDropped) {
|
|
auto MaybeISAInfo =
|
|
RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0_xmadeup1p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
EXPECT_THAT((*MaybeISAInfo)->toFeatures(), ElementsAre("+m"));
|
|
}
|
|
|
|
TEST(ToFeatures, UnsupportedExtensionsAreKeptIfIgnoreUnknownIsFalse) {
|
|
auto MaybeISAInfo =
|
|
RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0_xmadeup1p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
EXPECT_THAT((*MaybeISAInfo)->toFeatures(false, false),
|
|
ElementsAre("+m", "+xmadeup"));
|
|
}
|
|
|
|
TEST(ToFeatures, AddAllExtensionsAddsNegativeExtensions) {
|
|
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString("rv64i2p0_m2p0");
|
|
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
|
|
|
|
auto Features = (*MaybeISAInfo)->toFeatures(true);
|
|
EXPECT_GT(Features.size(), 1UL);
|
|
EXPECT_EQ(Features.front(), "+m");
|
|
// Every feature after should be a negative feature
|
|
for (auto &NegativeExt : llvm::drop_begin(Features))
|
|
EXPECT_TRUE(NegativeExt.substr(0, 1) == "-");
|
|
}
|
|
|
|
TEST(OrderedExtensionMap, ExtensionsAreCorrectlyOrdered) {
|
|
RISCVISAUtils::OrderedExtensionMap Exts;
|
|
for (auto ExtName : {"y", "l", "m", "c", "i", "xfoo", "xbar", "sfoo", "sbar",
|
|
"zmfoo", "zzfoo", "zfinx", "zicsr"})
|
|
Exts[ExtName] = {1, 0};
|
|
|
|
std::vector<std::string> ExtNames;
|
|
for (const auto &Ext : Exts)
|
|
ExtNames.push_back(Ext.first);
|
|
|
|
// FIXME: 'l' and 'y' should be ordered after 'i', 'm', 'c'.
|
|
EXPECT_THAT(ExtNames,
|
|
ElementsAre("i", "m", "l", "c", "y", "zicsr", "zmfoo", "zfinx",
|
|
"zzfoo", "sbar", "sfoo", "xbar", "xfoo"));
|
|
}
|
|
|
|
TEST(ParseArchString, ZceImplication) {
|
|
auto MaybeRV32IZce = RISCVISAInfo::parseArchString("rv32izce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32IZce, Succeeded());
|
|
const auto &ExtsRV32IZce = (*MaybeRV32IZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV32IZce.size(), 7UL);
|
|
EXPECT_EQ(ExtsRV32IZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV32IZce.count("zcmt"), 1U);
|
|
|
|
auto MaybeRV32IFZce = RISCVISAInfo::parseArchString("rv32ifzce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32IFZce, Succeeded());
|
|
const auto &ExtsRV32IFZce = (*MaybeRV32IFZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV32IFZce.size(), 9UL);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("f"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zcf"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV32IFZce.count("zcmt"), 1U);
|
|
|
|
auto MaybeRV32IDZce = RISCVISAInfo::parseArchString("rv32idzce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV32IDZce, Succeeded());
|
|
const auto &ExtsRV32IDZce = (*MaybeRV32IDZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV32IDZce.size(), 10UL);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("f"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("d"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zcf"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV32IDZce.count("zcmt"), 1U);
|
|
|
|
auto MaybeRV64IZce = RISCVISAInfo::parseArchString("rv64izce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64IZce, Succeeded());
|
|
const auto &ExtsRV64IZce = (*MaybeRV64IZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV64IZce.size(), 7UL);
|
|
EXPECT_EQ(ExtsRV64IZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV64IZce.count("zcmt"), 1U);
|
|
|
|
auto MaybeRV64IFZce = RISCVISAInfo::parseArchString("rv64ifzce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64IFZce, Succeeded());
|
|
const auto &ExtsRV64IFZce = (*MaybeRV64IFZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV64IFZce.size(), 8UL);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("f"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U);
|
|
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV64IFZce.count("zcmt"), 1U);
|
|
|
|
auto MaybeRV64IDZce = RISCVISAInfo::parseArchString("rv64idzce", true);
|
|
ASSERT_THAT_EXPECTED(MaybeRV64IDZce, Succeeded());
|
|
const auto &ExtsRV64IDZce = (*MaybeRV64IDZce)->getExtensions();
|
|
EXPECT_EQ(ExtsRV64IDZce.size(), 9UL);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("i"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zicsr"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("f"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("d"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zca"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zcb"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zce"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zcmp"), 1U);
|
|
EXPECT_EQ(ExtsRV64IDZce.count("zcmt"), 1U);
|
|
}
|
|
|
|
TEST(isSupportedExtensionWithVersion, AcceptsSingleExtensionWithVersion) {
|
|
EXPECT_TRUE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb1p0"));
|
|
EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zbb"));
|
|
EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo1p0"));
|
|
EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("zfoo"));
|
|
EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion(""));
|
|
EXPECT_FALSE(RISCVISAInfo::isSupportedExtensionWithVersion("c2p0zbb1p0"));
|
|
}
|
|
|
|
TEST(getTargetFeatureForExtension, RetrieveTargetFeatureFromOneExt) {
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zbb"), "zbb");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("ztso1p0"), "ztso");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("ztso"), "ztso");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zihintntl1234p4321"),
|
|
"");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zfoo"), "");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension(""), "");
|
|
EXPECT_EQ(RISCVISAInfo::getTargetFeatureForExtension("zbbzihintntl"), "");
|
|
}
|
|
|
|
TEST(RiscvExtensionsHelp, CheckExtensions) {
|
|
// clang-format off
|
|
std::string ExpectedOutput =
|
|
R"(All available -march extensions for RISC-V
|
|
|
|
Name Version Description
|
|
i 2.1 This is a long dummy description
|
|
e 2.0
|
|
m 2.0
|
|
a 2.1
|
|
f 2.2
|
|
d 2.2
|
|
c 2.0
|
|
b 1.0
|
|
v 1.0
|
|
h 1.0
|
|
zic64b 1.0
|
|
zicbom 1.0
|
|
zicbop 1.0
|
|
zicboz 1.0
|
|
ziccamoa 1.0
|
|
ziccif 1.0
|
|
zicclsm 1.0
|
|
ziccrse 1.0
|
|
zicntr 2.0
|
|
zicond 1.0
|
|
zicsr 2.0
|
|
zifencei 2.0
|
|
zihintntl 1.0
|
|
zihintpause 2.0
|
|
zihpm 2.0
|
|
zimop 1.0
|
|
zmmul 1.0
|
|
za128rs 1.0
|
|
za64rs 1.0
|
|
zaamo 1.0
|
|
zabha 1.0
|
|
zalrsc 1.0
|
|
zama16b 1.0
|
|
zawrs 1.0
|
|
zfa 1.0
|
|
zfbfmin 1.0
|
|
zfh 1.0
|
|
zfhmin 1.0
|
|
zfinx 1.0
|
|
zdinx 1.0
|
|
zca 1.0
|
|
zcb 1.0
|
|
zcd 1.0
|
|
zce 1.0
|
|
zcf 1.0
|
|
zcmop 1.0
|
|
zcmp 1.0
|
|
zcmt 1.0
|
|
zba 1.0
|
|
zbb 1.0
|
|
zbc 1.0
|
|
zbkb 1.0
|
|
zbkc 1.0
|
|
zbkx 1.0
|
|
zbs 1.0
|
|
zk 1.0
|
|
zkn 1.0
|
|
zknd 1.0
|
|
zkne 1.0
|
|
zknh 1.0
|
|
zkr 1.0
|
|
zks 1.0
|
|
zksed 1.0
|
|
zksh 1.0
|
|
zkt 1.0
|
|
ztso 1.0
|
|
zvbb 1.0
|
|
zvbc 1.0
|
|
zve32f 1.0
|
|
zve32x 1.0
|
|
zve64d 1.0
|
|
zve64f 1.0
|
|
zve64x 1.0
|
|
zvfbfmin 1.0
|
|
zvfbfwma 1.0
|
|
zvfh 1.0
|
|
zvfhmin 1.0
|
|
zvkb 1.0
|
|
zvkg 1.0
|
|
zvkn 1.0
|
|
zvknc 1.0
|
|
zvkned 1.0
|
|
zvkng 1.0
|
|
zvknha 1.0
|
|
zvknhb 1.0
|
|
zvks 1.0
|
|
zvksc 1.0
|
|
zvksed 1.0
|
|
zvksg 1.0
|
|
zvksh 1.0
|
|
zvkt 1.0
|
|
zvl1024b 1.0
|
|
zvl128b 1.0
|
|
zvl16384b 1.0
|
|
zvl2048b 1.0
|
|
zvl256b 1.0
|
|
zvl32768b 1.0
|
|
zvl32b 1.0
|
|
zvl4096b 1.0
|
|
zvl512b 1.0
|
|
zvl64b 1.0
|
|
zvl65536b 1.0
|
|
zvl8192b 1.0
|
|
zhinx 1.0
|
|
zhinxmin 1.0
|
|
shcounterenw 1.0
|
|
shgatpa 1.0
|
|
shtvala 1.0
|
|
shvsatpa 1.0
|
|
shvstvala 1.0
|
|
shvstvecd 1.0
|
|
smaia 1.0
|
|
smcdeleg 1.0
|
|
smcsrind 1.0
|
|
smepmp 1.0
|
|
smstateen 1.0
|
|
ssaia 1.0
|
|
ssccfg 1.0
|
|
ssccptr 1.0
|
|
sscofpmf 1.0
|
|
sscounterenw 1.0
|
|
sscsrind 1.0
|
|
ssstateen 1.0
|
|
ssstrict 1.0
|
|
sstc 1.0
|
|
sstvala 1.0
|
|
sstvecd 1.0
|
|
ssu64xl 1.0
|
|
svade 1.0
|
|
svadu 1.0
|
|
svbare 1.0
|
|
svinval 1.0
|
|
svnapot 1.0
|
|
svpbmt 1.0
|
|
xcvalu 1.0
|
|
xcvbi 1.0
|
|
xcvbitmanip 1.0
|
|
xcvelw 1.0
|
|
xcvmac 1.0
|
|
xcvmem 1.0
|
|
xcvsimd 1.0
|
|
xsfcease 1.0
|
|
xsfvcp 1.0
|
|
xsfvfnrclipxfqf 1.0
|
|
xsfvfwmaccqqq 1.0
|
|
xsfvqmaccdod 1.0
|
|
xsfvqmaccqoq 1.0
|
|
xsifivecdiscarddlone 1.0
|
|
xsifivecflushdlone 1.0
|
|
xtheadba 1.0
|
|
xtheadbb 1.0
|
|
xtheadbs 1.0
|
|
xtheadcmo 1.0
|
|
xtheadcondmov 1.0
|
|
xtheadfmemidx 1.0
|
|
xtheadmac 1.0
|
|
xtheadmemidx 1.0
|
|
xtheadmempair 1.0
|
|
xtheadsync 1.0
|
|
xtheadvdot 1.0
|
|
xventanacondops 1.0
|
|
xwchc 2.2
|
|
|
|
Experimental extensions
|
|
zicfilp 1.0 This is a long dummy description
|
|
zicfiss 1.0
|
|
zacas 1.0
|
|
zalasr 0.1
|
|
zvbc32e 0.7
|
|
zvkgs 0.7
|
|
smmpm 1.0
|
|
smnpm 1.0
|
|
ssnpm 1.0
|
|
sspm 1.0
|
|
ssqosid 1.0
|
|
supm 1.0
|
|
|
|
Supported Profiles
|
|
rva20s64
|
|
rva20u64
|
|
rva22s64
|
|
rva22u64
|
|
rvi20u32
|
|
rvi20u64
|
|
|
|
Experimental Profiles
|
|
rva23s64
|
|
rva23u64
|
|
rvb23s64
|
|
rvb23u64
|
|
rvm23u32
|
|
|
|
Use -march to specify the target's extension.
|
|
For example, clang -march=rv32i_v1p0)";
|
|
// clang-format on
|
|
|
|
StringMap<StringRef> DummyMap;
|
|
DummyMap["i"] = "This is a long dummy description";
|
|
DummyMap["experimental-zicfilp"] = "This is a long dummy description";
|
|
|
|
outs().flush();
|
|
testing::internal::CaptureStdout();
|
|
RISCVISAInfo::printSupportedExtensions(DummyMap);
|
|
outs().flush();
|
|
|
|
std::string CapturedOutput = testing::internal::GetCapturedStdout();
|
|
EXPECT_TRUE([](std::string &Captured, std::string &Expected) {
|
|
return Captured.find(Expected) != std::string::npos;
|
|
}(CapturedOutput, ExpectedOutput));
|
|
}
|
|
|
|
TEST(TargetParserTest, RISCVPrintEnabledExtensions) {
|
|
// clang-format off
|
|
std::string ExpectedOutput =
|
|
R"(Extensions enabled for the given RISC-V target
|
|
|
|
Name Version Description
|
|
i 2.1 'I' (Base Integer Instruction Set)
|
|
|
|
Experimental extensions
|
|
zicfilp 1.0 'Zicfilp' (Landing pad)
|
|
|
|
ISA String: rv64i2p1_zicfilp1p0_zicsr2p0
|
|
)";
|
|
// clang-format on
|
|
|
|
StringMap<StringRef> DescMap;
|
|
DescMap["i"] = "'I' (Base Integer Instruction Set)";
|
|
DescMap["experimental-zicfilp"] = "'Zicfilp' (Landing pad)";
|
|
std::set<StringRef> EnabledExtensions = {"i", "experimental-zicfilp"};
|
|
|
|
outs().flush();
|
|
testing::internal::CaptureStdout();
|
|
RISCVISAInfo::printEnabledExtensions(/*IsRV64=*/true, EnabledExtensions,
|
|
DescMap);
|
|
outs().flush();
|
|
std::string CapturedOutput = testing::internal::GetCapturedStdout();
|
|
|
|
EXPECT_EQ(CapturedOutput, ExpectedOutput);
|
|
}
|