[llvm] a4bf1b4 - [RISCV] Unify depedency check and extension implication parsing logics
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 9 21:16:08 PST 2021
Author: eopXD
Date: 2021-12-09T21:16:04-08:00
New Revision: a4bf1b449dc0691e182db879bfb53bc52fbf11b7
URL: https://github.com/llvm/llvm-project/commit/a4bf1b449dc0691e182db879bfb53bc52fbf11b7
DIFF: https://github.com/llvm/llvm-project/commit/a4bf1b449dc0691e182db879bfb53bc52fbf11b7.diff
LOG: [RISCV] Unify depedency check and extension implication parsing logics
Originially there are two places that does parsing - `parseArchString` and
`parseFeatures`, each with its code on dependency check and implication.
This patch extracts common parts of the two as functions of `RISCVISAInfo`
and let them 2 use it.
Reviewed By: asb
Differential Revision: https://reviews.llvm.org/D112359
Added:
llvm/test/MC/RISCV/attribute-arch-invalid.s
Modified:
clang/test/CodeGen/RISCV/riscv-metadata.c
clang/test/CodeGen/RISCV/riscv32-ilp32-ilp32f-ilp32d-abi.c
clang/test/CodeGen/RISCV/riscv32-ilp32d-abi.c
clang/test/CodeGen/RISCV/riscv32-ilp32f-ilp32d-abi.c
clang/test/CodeGen/RISCV/riscv64-lp64-lp64f-lp64d-abi.c
clang/test/CodeGen/RISCV/riscv64-lp64d-abi.c
clang/test/CodeGen/RISCV/riscv64-lp64f-lp64d-abi.c
clang/test/CodeGen/riscv32-ilp32d-abi.cpp
llvm/include/llvm/Support/RISCVISAInfo.h
llvm/lib/Support/RISCVISAInfo.cpp
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/test/MC/RISCV/attribute-arch.s
Removed:
################################################################################
diff --git a/clang/test/CodeGen/RISCV/riscv-metadata.c b/clang/test/CodeGen/RISCV/riscv-metadata.c
index 19bde4ca73beb..3e5b2b855bf5c 100644
--- a/clang/test/CodeGen/RISCV/riscv-metadata.c
+++ b/clang/test/CodeGen/RISCV/riscv-metadata.c
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple riscv32 -target-abi ilp32 -emit-llvm -o - %s | FileCheck -check-prefix=ILP32 %s
// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm -o - %s | FileCheck -check-prefix=ILP32F %s
-// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm -o - %s | FileCheck -check-prefix=ILP32D %s
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d -emit-llvm -o - %s | FileCheck -check-prefix=ILP32D %s
// RUN: %clang_cc1 -triple riscv64 -target-abi lp64 -emit-llvm -o - %s | FileCheck -check-prefix=LP64 %s
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm -o - %s | FileCheck -check-prefix=LP64F %s
-// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm -o - %s | FileCheck -check-prefix=LP64D %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-feature +f -target-abi lp64d -emit-llvm -o - %s | FileCheck -check-prefix=LP64D %s
// ILP32: !{{[0-9]+}} = !{i32 1, !"target-abi", !"ilp32"}
// ILP32F: !{{[0-9]+}} = !{i32 1, !"target-abi", !"ilp32f"}
diff --git a/clang/test/CodeGen/RISCV/riscv32-ilp32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/RISCV/riscv32-ilp32-ilp32f-ilp32d-abi.c
index 1bf953d39038b..5a5c47a3088cd 100644
--- a/clang/test/CodeGen/RISCV/riscv32-ilp32-ilp32f-ilp32d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv32-ilp32-ilp32f-ilp32d-abi.c
@@ -3,7 +3,7 @@
// RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-FORCEINT128
// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d -emit-llvm %s -o - \
// RUN: | FileCheck %s
// This file contains test cases that will have the same output for the ilp32,
diff --git a/clang/test/CodeGen/RISCV/riscv32-ilp32d-abi.c b/clang/test/CodeGen/RISCV/riscv32-ilp32d-abi.c
index 39a210a89ae79..523a4668ff6e7 100644
--- a/clang/test/CodeGen/RISCV/riscv32-ilp32d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv32-ilp32d-abi.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d -emit-llvm %s -o - \
// RUN: | FileCheck %s
#include <stdint.h>
diff --git a/clang/test/CodeGen/RISCV/riscv32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/RISCV/riscv32-ilp32f-ilp32d-abi.c
index e887d986f96a3..1de7d51c4fbc4 100644
--- a/clang/test/CodeGen/RISCV/riscv32-ilp32f-ilp32d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv32-ilp32f-ilp32d-abi.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d -emit-llvm %s -o - \
// RUN: | FileCheck %s
#include <stdint.h>
diff --git a/clang/test/CodeGen/RISCV/riscv64-lp64-lp64f-lp64d-abi.c b/clang/test/CodeGen/RISCV/riscv64-lp64-lp64f-lp64d-abi.c
index ba11475a9c550..0abb838f9bc3d 100644
--- a/clang/test/CodeGen/RISCV/riscv64-lp64-lp64f-lp64d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv64-lp64-lp64f-lp64d-abi.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-feature +f -target-abi lp64d -emit-llvm %s -o - \
// RUN: | FileCheck %s
// This file contains test cases that will have the same output for the lp64,
diff --git a/clang/test/CodeGen/RISCV/riscv64-lp64d-abi.c b/clang/test/CodeGen/RISCV/riscv64-lp64d-abi.c
index a25116f836fd4..f54e7ddd3fbeb 100644
--- a/clang/test/CodeGen/RISCV/riscv64-lp64d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv64-lp64d-abi.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-feature +f -target-abi lp64d -emit-llvm %s -o - \
// RUN: | FileCheck %s
#include <stdint.h>
diff --git a/clang/test/CodeGen/RISCV/riscv64-lp64f-lp64d-abi.c b/clang/test/CodeGen/RISCV/riscv64-lp64f-lp64d-abi.c
index b3a2645f4b060..71dd8e7e0ee8d 100644
--- a/clang/test/CodeGen/RISCV/riscv64-lp64f-lp64d-abi.c
+++ b/clang/test/CodeGen/RISCV/riscv64-lp64f-lp64d-abi.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \
// RUN: | FileCheck %s
-// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \
+// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-feature +f -target-abi lp64d -emit-llvm %s -o - \
// RUN: | FileCheck %s
#include <stdint.h>
diff --git a/clang/test/CodeGen/riscv32-ilp32d-abi.cpp b/clang/test/CodeGen/riscv32-ilp32d-abi.cpp
index 6859dbb349664..b98f5f5bc87b3 100644
--- a/clang/test/CodeGen/riscv32-ilp32d-abi.cpp
+++ b/clang/test/CodeGen/riscv32-ilp32d-abi.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d \
+// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d \
// RUN: -Wno-missing-declarations -emit-llvm %s -o - | FileCheck %s
struct empty_float2 { struct {}; float f; float g; };
diff --git a/llvm/include/llvm/Support/RISCVISAInfo.h b/llvm/include/llvm/Support/RISCVISAInfo.h
index 7110de601123f..1ba4d449b709a 100644
--- a/llvm/include/llvm/Support/RISCVISAInfo.h
+++ b/llvm/include/llvm/Support/RISCVISAInfo.h
@@ -81,6 +81,9 @@ class RISCVISAInfo {
void addExtension(StringRef ExtName, unsigned MajorVersion,
unsigned MinorVersion);
+ Error checkDependency();
+
+ void updateImplication();
void updateFLen();
};
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp
index 1ca2120c40750..378e6644d0d72 100644
--- a/llvm/lib/Support/RISCVISAInfo.cpp
+++ b/llvm/lib/Support/RISCVISAInfo.cpp
@@ -412,7 +412,6 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
assert(XLen == 32 || XLen == 64);
std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
- bool HasE = false;
for (auto &Feature : Features) {
StringRef ExtName = Feature;
bool Experimental = false;
@@ -431,29 +430,19 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
if (ExtensionInfoIterator == ExtensionInfos.end())
continue;
- if (Add) {
- if (ExtName == "e") {
- if (XLen != 32)
- return createStringError(
- errc::invalid_argument,
- "standard user-level extension 'e' requires 'rv32'");
- HasE = true;
- }
-
+ if (Add)
ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
ExtensionInfoIterator->Version.Minor);
- } else
- ISAInfo->Exts.erase(ExtName.str());
- }
- if (!HasE) {
- if (auto Version = findDefaultVersion("i"))
- ISAInfo->addExtension("i", Version->Major, Version->Minor);
else
- llvm_unreachable("Default extension version for 'i' not found?");
+ ISAInfo->Exts.erase(ExtName.str());
}
+ ISAInfo->updateImplication();
ISAInfo->updateFLen();
+ if (Error Result = ISAInfo->checkDependency())
+ return std::move(Result);
+
return std::move(ISAInfo);
}
@@ -479,7 +468,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
// The canonical order specified in ISA manual.
// Ref: Table 22.1 in RISC-V User-Level ISA V2.2
StringRef StdExts = AllStdExts;
- bool HasF = false, HasD = false;
char Baseline = Arch[4];
// First letter should be 'e', 'i' or 'g'.
@@ -500,8 +488,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
case 'g':
// g = imafd
StdExts = StdExts.drop_front(4);
- HasF = true;
- HasD = true;
break;
}
@@ -582,34 +568,14 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
// The order is OK, then push it into features.
// TODO: Use version number when setting target features
- switch (C) {
- default:
- // Currently LLVM supports only "mafdcbv".
+ // Currently LLVM supports only "mafdcbv".
+ StringRef SupportedStandardExtension = "mafdcbv";
+ if (SupportedStandardExtension.find(C) == StringRef::npos)
return createStringError(errc::invalid_argument,
"unsupported standard user-level extension '%c'",
C);
- case 'm':
- ISAInfo->addExtension("m", Major, Minor);
- break;
- case 'a':
- ISAInfo->addExtension("a", Major, Minor);
- break;
- case 'f':
- ISAInfo->addExtension("f", Major, Minor);
- HasF = true;
- break;
- case 'd':
- ISAInfo->addExtension("d", Major, Minor);
- HasD = true;
- break;
- case 'c':
- ISAInfo->addExtension("c", Major, Minor);
- break;
- case 'v':
- ISAInfo->addExtension("v", Major, Minor);
- ISAInfo->addExtension("zvlsseg", Major, Minor);
- break;
- }
+ ISAInfo->addExtension(std::string(1, C), Major, Minor);
+
// Consume full extension name and version, including any optional '_'
// between this extension and the next
++I;
@@ -617,21 +583,6 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
if (*I == '_')
++I;
}
- // Dependency check.
- // It's illegal to specify the 'd' (double-precision floating point)
- // extension without also specifying the 'f' (single precision
- // floating-point) extension.
- // TODO: This has been removed in later specs, which specify that D implies F
- if (HasD && !HasF)
- return createStringError(errc::invalid_argument,
- "d requires f extension to also be specified");
-
- // Additional dependency checks.
- // TODO: The 'q' extension requires rv64.
- // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
-
- if (OtherExts.empty())
- return std::move(ISAInfo);
// Handle other types of extensions other than the standard
// general purpose and standard user-level extensions.
@@ -652,52 +603,53 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"};
auto I = Prefix.begin();
auto E = Prefix.end();
+ if (Split.size() > 1 || Split[0] != "") {
+ for (StringRef Ext : Split) {
+ if (Ext.empty())
+ return createStringError(errc::invalid_argument,
+ "extension name missing after separator '_'");
+
+ StringRef Type = getExtensionType(Ext);
+ StringRef Desc = getExtensionTypeDesc(Ext);
+ auto Pos = findFirstNonVersionCharacter(Ext) + 1;
+ StringRef Name(Ext.substr(0, Pos));
+ StringRef Vers(Ext.substr(Pos));
+
+ if (Type.empty())
+ return createStringError(errc::invalid_argument,
+ "invalid extension prefix '" + Ext + "'");
+
+ // Check ISA extensions are specified in the canonical order.
+ while (I != E && *I != Type)
+ ++I;
+
+ if (I == E)
+ return createStringError(errc::invalid_argument,
+ "%s not given in canonical order '%s'",
+ Desc.str().c_str(), Ext.str().c_str());
+
+ if (Name.size() == Type.size()) {
+ return createStringError(errc::invalid_argument,
+ "%s name missing after '%s'",
+ Desc.str().c_str(), Type.str().c_str());
+ }
- for (StringRef Ext : Split) {
- if (Ext.empty())
- return createStringError(errc::invalid_argument,
- "extension name missing after separator '_'");
-
- StringRef Type = getExtensionType(Ext);
- StringRef Desc = getExtensionTypeDesc(Ext);
- size_t Pos = findFirstNonVersionCharacter(Ext) + 1;
- StringRef Name(Ext.substr(0, Pos));
- StringRef Vers(Ext.substr(Pos));
-
- if (Type.empty())
- return createStringError(errc::invalid_argument,
- "invalid extension prefix '" + Ext + "'");
-
- // Check ISA extensions are specified in the canonical order.
- while (I != E && *I != Type)
- ++I;
-
- if (I == E)
- return createStringError(errc::invalid_argument,
- "%s not given in canonical order '%s'",
- Desc.str().c_str(), Ext.str().c_str());
-
- if (Name.size() == Type.size()) {
- return createStringError(errc::invalid_argument,
- "%s name missing after '%s'", Desc.str().c_str(),
- Type.str().c_str());
+ unsigned Major, Minor, ConsumeLength;
+ if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
+ EnableExperimentalExtension,
+ ExperimentalExtensionVersionCheck))
+ return std::move(E);
+
+ // Check if duplicated extension.
+ if (llvm::is_contained(AllExts, Name))
+ return createStringError(errc::invalid_argument, "duplicated %s '%s'",
+ Desc.str().c_str(), Name.str().c_str());
+
+ ISAInfo->addExtension(Name, Major, Minor);
+ // Extension format is correct, keep parsing the extensions.
+ // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
+ AllExts.push_back(Name);
}
-
- unsigned Major, Minor, ConsumeLength;
- if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
- EnableExperimentalExtension,
- ExperimentalExtensionVersionCheck))
- return std::move(E);
-
- // Check if duplicated extension.
- if (llvm::is_contained(AllExts, Name))
- return createStringError(errc::invalid_argument, "duplicated %s '%s'",
- Desc.str().c_str(), Name.str().c_str());
-
- ISAInfo->addExtension(Name, Major, Minor);
- // Extension format is correct, keep parsing the extensions.
- // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
- AllExts.push_back(Name);
}
for (auto Ext : AllExts) {
@@ -708,11 +660,65 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
}
}
+ ISAInfo->updateImplication();
ISAInfo->updateFLen();
+ if (Error Result = ISAInfo->checkDependency())
+ return std::move(Result);
+
return std::move(ISAInfo);
}
+Error RISCVISAInfo::checkDependency() {
+ bool IsRv32 = XLen == 32;
+ bool HasE = Exts.count("e") == 1;
+ bool HasD = Exts.count("d") == 1;
+ bool HasF = Exts.count("f") == 1;
+
+ if (HasE && !IsRv32)
+ return createStringError(
+ errc::invalid_argument,
+ "standard user-level extension 'e' requires 'rv32'");
+
+ // It's illegal to specify the 'd' (double-precision floating point)
+ // extension without also specifying the 'f' (single precision
+ // floating-point) extension.
+ // TODO: This has been removed in later specs, which specify that D implies F
+ if (HasD && !HasF)
+ return createStringError(errc::invalid_argument,
+ "d requires f extension to also be specified");
+
+ // Additional dependency checks.
+ // TODO: The 'q' extension requires rv64.
+ // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
+
+ return Error::success();
+}
+
+void RISCVISAInfo::updateImplication() {
+ bool HasE = Exts.count("e") == 1;
+ bool HasI = Exts.count("i") == 1;
+ bool HasV = Exts.count("v") == 1;
+ bool HasZfh = Exts.count("zfh") == 1;
+
+ // If not in e extension and i extension does not exist, i extension is
+ // implied
+ if (!HasE && !HasI) {
+ auto Version = findDefaultVersion("i");
+ addExtension("i", Version->Major, Version->Minor);
+ }
+
+ if (HasV) {
+ auto Version = findDefaultVersion("zvlsseg");
+ addExtension("zvlsseg", Version->Major, Version->Minor);
+ }
+
+ if (HasZfh) {
+ auto Version = findDefaultVersion("zfhmin");
+ addExtension("zfhmin", Version->Major, Version->Minor);
+ }
+}
+
void RISCVISAInfo::updateFLen() {
FLen = 0;
// TODO: Handle q extension.
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 53fc70bf745f9..6cc0e1f3e5a57 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -2066,7 +2066,11 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
"unexpected token in '.attribute' directive"))
return true;
- if (Tag == RISCVAttrs::ARCH) {
+ if (IsIntegerValue)
+ getTargetStreamer().emitAttribute(Tag, IntegerValue);
+ else if (Tag != RISCVAttrs::ARCH)
+ getTargetStreamer().emitTextAttribute(Tag, StringValue);
+ else {
StringRef Arch = StringValue;
for (auto Feature : RISCVFeatureKV)
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
@@ -2074,7 +2078,7 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
auto ParseResult = llvm::RISCVISAInfo::parseArchString(
StringValue, /*EnableExperimentalExtension=*/true,
- /*ExperimentalExtensionVersionCheck=*/false);
+ /*ExperimentalExtensionVersionCheck=*/true);
if (!ParseResult) {
std::string Buffer;
raw_string_ostream OutputErrMsg(Buffer);
@@ -2097,35 +2101,9 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
setFeatureBits(RISCV::Feature64Bit, "64bit");
else
return Error(ValueExprLoc, "bad arch string " + Arch);
- }
- if (IsIntegerValue)
- getTargetStreamer().emitAttribute(Tag, IntegerValue);
- else {
- if (Tag != RISCVAttrs::ARCH) {
- getTargetStreamer().emitTextAttribute(Tag, StringValue);
- } else {
- std::vector<std::string> FeatureVector;
- RISCVFeatures::toFeatureVector(FeatureVector, getSTI().getFeatureBits());
-
- // Parse that by RISCVISAInfo->
- unsigned XLen = getFeatureBits(RISCV::Feature64Bit) ? 64 : 32;
- auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);
- if (!ParseResult) {
- std::string Buffer;
- raw_string_ostream OutputErrMsg(Buffer);
- handleAllErrors(ParseResult.takeError(),
- [&](llvm::StringError &ErrMsg) {
- OutputErrMsg << ErrMsg.getMessage();
- });
-
- return Error(ValueExprLoc, OutputErrMsg.str());
- }
- auto &ISAInfo = *ParseResult;
-
- // Then emit the arch string.
- getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
- }
+ // Then emit the arch string.
+ getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
}
return false;
diff --git a/llvm/test/MC/RISCV/attribute-arch-invalid.s b/llvm/test/MC/RISCV/attribute-arch-invalid.s
new file mode 100644
index 0000000000000..73bed8580902b
--- /dev/null
+++ b/llvm/test/MC/RISCV/attribute-arch-invalid.s
@@ -0,0 +1,48 @@
+## Invalid arch string
+
+# RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple riscv64 < %s 2>&1 | FileCheck %s
+
+## Version strings are required for experimental extensions
+
+.attribute arch, "rv32iv"
+# CHECK: error: invalid arch name 'rv32iv', experimental extension requires explicit version number `v`
+
+.attribute arch, "rv32izba"
+# CHECK: error: invalid arch name 'rv32izba', experimental extension requires explicit version number `zba`
+
+.attribute arch, "rv32izbb"
+# CHECK: error: invalid arch name 'rv32izbb', experimental extension requires explicit version number `zbb`
+
+.attribute arch, "rv32izbc"
+# CHECK: error: invalid arch name 'rv32izbc', experimental extension requires explicit version number `zbc`
+
+.attribute arch, "rv32izbe"
+# CHECK: error: invalid arch name 'rv32izbe', experimental extension requires explicit version number `zbe`
+
+.attribute arch, "rv32izbf"
+# CHECK: error: invalid arch name 'rv32izbf', experimental extension requires explicit version number `zbf`
+
+.attribute arch, "rv32izbm"
+# CHECK: error: invalid arch name 'rv32izbm', experimental extension requires explicit version number `zbm`
+
+.attribute arch, "rv32izbp"
+# CHECK: error: invalid arch name 'rv32izbp', experimental extension requires explicit version number `zbp`
+
+.attribute arch, "rv32izbr"
+# CHECK: error: invalid arch name 'rv32izbr', experimental extension requires explicit version number `zbr`
+
+.attribute arch, "rv32izbs"
+# CHECK: error: invalid arch name 'rv32izbs', experimental extension requires explicit version number `zbs`
+
+.attribute arch, "rv32izbt"
+# CHECK: error: invalid arch name 'rv32izbt', experimental extension requires explicit version number `zbt`
+
+.attribute arch, "rv32ifzfhmin"
+# CHECK: error: invalid arch name 'rv32ifzfhmin', experimental extension requires explicit version number `zfhmin`
+
+.attribute arch, "rv32ifzfh"
+# CHECK: error: invalid arch name 'rv32ifzfh', experimental extension requires explicit version number `zfh`
+
+.attribute arch, "rv32ivzvamo_zvlsseg"
+# CHECK: error: invalid arch name 'rv32ivzvamo_zvlsseg', experimental extension requires explicit version number `v`
diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s
index 9edc0aacda037..2928222b64fff 100644
--- a/llvm/test/MC/RISCV/attribute-arch.s
+++ b/llvm/test/MC/RISCV/attribute-arch.s
@@ -33,47 +33,46 @@
.attribute arch, "rv32ima2p0_fdc"
# CHECK: attribute 5, "rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
-.attribute arch, "rv32iv"
+## Experimental extensions require version string to be explicitly specified
+
+.attribute arch, "rv32iv0p10"
# CHECK: attribute 5, "rv32i2p0_v0p10_zvlsseg0p10"
-.attribute arch, "rv32izba"
+.attribute arch, "rv32izba1p0"
# CHECK: attribute 5, "rv32i2p0_zba1p0"
-.attribute arch, "rv32izbb"
+.attribute arch, "rv32izbb1p0"
# CHECK: attribute 5, "rv32i2p0_zbb1p0"
-.attribute arch, "rv32izbc"
+.attribute arch, "rv32izbc1p0"
# CHECK: attribute 5, "rv32i2p0_zbc1p0"
-.attribute arch, "rv32izbe"
+.attribute arch, "rv32izbe0p93"
# CHECK: attribute 5, "rv32i2p0_zbe0p93"
-.attribute arch, "rv32izbf"
+.attribute arch, "rv32izbf0p93"
# CHECK: attribute 5, "rv32i2p0_zbf0p93"
-.attribute arch, "rv32izbm"
+.attribute arch, "rv32izbm0p93"
# CHECK: attribute 5, "rv32i2p0_zbm0p93"
-.attribute arch, "rv32izbp"
+.attribute arch, "rv32izbp0p93"
# CHECK: attribute 5, "rv32i2p0_zbp0p93"
-.attribute arch, "rv32izbr"
+.attribute arch, "rv32izbr0p93"
# CHECK: attribute 5, "rv32i2p0_zbr0p93"
-.attribute arch, "rv32izbs"
+.attribute arch, "rv32izbs1p0"
# CHECK: attribute 5, "rv32i2p0_zbs1p0"
-.attribute arch, "rv32izbt"
+.attribute arch, "rv32izbt0p93"
# CHECK: attribute 5, "rv32i2p0_zbt0p93"
-.attribute arch, "rv32ifzfhmin"
+.attribute arch, "rv32ifzfhmin0p1"
# CHECK: attribute 5, "rv32i2p0_f2p0_zfhmin0p1"
-.attribute arch, "rv32ifzfh"
+.attribute arch, "rv32ifzfh0p1"
# CHECK: attribute 5, "rv32i2p0_f2p0_zfh0p1_zfhmin0p1"
-.attribute arch, "rv32ivzvamo_zvlsseg"
-# CHECK: attribute 5, "rv32i2p0_v0p10_zvamo0p10_zvlsseg0p10"
-
-.attribute arch, "rv32iv_zvamo0p10_zvlsseg"
+.attribute arch, "rv32iv0p10zvamo0p10_zvlsseg0p10"
# CHECK: attribute 5, "rv32i2p0_v0p10_zvamo0p10_zvlsseg0p10"
More information about the llvm-commits
mailing list