Skip to content

Commit ea4ad1e

Browse files
quartersdgjpienaar
authored andcommitted
Add AsmParser::parseDecimalInteger.
An attribute parser needs to parse lists of possibly negative integers separated by x in a way which is foiled by parseInteger handling hex format and parseIntegerInDimensionList does not allow negatives.
1 parent 56535a0 commit ea4ad1e

File tree

4 files changed

+84
-5
lines changed

4 files changed

+84
-5
lines changed

mlir/include/mlir/IR/OpImplementation.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -714,16 +714,27 @@ class AsmParser {
714714
return *parseResult;
715715
}
716716

717+
/// Parse a decimal integer value from the stream.
718+
template <typename IntT>
719+
ParseResult parseDecimalInteger(IntT &result) {
720+
auto loc = getCurrentLocation();
721+
OptionalParseResult parseResult = parseOptionalDecimalInteger(result);
722+
if (!parseResult.has_value())
723+
return emitError(loc, "expected decimal integer value");
724+
return *parseResult;
725+
}
726+
717727
/// Parse an optional integer value from the stream.
718728
virtual OptionalParseResult parseOptionalInteger(APInt &result) = 0;
729+
virtual OptionalParseResult parseOptionalDecimalInteger(APInt &result) = 0;
719730

720-
template <typename IntT>
721-
OptionalParseResult parseOptionalInteger(IntT &result) {
731+
private:
732+
template <typename IntT, typename ParseFn>
733+
OptionalParseResult parseOptionalIntegerAndCheck(IntT &result,
734+
ParseFn &&parseFn) {
722735
auto loc = getCurrentLocation();
723-
724-
// Parse the unsigned variant.
725736
APInt uintResult;
726-
OptionalParseResult parseResult = parseOptionalInteger(uintResult);
737+
OptionalParseResult parseResult = parseFn(uintResult);
727738
if (!parseResult.has_value() || failed(*parseResult))
728739
return parseResult;
729740

@@ -737,6 +748,20 @@ class AsmParser {
737748
return success();
738749
}
739750

751+
public:
752+
template <typename IntT>
753+
OptionalParseResult parseOptionalInteger(IntT &result) {
754+
return parseOptionalIntegerAndCheck(
755+
result, [&](APInt &result) { return parseOptionalInteger(result); });
756+
}
757+
758+
template <typename IntT>
759+
OptionalParseResult parseOptionalDecimalInteger(IntT &result) {
760+
return parseOptionalIntegerAndCheck(result, [&](APInt &result) {
761+
return parseOptionalDecimalInteger(result);
762+
});
763+
}
764+
740765
/// These are the supported delimiters around operand lists and region
741766
/// argument lists, used by parseOperandList.
742767
enum class Delimiter {

mlir/lib/AsmParser/AsmParserImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ class AsmParserImpl : public BaseT {
322322
return parser.parseOptionalInteger(result);
323323
}
324324

325+
/// Parse an optional integer value from the stream.
326+
OptionalParseResult parseOptionalDecimalInteger(APInt &result) override {
327+
return parser.parseOptionalDecimalInteger(result);
328+
}
329+
325330
/// Parse a list of comma-separated items with an optional delimiter. If a
326331
/// delimiter is provided, then an empty list is allowed. If not, then at
327332
/// least one element will be parsed.

mlir/lib/AsmParser/Parser.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "llvm/ADT/STLExtras.h"
4242
#include "llvm/ADT/ScopeExit.h"
4343
#include "llvm/ADT/Sequence.h"
44+
#include "llvm/ADT/StringExtras.h"
4445
#include "llvm/ADT/StringMap.h"
4546
#include "llvm/ADT/StringSet.h"
4647
#include "llvm/Support/Alignment.h"
@@ -307,6 +308,51 @@ OptionalParseResult Parser::parseOptionalInteger(APInt &result) {
307308
return success();
308309
}
309310

311+
namespace {
312+
bool isBinOrHexOrOctIndicator(char c) {
313+
return (llvm::toLower(c) == 'x' || llvm::toLower(c) == 'b' ||
314+
llvm::isDigit(c));
315+
}
316+
} // namespace
317+
318+
/// Parse an optional integer value only in decimal format from the stream.
319+
OptionalParseResult Parser::parseOptionalDecimalInteger(APInt &result) {
320+
Token curToken = getToken();
321+
if (curToken.isNot(Token::integer, Token::minus)) {
322+
return std::nullopt;
323+
}
324+
325+
bool negative = consumeIf(Token::minus);
326+
Token curTok = getToken();
327+
if (parseToken(Token::integer, "expected integer value")) {
328+
return failure();
329+
}
330+
331+
StringRef spelling = curTok.getSpelling();
332+
// If the integer is in bin, hex, or oct format, return only the 0 and reset
333+
// the lex pointer.
334+
if (spelling[0] == '0' && spelling.size() > 1 &&
335+
isBinOrHexOrOctIndicator(spelling[1])) {
336+
result = 0;
337+
state.lex.resetPointer(spelling.data() + 1);
338+
consumeToken();
339+
return success();
340+
}
341+
342+
if (spelling.getAsInteger(10, result))
343+
return emitError(curTok.getLoc(), "integer value too large");
344+
345+
// Make sure we have a zero at the top so we return the right signedness.
346+
if (result.isNegative())
347+
result = result.zext(result.getBitWidth() + 1);
348+
349+
// Process the negative sign if present.
350+
if (negative)
351+
result.negate();
352+
353+
return success();
354+
}
355+
310356
/// Parse a floating point value from an integer literal token.
311357
ParseResult Parser::parseFloatFromIntegerLiteral(
312358
std::optional<APFloat> &result, const Token &tok, bool isNegative,

mlir/lib/AsmParser/Parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ class Parser {
144144
/// Parse an optional integer value from the stream.
145145
OptionalParseResult parseOptionalInteger(APInt &result);
146146

147+
/// Parse an optional integer value only in decimal format from the stream.
148+
OptionalParseResult parseOptionalDecimalInteger(APInt &result);
149+
147150
/// Parse a floating point value from an integer literal token.
148151
ParseResult parseFloatFromIntegerLiteral(std::optional<APFloat> &result,
149152
const Token &tok, bool isNegative,

0 commit comments

Comments
 (0)