Skip to content

Commit d867988

Browse files
authored
[DataLayout] Refactor parsing of "ni" specification (#104546)
Split off of #104545 to reduce patch size. This introduces `parseAddrSpace` function, intended as a replacement for `getAddrSpace`, which doesn't check for trailing characters after the address space number. `getAddrSpace` will be removed after switching all uses to `parseAddrSpace`. Pull Request: #104546
1 parent a84790e commit d867988

File tree

2 files changed

+77
-16
lines changed

2 files changed

+77
-16
lines changed

Diff for: llvm/lib/IR/DataLayout.cpp

+36-16
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,22 @@ static Error reportError(const Twine &Message) {
272272
return createStringError(inconvertibleErrorCode(), Message);
273273
}
274274

275+
static Error createSpecFormatError(Twine Format) {
276+
return createStringError("malformed specification, must be of the form \"" +
277+
Format + "\"");
278+
}
279+
280+
/// Attempts to parse an address space component of a specification.
281+
static Error parseAddrSpace(StringRef Str, unsigned &AddrSpace) {
282+
if (Str.empty())
283+
return createStringError("address space component cannot be empty");
284+
285+
if (!to_integer(Str, AddrSpace, 10) || !isUInt<24>(AddrSpace))
286+
return createStringError("address space must be a 24-bit integer");
287+
288+
return Error::success();
289+
}
290+
275291
/// Checked version of split, to ensure mandatory subparts.
276292
static Error split(StringRef Str, char Separator,
277293
std::pair<StringRef, StringRef> &Split) {
@@ -313,6 +329,26 @@ static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
313329
}
314330

315331
Error DataLayout::parseSpecification(StringRef Spec) {
332+
// The "ni" specifier is the only two-character specifier. Handle it first.
333+
if (Spec.starts_with("ni")) {
334+
// ni:<address space>[:<address space>]...
335+
StringRef Rest = Spec.drop_front(2);
336+
337+
// Drop the first ':', then split the rest of the string the usual way.
338+
if (!Rest.consume_front(":"))
339+
return createSpecFormatError("ni:<address space>[:<address space>]...");
340+
341+
for (StringRef Str : split(Rest, ':')) {
342+
unsigned AddrSpace;
343+
if (Error Err = parseAddrSpace(Str, AddrSpace))
344+
return Err;
345+
if (AddrSpace == 0)
346+
return createStringError("address space 0 cannot be non-integral");
347+
NonIntegralAddressSpaces.push_back(AddrSpace);
348+
}
349+
return Error::success();
350+
}
351+
316352
// Split at ':'.
317353
std::pair<StringRef, StringRef> Split;
318354
if (Error Err = ::split(Spec, ':', Split))
@@ -322,22 +358,6 @@ Error DataLayout::parseSpecification(StringRef Spec) {
322358
StringRef &Tok = Split.first; // Current token.
323359
StringRef &Rest = Split.second; // The rest of the string.
324360

325-
if (Tok == "ni") {
326-
do {
327-
if (Error Err = ::split(Rest, ':', Split))
328-
return Err;
329-
Rest = Split.second;
330-
unsigned AS;
331-
if (Error Err = getInt(Split.first, AS))
332-
return Err;
333-
if (AS == 0)
334-
return reportError("Address space 0 can never be non-integral");
335-
NonIntegralAddressSpaces.push_back(AS);
336-
} while (!Rest.empty());
337-
338-
return Error::success();
339-
}
340-
341361
char SpecifierChar = Tok.front();
342362
Tok = Tok.substr(1);
343363

Diff for: llvm/unittests/IR/DataLayoutTest.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,47 @@ TEST(DataLayout, LayoutStringFormat) {
134134
FailedWithMessage("empty specification is not allowed"));
135135
}
136136

137+
TEST(DataLayout, ParseNonIntegralAddrSpace) {
138+
for (StringRef Str : {"ni:1", "ni:16777215", "ni:1:16777215"})
139+
EXPECT_THAT_EXPECTED(DataLayout::parse(Str), Succeeded());
140+
141+
for (StringRef Str : {"ni", "ni42", "nix"})
142+
EXPECT_THAT_EXPECTED(
143+
DataLayout::parse(Str),
144+
FailedWithMessage("malformed specification, must be of the form "
145+
"\"ni:<address space>[:<address space>]...\""));
146+
147+
for (StringRef Str : {"ni:", "ni::42", "ni:42:"})
148+
EXPECT_THAT_EXPECTED(
149+
DataLayout::parse(Str),
150+
FailedWithMessage("address space component cannot be empty"));
151+
152+
for (StringRef Str : {"ni:x", "ni:42:0x1", "ni:16777216", "ni:42:16777216"})
153+
EXPECT_THAT_EXPECTED(
154+
DataLayout::parse(Str),
155+
FailedWithMessage("address space must be a 24-bit integer"));
156+
157+
for (StringRef Str : {"ni:0", "ni:42:0"})
158+
EXPECT_THAT_EXPECTED(
159+
DataLayout::parse(Str),
160+
FailedWithMessage("address space 0 cannot be non-integral"));
161+
}
162+
163+
TEST(DataLayout, IsNonIntegralAddressSpace) {
164+
DataLayout Default;
165+
EXPECT_THAT(Default.getNonIntegralAddressSpaces(), ::testing::SizeIs(0));
166+
EXPECT_FALSE(Default.isNonIntegralAddressSpace(0));
167+
EXPECT_FALSE(Default.isNonIntegralAddressSpace(1));
168+
169+
DataLayout Custom = cantFail(DataLayout::parse("ni:2:16777215"));
170+
EXPECT_THAT(Custom.getNonIntegralAddressSpaces(),
171+
::testing::ElementsAreArray({2U, 16777215U}));
172+
EXPECT_FALSE(Custom.isNonIntegralAddressSpace(0));
173+
EXPECT_FALSE(Custom.isNonIntegralAddressSpace(1));
174+
EXPECT_TRUE(Custom.isNonIntegralAddressSpace(2));
175+
EXPECT_TRUE(Custom.isNonIntegralAddressSpace(16777215));
176+
}
177+
137178
TEST(DataLayoutTest, CopyAssignmentInvalidatesStructLayout) {
138179
DataLayout DL1 = cantFail(DataLayout::parse("p:32:32"));
139180
DataLayout DL2 = cantFail(DataLayout::parse("p:64:64"));

0 commit comments

Comments
 (0)