14#include <mlir/IR/Builders.h>
15#include <mlir/IR/DialectImplementation.h>
17#include <llvm/ADT/StringExtras.h>
18#include <llvm/ADT/TypeSwitch.h>
23static bool isValidSMTLibAtomChar(
char ch) {
24 return llvm::isAlnum(ch) || ch ==
'_' || ch ==
'.' || ch ==
'$' || ch ==
'-' || ch ==
'!';
27static LogicalResult verifySMTLibSymbolText(
28 function_ref<InFlightDiagnostic()> emitError, StringRef text,
bool requireLeadingColon
31 return emitError() <<
"symbol text must not be empty";
33 if (requireLeadingColon) {
34 if (!text.starts_with(
':')) {
35 return emitError() <<
"keyword must start with ':'";
37 text = text.drop_front();
39 return emitError() <<
"keyword must contain at least one character after ':'";
41 }
else if (text.starts_with(
':')) {
42 return emitError() <<
"symbol must not start with ':'";
45 for (
char ch : text) {
46 if (!isValidSMTLibAtomChar(ch)) {
47 return emitError() <<
"invalid SMT-LIB symbol character '" << ch <<
'\'';
57LogicalResult BitVectorAttr::verify(
58 function_ref<InFlightDiagnostic()> emitError,
61 if (value.getBitWidth() < 1) {
62 return emitError() <<
"bit-width must be at least 1, but got " << value.getBitWidth();
67std::string BitVectorAttr::getValueAsString(
bool prefix)
const {
68 unsigned width = getValue().getBitWidth();
69 SmallVector<char> toPrint;
70 StringRef pref = prefix ?
"#" :
"";
72 getValue().toString(toPrint, 16,
false,
false,
false);
75 SmallVector<char> leadingZeros(width / 4 - toPrint.size(),
'0');
76 return (pref +
"x" + Twine(leadingZeros) + toPrint).str();
79 getValue().toString(toPrint, 2,
false,
false,
false);
81 SmallVector<char> leadingZeros(width - toPrint.size(),
'0');
82 return (pref +
"b" + Twine(leadingZeros) + toPrint).str();
86static FailureOr<APInt>
87parseBitVectorString(function_ref<InFlightDiagnostic()> emitError, StringRef value) {
88 auto reportError = [emitError](StringRef msg) -> FailureOr<APInt> {
90 return emitError() << msg;
95 if (value[0] !=
'#') {
96 return reportError(
"expected '#'");
99 if (value.size() < 3) {
100 return reportError(
"expected at least one digit");
103 if (value[1] ==
'b') {
104 return APInt(value.size() - 2, std::string(value.begin() + 2, value.end()), 2);
107 if (value[1] ==
'x') {
108 return APInt((value.size() - 2) * 4, std::string(value.begin() + 2, value.end()), 16);
111 return reportError(
"expected either 'b' or 'x'");
114BitVectorAttr BitVectorAttr::get(MLIRContext *context, StringRef value) {
115 auto maybeValue = parseBitVectorString(
nullptr, value);
117 assert(succeeded(maybeValue) &&
"string must have SMT-LIB format");
118 return Base::get(context, *maybeValue);
121BitVectorAttr BitVectorAttr::getChecked(
122 function_ref<InFlightDiagnostic()> emitError, MLIRContext *context, StringRef value
124 auto maybeValue = parseBitVectorString(emitError, value);
125 if (failed(maybeValue)) {
129 return Base::getChecked(emitError, context, *maybeValue);
132BitVectorAttr BitVectorAttr::get(MLIRContext *context, uint64_t value,
unsigned width) {
133 return Base::get(context, APInt(width, value));
136BitVectorAttr BitVectorAttr::getChecked(
137 function_ref<InFlightDiagnostic()> emitError, MLIRContext *context, uint64_t value,
140 if (width < 64 && value >= (UINT64_C(1) << width)) {
141 emitError() <<
"value does not fit in a bit-vector of desired width";
144 return Base::getChecked(emitError, context, APInt(width, value));
147Attribute BitVectorAttr::parse(AsmParser &odsParser, Type odsType) {
148 llvm::SMLoc loc = odsParser.getCurrentLocation();
151 if (odsParser.parseLess() || odsParser.parseInteger(val) || odsParser.parseGreater()) {
156 if (!odsType || !llvm::isa<BitVectorType>(odsType)) {
157 odsParser.emitError(loc) <<
"explicit bit-vector type required";
161 unsigned width = llvm::cast<BitVectorType>(odsType).getWidth();
163 if (width > val.getBitWidth()) {
167 val = val.sext(width);
168 }
else if (width < val.getBitWidth()) {
171 unsigned neededBits = val.isNegative() ? val.getSignificantBits() : val.getActiveBits();
172 if (width < neededBits) {
173 odsParser.emitError(loc) <<
"integer value out of range for given bit-vector type "
177 val = val.trunc(width);
180 return BitVectorAttr::get(odsParser.getContext(), val);
183void BitVectorAttr::print(AsmPrinter &odsPrinter)
const {
187 odsPrinter <<
"<" << getValue() <<
">";
190Type BitVectorAttr::getType()
const {
198LogicalResult KeywordAttr::verify(function_ref<InFlightDiagnostic()> emitError, StringRef value) {
199 return verifySMTLibSymbolText(emitError, value,
true);
202Attribute KeywordAttr::parse(AsmParser &parser, Type) {
203 SMLoc loc = parser.getCurrentLocation();
205 if (parser.parseLess() || parser.parseColon() || parser.parseKeyword(&keyword) ||
206 parser.parseGreater()) {
209 return parser.getChecked<KeywordAttr>(loc, parser.getContext(), (
":" + keyword).str());
212void KeywordAttr::print(AsmPrinter &printer)
const { printer <<
'<' << getValue() <<
'>'; }
214LogicalResult SymbolAttr::verify(function_ref<InFlightDiagnostic()> emitError, StringRef value) {
215 return verifySMTLibSymbolText(emitError, value,
false);
218Attribute SymbolAttr::parse(AsmParser &parser, Type) {
219 SMLoc loc = parser.getCurrentLocation();
221 if (parser.parseLess() || parser.parseKeyword(&symbol) || parser.parseGreater()) {
224 return parser.getChecked<SymbolAttr>(loc, parser.getContext(), symbol.str());
227void SymbolAttr::print(AsmPrinter &printer)
const { printer <<
'<' << getValue() <<
'>'; }
233#define GET_ATTRDEF_CLASSES
241 #define GET_ATTRDEF_LIST
static BitVectorType get(::mlir::MLIRContext *context, int64_t width)
void registerAttributes()