Skip to content

Commit 2b09a89

Browse files
committed
[OpAsmParser] Refactor parseOptionalInteger to support wide integers, NFC.
OpAsmParser (and DialectAsmParser) supports a pair of parseInteger/parseOptionalInteger methods, which allow parsing a bare integer into a C type of your choice (e.g. int8_t) using templates. It was implemented in terms of a virtual method call that is hard coded to int64_t because "that should be big enough". Change the virtual method hook to return an APInt instead. This allows asmparsers for custom ops to parse large integers if they want to, without changing any of the clients of the fixed size C API. Differential Revision: https://reviews.llvm.org/D102120
1 parent ad558a4 commit 2b09a89

File tree

5 files changed

+39
-21
lines changed

5 files changed

+39
-21
lines changed

mlir/include/mlir/IR/DialectImplementation.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ class DialectAsmParser {
139139
virtual ParseResult parseFloat(double &result) = 0;
140140

141141
/// Parse an integer value from the stream.
142-
template <typename IntT> ParseResult parseInteger(IntT &result) {
142+
template <typename IntT>
143+
ParseResult parseInteger(IntT &result) {
143144
auto loc = getCurrentLocation();
144145
OptionalParseResult parseResult = parseOptionalInteger(result);
145146
if (!parseResult.hasValue())
@@ -148,21 +149,24 @@ class DialectAsmParser {
148149
}
149150

150151
/// Parse an optional integer value from the stream.
151-
virtual OptionalParseResult parseOptionalInteger(uint64_t &result) = 0;
152+
virtual OptionalParseResult parseOptionalInteger(APInt &result) = 0;
152153

153154
template <typename IntT>
154155
OptionalParseResult parseOptionalInteger(IntT &result) {
155156
auto loc = getCurrentLocation();
156157

157158
// Parse the unsigned variant.
158-
uint64_t uintResult;
159+
APInt uintResult;
159160
OptionalParseResult parseResult = parseOptionalInteger(uintResult);
160161
if (!parseResult.hasValue() || failed(*parseResult))
161162
return parseResult;
162163

163-
// Try to convert to the provided integer type.
164-
result = IntT(uintResult);
165-
if (uint64_t(result) != uintResult)
164+
// Try to convert to the provided integer type. sextOrTrunc is correct even
165+
// for unsigned types because parseOptionalInteger ensures the sign bit is
166+
// zero for non-negated integers.
167+
result =
168+
(IntT)uintResult.sextOrTrunc(sizeof(IntT) * CHAR_BIT).getLimitedValue();
169+
if (APInt(uintResult.getBitWidth(), result) != uintResult)
166170
return emitError(loc, "integer value too large");
167171
return success();
168172
}
@@ -172,13 +176,14 @@ class DialectAsmParser {
172176
/// unlike `OpBuilder::getType`, this method does not implicitly insert a
173177
/// context parameter.
174178
template <typename T, typename... ParamsT>
175-
T getChecked(llvm::SMLoc loc, ParamsT &&...params) {
179+
T getChecked(llvm::SMLoc loc, ParamsT &&... params) {
176180
return T::getChecked([&] { return emitError(loc); },
177181
std::forward<ParamsT>(params)...);
178182
}
179183
/// A variant of `getChecked` that uses the result of `getNameLoc` to emit
180184
/// errors.
181-
template <typename T, typename... ParamsT> T getChecked(ParamsT &&...params) {
185+
template <typename T, typename... ParamsT>
186+
T getChecked(ParamsT &&... params) {
182187
return T::getChecked([&] { return emitError(getNameLoc()); },
183188
std::forward<ParamsT>(params)...);
184189
}
@@ -331,7 +336,8 @@ class DialectAsmParser {
331336
virtual ParseResult parseType(Type &result) = 0;
332337

333338
/// Parse a type of a specific kind, e.g. a FunctionType.
334-
template <typename TypeType> ParseResult parseType(TypeType &result) {
339+
template <typename TypeType>
340+
ParseResult parseType(TypeType &result) {
335341
llvm::SMLoc loc = getCurrentLocation();
336342

337343
// Parse any kind of type.

mlir/include/mlir/IR/OpImplementation.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -435,21 +435,24 @@ class OpAsmParser {
435435
}
436436

437437
/// Parse an optional integer value from the stream.
438-
virtual OptionalParseResult parseOptionalInteger(uint64_t &result) = 0;
438+
virtual OptionalParseResult parseOptionalInteger(APInt &result) = 0;
439439

440440
template <typename IntT>
441441
OptionalParseResult parseOptionalInteger(IntT &result) {
442442
auto loc = getCurrentLocation();
443443

444444
// Parse the unsigned variant.
445-
uint64_t uintResult;
445+
APInt uintResult;
446446
OptionalParseResult parseResult = parseOptionalInteger(uintResult);
447447
if (!parseResult.hasValue() || failed(*parseResult))
448448
return parseResult;
449449

450-
// Try to convert to the provided integer type.
451-
result = IntT(uintResult);
452-
if (uint64_t(result) != uintResult)
450+
// Try to convert to the provided integer type. sextOrTrunc is correct even
451+
// for unsigned types because parseOptionalInteger ensures the sign bit is
452+
// zero for non-negated integers.
453+
result =
454+
(IntT)uintResult.sextOrTrunc(sizeof(IntT) * CHAR_BIT).getLimitedValue();
455+
if (APInt(uintResult.getBitWidth(), result) != uintResult)
453456
return emitError(loc, "integer value too large");
454457
return success();
455458
}

mlir/lib/Parser/DialectSymbolParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class CustomDialectAsmParser : public DialectAsmParser {
9494
}
9595

9696
/// Parse an optional integer value from the stream.
97-
OptionalParseResult parseOptionalInteger(uint64_t &result) override {
97+
OptionalParseResult parseOptionalInteger(APInt &result) override {
9898
return parser.parseOptionalInteger(result);
9999
}
100100

mlir/lib/Parser/Parser.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ ParseResult Parser::parseToken(Token::Kind expectedToken,
9696
}
9797

9898
/// Parse an optional integer value from the stream.
99-
OptionalParseResult Parser::parseOptionalInteger(uint64_t &result) {
99+
OptionalParseResult Parser::parseOptionalInteger(APInt &result) {
100100
Token curToken = getToken();
101101
if (curToken.isNot(Token::integer, Token::minus))
102102
return llvm::None;
@@ -106,10 +106,19 @@ OptionalParseResult Parser::parseOptionalInteger(uint64_t &result) {
106106
if (parseToken(Token::integer, "expected integer value"))
107107
return failure();
108108

109-
auto val = curTok.getUInt64IntegerValue();
110-
if (!val)
109+
StringRef spelling = curTok.getSpelling();
110+
bool isHex = spelling.size() > 1 && spelling[1] == 'x';
111+
if (spelling.getAsInteger(isHex ? 0 : 10, result))
111112
return emitError(curTok.getLoc(), "integer value too large");
112-
result = negative ? -*val : *val;
113+
114+
// Make sure we have a zero at the top so we return the right signedness.
115+
if (result.isNegative())
116+
result = result.zext(result.getBitWidth() + 1);
117+
118+
// Process the negative sign if present.
119+
if (negative)
120+
result.negate();
121+
113122
return success();
114123
}
115124

@@ -1217,7 +1226,7 @@ class CustomOpAsmParser : public OpAsmParser {
12171226
}
12181227

12191228
/// Parse an optional integer value from the stream.
1220-
OptionalParseResult parseOptionalInteger(uint64_t &result) override {
1229+
OptionalParseResult parseOptionalInteger(APInt &result) override {
12211230
return parser.parseOptionalInteger(result);
12221231
}
12231232

mlir/lib/Parser/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class Parser {
128128
ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
129129

130130
/// Parse an optional integer value from the stream.
131-
OptionalParseResult parseOptionalInteger(uint64_t &result);
131+
OptionalParseResult parseOptionalInteger(APInt &result);
132132

133133
/// Parse a floating point value from an integer literal token.
134134
ParseResult parseFloatFromIntegerLiteral(Optional<APFloat> &result,

0 commit comments

Comments
 (0)