Skip to content

Commit ff93c9b

Browse files
committed
[lld][RISCV] Avoid error when encountering unrecognised ISA extensions/versions in RISC-V attributes
This patch follows on from this RFC thread <https://discourse.llvm.org/t/rfc-resolving-issues-related-to-extension-versioning-in-risc-v/68472/> and the ensuing discussion in the RISC-V LLVM sync-up call. The consensus agreed that the behaviour change in LLD introduced in D138550 that results in object files including arch attributes with unrecognised extensions or versions of extensions is a regression and should be treated as such. As it stands, this logic means that LLD will error out if trying to link a RISC-V object file from LLVM HEAD (rv32i2p0/rv64i2p0) with one from current GCC (rv32i2p1/rv64i2p1 by default). There's a bigger discussion about exactly when to warn vs error and so on, and how to control that, and this patch doesn't attempt to address all those questions. It simply tries to fix the problem with a minimally invasive change, intended to be cherry-picked for 16.0.x (ideally 16.0.0, but queued for 16.0.1 if we're too late in the release cycle). As you can see from the test changes, although the changed logic is mostly more permissive, it will reject some embedded arch strings that were accepted before. Because the same logic was previously used for parsing human-written -march as for the arch attribute (intended to be stored in normalised form), various short-hand formats were previously accepted. Maintaining support for such ill-formed attributes would substantially complicate the logic, and given the previous implementation was so much stricter in every other way, was surely a bug rather than a design choice. Surprisingly, the precise rules for how numbers can be embedded into extension names isn't fully defined (there is a PR to the ISA manual that is not yet merged <riscv/riscv-isa-manual#718>). In the absence of specific criteria for rejecting extensions names that would be ambiguous in abbreviated form, `RISCVISAInfo::parseArchStringNormalized` just pulls out the version information from the end of each extension description. Differential Revision: https://reviews.llvm.org/D144353
1 parent 7d5275e commit ff93c9b

File tree

6 files changed

+263
-29
lines changed

6 files changed

+263
-29
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,7 @@ class RISCVAttributesSection final : public SyntheticSection {
848848
static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts,
849849
unsigned &mergedXlen, const InputSectionBase *sec,
850850
StringRef s) {
851-
auto maybeInfo =
852-
RISCVISAInfo::parseArchString(s, /*EnableExperimentalExtension=*/true,
853-
/*ExperimentalExtensionVersionCheck=*/true);
851+
auto maybeInfo = RISCVISAInfo::parseNormalizedArchString(s);
854852
if (!maybeInfo) {
855853
errorOrWarn(toString(sec) + ": " + s + ": " +
856854
llvm::toString(maybeInfo.takeError()));
@@ -865,8 +863,6 @@ static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts,
865863
} else {
866864
for (const auto &ext : info.getExtensions()) {
867865
if (auto it = mergedExts.find(ext.first); it != mergedExts.end()) {
868-
// TODO This is untested because RISCVISAInfo::parseArchString does not
869-
// accept unsupported versions yet.
870866
if (std::tie(it->second.MajorVersion, it->second.MinorVersion) >=
871867
std::tie(ext.second.MajorVersion, ext.second.MinorVersion))
872868
continue;

lld/test/ELF/riscv-attributes.s

Lines changed: 89 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,24 @@
1515
# RUN: llvm-readobj --arch-specific out2 | FileCheck %s --check-prefix=CHECK2
1616

1717
# RUN: llvm-mc -filetype=obj -triple=riscv64 unrecognized_ext1.s -o unrecognized_ext1.o
18-
# RUN: not ld.lld unrecognized_ext1.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNRECOGNIZED_EXT1 --implicit-check-not=error:
19-
# UNRECOGNIZED_EXT1: error: unrecognized_ext1.o:(.riscv.attributes): rv64i2p0_y2p0: invalid standard user-level extension 'y'
18+
# RUN: ld.lld -e 0 unrecognized_ext1.o -o unrecognized_ext1 2>&1 | count 0
19+
# RUN: llvm-readobj --arch-specific unrecognized_ext1 | FileCheck %s --check-prefix=UNRECOGNIZED_EXT1
2020

2121
# RUN: llvm-mc -filetype=obj -triple=riscv64 unrecognized_ext2.s -o unrecognized_ext2.o
22-
# RUN: not ld.lld unrecognized_ext2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNRECOGNIZED_EXT2 --implicit-check-not=error:
23-
# UNRECOGNIZED_EXT2: error: unrecognized_ext2.o:(.riscv.attributes): rv64i2p0_zmadeup1p0: unsupported version number 1.0 for extension 'zmadeup'
22+
# RUN: ld.lld -e 0 unrecognized_ext2.o -o unrecognized_ext2 2>&1 | count 0
23+
# RUN: llvm-readobj --arch-specific unrecognized_ext2 | FileCheck %s --check-prefix=UNRECOGNIZED_EXT2
2424

2525
# RUN: llvm-mc -filetype=obj -triple=riscv64 unrecognized_version.s -o unrecognized_version.o
26-
# RUN: not ld.lld unrecognized_version.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNRECOGNIZED_VERSION --implicit-check-not=error:
27-
# UNRECOGNIZED_VERSION: error: unrecognized_version.o:(.riscv.attributes): rv64i99p0: unsupported version number 99.0 for extension 'i'
26+
# RUN: ld.lld -e 0 unrecognized_version.o -o unrecognized_version 2>&1 | count 0
27+
# RUN: llvm-readobj --arch-specific unrecognized_version | FileCheck %s --check-prefix=UNRECOGNIZED_VERSION
28+
29+
# RUN: llvm-mc -filetype=obj -triple=riscv64 merge_version_test_input.s -o merge_version_test_input.o
30+
# RUN: ld.lld -e 0 unrecognized_version.o merge_version_test_input.o -o out3 2>&1 | count 0
31+
# RUN: llvm-readobj --arch-specific out3 | FileCheck %s --check-prefix=CHECK3
2832

2933
# RUN: llvm-mc -filetype=obj -triple=riscv64 invalid_arch1.s -o invalid_arch1.o
30-
# RUN: ld.lld -e 0 invalid_arch1.o -o invalid_arch1
31-
# RUN: llvm-readobj --arch-specific invalid_arch1 | FileCheck %s --check-prefix=INVALID_ARCH1
34+
# RUN: not ld.lld invalid_arch1.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=INVALID_ARCH1 --implicit-check-not=error:
35+
# INVALID_ARCH1: error: invalid_arch1.o:(.riscv.attributes): rv64i2: extension lacks version in expected format
3236

3337
## A zero value attribute is not printed.
3438
# RUN: llvm-mc -filetype=obj -triple=riscv64 unaligned_access_0.s -o unaligned_access_0.o
@@ -121,6 +125,23 @@
121125
# CHECK2-NEXT: }
122126
# CHECK2-NEXT: }
123127

128+
# CHECK3: BuildAttributes {
129+
# CHECK3-NEXT: FormatVersion: 0x41
130+
# CHECK3-NEXT: Section 1 {
131+
# CHECK3-NEXT: SectionLength: 26
132+
# CHECK3-NEXT: Vendor: riscv
133+
# CHECK3-NEXT: Tag: Tag_File (0x1)
134+
# CHECK3-NEXT: Size: 16
135+
# CHECK3-NEXT: FileAttributes {
136+
# CHECK3-NEXT: Attribute {
137+
# CHECK3-NEXT: Tag: 5
138+
# CHECK3-NEXT: TagName: arch
139+
# CHECK3-NEXT: Value: rv64i99p0
140+
# CHECK3-NEXT: }
141+
# CHECK3-NEXT: }
142+
# CHECK3-NEXT: }
143+
# CHECK3-NEXT: }
144+
124145
#--- a.s
125146
.attribute stack_align, 16
126147
.attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
@@ -140,6 +161,22 @@
140161
.attribute priv_spec_minor, 2
141162

142163
#--- unrecognized_ext1.s
164+
# UNRECOGNIZED_EXT1: BuildAttributes {
165+
# UNRECOGNIZED_EXT1-NEXT: FormatVersion: 0x41
166+
# UNRECOGNIZED_EXT1-NEXT: Section 1 {
167+
# UNRECOGNIZED_EXT1-NEXT: SectionLength: 30
168+
# UNRECOGNIZED_EXT1-NEXT: Vendor: riscv
169+
# UNRECOGNIZED_EXT1-NEXT: Tag: Tag_File (0x1)
170+
# UNRECOGNIZED_EXT1-NEXT: Size: 20
171+
# UNRECOGNIZED_EXT1-NEXT: FileAttributes {
172+
# UNRECOGNIZED_EXT1-NEXT: Attribute {
173+
# UNRECOGNIZED_EXT1-NEXT: Tag: 5
174+
# UNRECOGNIZED_EXT1-NEXT: TagName: arch
175+
# UNRECOGNIZED_EXT1-NEXT: Value: rv64i2p0_y2p0
176+
# UNRECOGNIZED_EXT1-NEXT: }
177+
# UNRECOGNIZED_EXT1-NEXT: }
178+
# UNRECOGNIZED_EXT1-NEXT: }
179+
# UNRECOGNIZED_EXT1-NEXT: }
143180
.section .riscv.attributes,"",@0x70000003
144181
.byte 0x41
145182
.long .Lend-.riscv.attributes-1
@@ -152,6 +189,22 @@
152189
.Lend:
153190

154191
#--- unrecognized_ext2.s
192+
# UNRECOGNIZED_EXT2: BuildAttributes {
193+
# UNRECOGNIZED_EXT2-NEXT: FormatVersion: 0x41
194+
# UNRECOGNIZED_EXT2-NEXT: Section 1 {
195+
# UNRECOGNIZED_EXT2-NEXT: SectionLength: 36
196+
# UNRECOGNIZED_EXT2-NEXT: Vendor: riscv
197+
# UNRECOGNIZED_EXT2-NEXT: Tag: Tag_File (0x1)
198+
# UNRECOGNIZED_EXT2-NEXT: Size: 26
199+
# UNRECOGNIZED_EXT2-NEXT: FileAttributes {
200+
# UNRECOGNIZED_EXT2-NEXT: Attribute {
201+
# UNRECOGNIZED_EXT2-NEXT: Tag: 5
202+
# UNRECOGNIZED_EXT2-NEXT: TagName: arch
203+
# UNRECOGNIZED_EXT2-NEXT: Value: rv64i2p0_zmadeup1p0
204+
# UNRECOGNIZED_EXT2-NEXT: }
205+
# UNRECOGNIZED_EXT2-NEXT: }
206+
# UNRECOGNIZED_EXT2-NEXT: }
207+
# UNRECOGNIZED_EXT2-NEXT: }
155208
.section .riscv.attributes,"",@0x70000003
156209
.byte 0x41
157210
.long .Lend-.riscv.attributes-1
@@ -164,6 +217,22 @@
164217
.Lend:
165218

166219
#--- unrecognized_version.s
220+
# UNRECOGNIZED_VERSION: BuildAttributes {
221+
# UNRECOGNIZED_VERSION-NEXT: FormatVersion: 0x41
222+
# UNRECOGNIZED_VERSION-NEXT: Section 1 {
223+
# UNRECOGNIZED_VERSION-NEXT: SectionLength: 26
224+
# UNRECOGNIZED_VERSION-NEXT: Vendor: riscv
225+
# UNRECOGNIZED_VERSION-NEXT: Tag: Tag_File (0x1)
226+
# UNRECOGNIZED_VERSION-NEXT: Size: 16
227+
# UNRECOGNIZED_VERSION-NEXT: FileAttributes {
228+
# UNRECOGNIZED_VERSION-NEXT: Attribute {
229+
# UNRECOGNIZED_VERSION-NEXT: Tag: 5
230+
# UNRECOGNIZED_VERSION-NEXT: TagName: arch
231+
# UNRECOGNIZED_VERSION-NEXT: Value: rv64i99p0
232+
# UNRECOGNIZED_VERSION-NEXT: }
233+
# UNRECOGNIZED_VERSION-NEXT: }
234+
# UNRECOGNIZED_VERSION-NEXT: }
235+
# UNRECOGNIZED_VERSION-NEXT: }
167236
.section .riscv.attributes,"",@0x70000003
168237
.byte 0x41
169238
.long .Lend-.riscv.attributes-1
@@ -175,23 +244,19 @@
175244
.asciz "rv64i99p0"
176245
.Lend:
177246

247+
#--- merge_version_test_input.s
248+
.section .riscv.attributes,"",@0x70000003
249+
.byte 0x41
250+
.long .Lend-.riscv.attributes-1
251+
.asciz "riscv" # vendor
252+
.Lbegin:
253+
.byte 1 # Tag_File
254+
.long .Lend-.Lbegin
255+
.byte 5 # Tag_RISCV_arch
256+
.asciz "rv64i2p1"
257+
.Lend:
258+
178259
#--- invalid_arch1.s
179-
# INVALID_ARCH1: BuildAttributes {
180-
# INVALID_ARCH1-NEXT: FormatVersion: 0x41
181-
# INVALID_ARCH1-NEXT: Section 1 {
182-
# INVALID_ARCH1-NEXT: SectionLength: 25
183-
# INVALID_ARCH1-NEXT: Vendor: riscv
184-
# INVALID_ARCH1-NEXT: Tag: Tag_File (0x1)
185-
# INVALID_ARCH1-NEXT: Size: 15
186-
# INVALID_ARCH1-NEXT: FileAttributes {
187-
# INVALID_ARCH1-NEXT: Attribute {
188-
# INVALID_ARCH1-NEXT: Tag: 5
189-
# INVALID_ARCH1-NEXT: TagName: arch
190-
# INVALID_ARCH1-NEXT: Value: rv64i2p0
191-
# INVALID_ARCH1-NEXT: }
192-
# INVALID_ARCH1-NEXT: }
193-
# INVALID_ARCH1-NEXT: }
194-
# INVALID_ARCH1-NEXT: }
195260
.section .riscv.attributes,"",@0x70000003
196261
.byte 0x41
197262
.long .Lend-.riscv.attributes-1

llvm/include/llvm/Support/RISCVISAInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ class RISCVISAInfo {
5151
bool ExperimentalExtensionVersionCheck = true,
5252
bool IgnoreUnknown = false);
5353

54+
/// Parse RISCV ISA info from an arch string that is already in normalized
55+
/// form (as defined in the psABI). Unlike parseArchString, this function
56+
/// will not error for unrecognized extension names or extension versions.
57+
static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
58+
parseNormalizedArchString(StringRef Arch);
59+
5460
/// Parse RISCV ISA info from feature vector.
5561
static llvm::Expected<std::unique_ptr<RISCVISAInfo>>
5662
parseFeatures(unsigned XLen, const std::vector<std::string> &Features);

llvm/lib/Support/RISCVISAInfo.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,67 @@ RISCVISAInfo::parseFeatures(unsigned XLen,
519519
return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
520520
}
521521

522+
llvm::Expected<std::unique_ptr<RISCVISAInfo>>
523+
RISCVISAInfo::parseNormalizedArchString(StringRef Arch) {
524+
if (llvm::any_of(Arch, isupper)) {
525+
return createStringError(errc::invalid_argument,
526+
"string must be lowercase");
527+
}
528+
// Must start with a valid base ISA name.
529+
unsigned XLen;
530+
if (Arch.startswith("rv32i") || Arch.startswith("rv32e"))
531+
XLen = 32;
532+
else if (Arch.startswith("rv64i") || Arch.startswith("rv64e"))
533+
XLen = 64;
534+
else
535+
return createStringError(errc::invalid_argument,
536+
"arch string must begin with valid base ISA");
537+
std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
538+
// Discard rv32/rv64 prefix.
539+
Arch = Arch.substr(4);
540+
541+
// Each extension is of the form ${name}${major_version}p${minor_version}
542+
// and separated by _. Split by _ and then extract the name and version
543+
// information for each extension.
544+
SmallVector<StringRef, 8> Split;
545+
Arch.split(Split, '_');
546+
for (StringRef Ext : Split) {
547+
StringRef Prefix, MinorVersionStr;
548+
std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p');
549+
if (MinorVersionStr.empty())
550+
return createStringError(errc::invalid_argument,
551+
"extension lacks version in expected format");
552+
unsigned MajorVersion, MinorVersion;
553+
if (MinorVersionStr.getAsInteger(10, MinorVersion))
554+
return createStringError(errc::invalid_argument,
555+
"failed to parse minor version number");
556+
557+
// Split Prefix into the extension name and the major version number
558+
// (the trailing digits of Prefix).
559+
int TrailingDigits = 0;
560+
StringRef ExtName = Prefix;
561+
while (!ExtName.empty()) {
562+
if (!isDigit(ExtName.back()))
563+
break;
564+
ExtName = ExtName.drop_back(1);
565+
TrailingDigits++;
566+
}
567+
if (!TrailingDigits)
568+
return createStringError(errc::invalid_argument,
569+
"extension lacks version in expected format");
570+
571+
StringRef MajorVersionStr = Prefix.take_back(TrailingDigits);
572+
if (MajorVersionStr.getAsInteger(10, MajorVersion))
573+
return createStringError(errc::invalid_argument,
574+
"failed to parse major version number");
575+
ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion);
576+
}
577+
ISAInfo->updateFLen();
578+
ISAInfo->updateMinVLen();
579+
ISAInfo->updateMaxELen();
580+
return std::move(ISAInfo);
581+
}
582+
522583
llvm::Expected<std::unique_ptr<RISCVISAInfo>>
523584
RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
524585
bool ExperimentalExtensionVersionCheck,

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ add_llvm_unittest(SupportTests
6868
ReverseIterationTest.cpp
6969
ReplaceFileTest.cpp
7070
RISCVAttributeParserTest.cpp
71+
RISCVISAInfoTest.cpp
7172
ScaledNumberTest.cpp
7273
ScopedPrinterTest.cpp
7374
SHA256.cpp
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//===-- unittests/RISCVISAInfoTest.cpp ------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Support/RISCVISAInfo.h"
10+
#include "llvm/Testing/Support/Error.h"
11+
#include "gtest/gtest.h"
12+
13+
using namespace llvm;
14+
15+
bool operator==(const llvm::RISCVExtensionInfo &A,
16+
const llvm::RISCVExtensionInfo &B) {
17+
return A.ExtName == B.ExtName && A.MajorVersion == B.MajorVersion &&
18+
A.MinorVersion == B.MinorVersion;
19+
}
20+
21+
TEST(ParseNormalizedArchString, RejectsUpperCase) {
22+
for (StringRef Input : {"RV32", "rV64", "rv32i2P0", "rv64i2p0_A2p0"}) {
23+
EXPECT_EQ(
24+
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
25+
"string must be lowercase");
26+
}
27+
}
28+
29+
TEST(ParseNormalizedArchString, RejectsInvalidBaseISA) {
30+
for (StringRef Input : {"rv32", "rv64", "rv32j", "rv65i"}) {
31+
EXPECT_EQ(
32+
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
33+
"arch string must begin with valid base ISA");
34+
}
35+
}
36+
37+
TEST(ParseNormalizedArchString, RejectsMalformedInputs) {
38+
for (StringRef Input : {"rv64i2p0_", "rv32i2p0__a2p0", "rv32e2.0", "rv64e2p",
39+
"rv32i", "rv64ip1"}) {
40+
EXPECT_EQ(
41+
toString(RISCVISAInfo::parseNormalizedArchString(Input).takeError()),
42+
"extension lacks version in expected format");
43+
}
44+
}
45+
46+
TEST(ParseNormalizedArchString, AcceptsValidBaseISAsAndSetsXLen) {
47+
auto MaybeRV32I = RISCVISAInfo::parseNormalizedArchString("rv32i2p0");
48+
ASSERT_THAT_EXPECTED(MaybeRV32I, Succeeded());
49+
RISCVISAInfo &InfoRV32I = **MaybeRV32I;
50+
EXPECT_EQ(InfoRV32I.getExtensions().size(), 1UL);
51+
EXPECT_TRUE(InfoRV32I.getExtensions().at("i") ==
52+
(RISCVExtensionInfo{"i", 2, 0}));
53+
EXPECT_EQ(InfoRV32I.getXLen(), 32U);
54+
55+
auto MaybeRV32E = RISCVISAInfo::parseNormalizedArchString("rv32e2p0");
56+
ASSERT_THAT_EXPECTED(MaybeRV32E, Succeeded());
57+
RISCVISAInfo &InfoRV32E = **MaybeRV32E;
58+
EXPECT_EQ(InfoRV32E.getExtensions().size(), 1UL);
59+
EXPECT_TRUE(InfoRV32E.getExtensions().at("e") ==
60+
(RISCVExtensionInfo{"e", 2, 0}));
61+
EXPECT_EQ(InfoRV32I.getXLen(), 32U);
62+
63+
auto MaybeRV64I = RISCVISAInfo::parseNormalizedArchString("rv64i2p0");
64+
ASSERT_THAT_EXPECTED(MaybeRV64I, Succeeded());
65+
RISCVISAInfo &InfoRV64I = **MaybeRV64I;
66+
EXPECT_EQ(InfoRV64I.getExtensions().size(), 1UL);
67+
EXPECT_TRUE(InfoRV64I.getExtensions().at("i") ==
68+
(RISCVExtensionInfo{"i", 2, 0}));
69+
EXPECT_EQ(InfoRV64I.getXLen(), 64U);
70+
71+
auto MaybeRV64E = RISCVISAInfo::parseNormalizedArchString("rv64e2p0");
72+
ASSERT_THAT_EXPECTED(MaybeRV64E, Succeeded());
73+
RISCVISAInfo &InfoRV64E = **MaybeRV64E;
74+
EXPECT_EQ(InfoRV64E.getExtensions().size(), 1UL);
75+
EXPECT_TRUE(InfoRV64E.getExtensions().at("e") ==
76+
(RISCVExtensionInfo{"e", 2, 0}));
77+
EXPECT_EQ(InfoRV64I.getXLen(), 64U);
78+
}
79+
80+
TEST(ParseNormalizedArchString, AcceptsArbitraryExtensionsAndVersions) {
81+
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
82+
"rv64i5p1_m3p2_zmadeup11p12_sfoo2p0_xbar3p0");
83+
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
84+
RISCVISAInfo &Info = **MaybeISAInfo;
85+
EXPECT_EQ(Info.getExtensions().size(), 5UL);
86+
EXPECT_TRUE(Info.getExtensions().at("i") == (RISCVExtensionInfo{"i", 5, 1}));
87+
EXPECT_TRUE(Info.getExtensions().at("m") == (RISCVExtensionInfo{"m", 3, 2}));
88+
EXPECT_TRUE(Info.getExtensions().at("zmadeup") ==
89+
(RISCVExtensionInfo{"zmadeup", 11, 12}));
90+
EXPECT_TRUE(Info.getExtensions().at("sfoo") ==
91+
(RISCVExtensionInfo{"sfoo", 2, 0}));
92+
EXPECT_TRUE(Info.getExtensions().at("xbar") ==
93+
(RISCVExtensionInfo{"xbar", 3, 0}));
94+
}
95+
96+
TEST(ParseNormalizedArchString, UpdatesFLenMinVLenMaxELen) {
97+
auto MaybeISAInfo = RISCVISAInfo::parseNormalizedArchString(
98+
"rv64i2p0_d2p0_zvl64b1p0_zve64d1p0");
99+
ASSERT_THAT_EXPECTED(MaybeISAInfo, Succeeded());
100+
RISCVISAInfo &Info = **MaybeISAInfo;
101+
EXPECT_EQ(Info.getXLen(), 64U);
102+
EXPECT_EQ(Info.getFLen(), 64U);
103+
EXPECT_EQ(Info.getMinVLen(), 64U);
104+
EXPECT_EQ(Info.getMaxELen(), 64U);
105+
}

0 commit comments

Comments
 (0)