14#include <mlir/IR/Builders.h>
15#include <mlir/IR/DialectImplementation.h>
17#include <llvm/ADT/TypeSwitch.h>
26LogicalResult BitVectorAttr::verify(
27 function_ref<InFlightDiagnostic()> emitError,
30 if (value.getBitWidth() < 1) {
31 return emitError() <<
"bit-width must be at least 1, but got " << value.getBitWidth();
36std::string BitVectorAttr::getValueAsString(
bool prefix)
const {
37 unsigned width = getValue().getBitWidth();
38 SmallVector<char> toPrint;
39 StringRef pref = prefix ?
"#" :
"";
41 getValue().toString(toPrint, 16,
false,
false,
false);
44 SmallVector<char> leadingZeros(width / 4 - toPrint.size(),
'0');
45 return (pref +
"x" + Twine(leadingZeros) + toPrint).str();
48 getValue().toString(toPrint, 2,
false,
false,
false);
50 SmallVector<char> leadingZeros(width - toPrint.size(),
'0');
51 return (pref +
"b" + Twine(leadingZeros) + toPrint).str();
55static FailureOr<APInt>
56parseBitVectorString(function_ref<InFlightDiagnostic()> emitError, StringRef value) {
57 auto reportError = [&](StringRef msg) -> FailureOr<APInt> {
59 return emitError() << msg;
64 if (value[0] !=
'#') {
65 return reportError(
"expected '#'");
68 if (value.size() < 3) {
69 return reportError(
"expected at least one digit");
72 if (value[1] ==
'b') {
73 return APInt(value.size() - 2, std::string(value.begin() + 2, value.end()), 2);
76 if (value[1] ==
'x') {
77 return APInt((value.size() - 2) * 4, std::string(value.begin() + 2, value.end()), 16);
80 return reportError(
"expected either 'b' or 'x'");
83BitVectorAttr BitVectorAttr::get(MLIRContext *context, StringRef value) {
84 auto maybeValue = parseBitVectorString(
nullptr, value);
86 assert(succeeded(maybeValue) &&
"string must have SMT-LIB format");
87 return Base::get(context, *maybeValue);
90BitVectorAttr BitVectorAttr::getChecked(
91 function_ref<InFlightDiagnostic()> emitError, MLIRContext *context, StringRef value
93 auto maybeValue = parseBitVectorString(emitError, value);
94 if (failed(maybeValue)) {
98 return Base::getChecked(emitError, context, *maybeValue);
101BitVectorAttr BitVectorAttr::get(MLIRContext *context, uint64_t value,
unsigned width) {
102 return Base::get(context, APInt(width, value));
105BitVectorAttr BitVectorAttr::getChecked(
106 function_ref<InFlightDiagnostic()> emitError, MLIRContext *context, uint64_t value,
109 if (width < 64 && value >= (UINT64_C(1) << width)) {
110 emitError() <<
"value does not fit in a bit-vector of desired width";
113 return Base::getChecked(emitError, context, APInt(width, value));
116Attribute BitVectorAttr::parse(AsmParser &odsParser, Type odsType) {
117 llvm::SMLoc loc = odsParser.getCurrentLocation();
120 if (odsParser.parseLess() || odsParser.parseInteger(val) || odsParser.parseGreater()) {
125 if (!odsType || !llvm::isa<BitVectorType>(odsType)) {
126 odsParser.emitError(loc) <<
"explicit bit-vector type required";
130 unsigned width = llvm::cast<BitVectorType>(odsType).getWidth();
132 if (width > val.getBitWidth()) {
136 val = val.sext(width);
137 }
else if (width < val.getBitWidth()) {
140 unsigned neededBits = val.isNegative() ? val.getSignificantBits() : val.getActiveBits();
141 if (width < neededBits) {
142 odsParser.emitError(loc) <<
"integer value out of range for given bit-vector type "
146 val = val.trunc(width);
149 return BitVectorAttr::get(odsParser.getContext(), val);
152void BitVectorAttr::print(AsmPrinter &odsPrinter)
const {
156 odsPrinter <<
"<" << getValue() <<
">";
159Type BitVectorAttr::getType()
const {
167#define GET_ATTRDEF_CLASSES
175 #define GET_ATTRDEF_LIST
static BitVectorType get(::mlir::MLIRContext *context, int64_t width)
void registerAttributes()