20#include <mlir/IR/DialectImplementation.h>
22#include <llvm/ADT/TypeSwitch.h>
29#define GET_TYPEDEF_CLASSES
31#define GET_ATTRDEF_CLASSES
39enum class FeltAttrEncoding : uint8_t {
44struct FeltDialectBytecodeInterface
48 Attribute readAttribute(DialectBytecodeReader &reader)
const final {
50 if (failed(reader.readVarInt(encoding))) {
53 if (encoding > std::numeric_limits<uint8_t>::max()) {
54 reader.emitError() <<
"unknown felt attribute encoding: " << encoding;
58 switch (
static_cast<FeltAttrEncoding
>(encoding)) {
59 case FeltAttrEncoding::FeltConst: {
62 if (failed(value) || failed(reader.readType(type))) {
65 return llzk::felt::FeltConstAttr::get(getContext(), *value, type);
67 case FeltAttrEncoding::FieldSpec: {
69 if (failed(reader.readAttribute(fieldName))) {
78 return llzk::InFlightDiagnosticWrapper(reader.emitError());
80 return llzk::felt::FieldSpecAttr::get(getContext(), fieldName, *prime);
84 reader.emitError() <<
"unknown felt attribute encoding: " << encoding;
88 LogicalResult writeAttribute(Attribute attr, DialectBytecodeWriter &writer)
const final {
89 if (
auto feltConst = dyn_cast<llzk::felt::FeltConstAttr>(attr)) {
90 writer.writeVarInt(
static_cast<uint64_t
>(FeltAttrEncoding::FeltConst));
92 writer.writeType(feltConst.getType());
95 if (
auto fieldSpec = dyn_cast<llzk::felt::FieldSpecAttr>(attr)) {
96 writer.writeVarInt(
static_cast<uint64_t
>(FeltAttrEncoding::FieldSpec));
97 writer.writeAttribute(fieldSpec.getFieldName());
116Attribute FieldSpecAttr::parse(AsmParser &odsParser, Type) {
117 Builder odsBuilder(odsParser.getContext());
118 llvm::SMLoc odsLoc = odsParser.getCurrentLocation();
119 FailureOr<StringAttr> fieldNameAttrRes;
120 FailureOr<llvm::APInt> primeRes;
123 if (odsParser.parseLess()) {
128 fieldNameAttrRes = FieldParser<StringAttr>::parse(odsParser);
129 if (failed(fieldNameAttrRes)) {
131 odsParser.getCurrentLocation(),
"failed to parse LLZK_FieldSpecAttr parameter 'fieldName' "
132 "which is to be a `StringAttr`"
137 if (odsParser.parseComma()) {
143 if (failed(primeRes)) {
145 odsParser.getCurrentLocation(),
146 "failed to parse LLZK_FieldSpecAttr parameter 'prime' which is to be a `llvm::APInt`"
151 if (odsParser.parseGreater()) {
154 assert(succeeded(fieldNameAttrRes));
155 assert(succeeded(primeRes));
158 auto errFn = [&odsParser]() {
159 return InFlightDiagnosticWrapper(odsParser.emitError(odsParser.getCurrentLocation()));
163 return odsParser.getChecked<FieldSpecAttr>(
164 odsLoc, odsParser.getContext(), StringAttr(*fieldNameAttrRes), llvm::APInt(*primeRes)
168void FieldSpecAttr::print(AsmPrinter &odsPrinter)
const {
169 Builder odsBuilder(getContext());
171 odsPrinter.printStrippedAttrOrType(getFieldName());
173 odsPrinter.printStrippedAttrOrType(getPrime());
181Attribute FeltConstAttr::parse(AsmParser &odsParser, Type) {
182 SMLoc odsLoc = odsParser.getCurrentLocation();
185 FailureOr<APInt> valueRes = FieldParser<APInt>::parse(odsParser);
186 if (failed(valueRes)) {
188 odsParser.getCurrentLocation(),
189 "failed to parse LLZK_FeltConstAttr parameter 'value' which is to be a `::llvm::APInt`"
197 if (odsParser.parseOptionalColon().succeeded()) {
198 FailureOr<FeltType> typeRes = FieldParser<FeltType>::parse(odsParser);
199 if (failed(typeRes)) {
201 odsParser.getCurrentLocation(),
202 "failed to parse LLZK_FeltConstAttr parameter 'type' which is to be a `FeltType`"
209 else if (odsParser.parseOptionalLess().succeeded()) {
210 FailureOr<StringAttr> fieldNameRes = FieldParser<StringAttr>::parse(odsParser);
211 if (failed(fieldNameRes)) {
213 odsParser.getCurrentLocation(),
"failed to parse LLZK_FeltConstAttr(version 1) field "
214 "name parameter which is to be a `StringAttr`"
218 if (odsParser.parseGreater()) {
221 type =
FeltType::get(odsParser.getContext(), (*fieldNameRes).getValue());
224 return odsParser.getChecked<FeltConstAttr>(odsLoc, odsParser.getContext(), *valueRes, type);
228void FeltConstAttr::print(AsmPrinter &odsPrinter)
const {
230 odsPrinter.printStrippedAttrOrType(getValue());
233 odsPrinter.printStrippedAttrOrType(getType());
257 if (
auto attr = llvm::dyn_cast<FeltConstAttr>(value)) {
263auto FeltDialect::initialize() ->
void {
273 #define GET_TYPEDEF_LIST
280 #define GET_ATTRDEF_LIST
284 addInterfaces<FeltDialectBytecodeInterface>();
Information about the prime finite field used for the interval analysis.
static llvm::LogicalResult verifyFieldDefined(llvm::StringRef fieldName, EmitErrorFn errFn)
Search for a field with the given name, reporting an error if the field is not found.
static const Field & getField(llvm::StringRef fieldName, EmitErrorFn errFn)
Get a Field from a given field name string.
static void addField(llvm::StringRef fieldName, const llvm::APInt &prime, EmitErrorFn errFn)
Add a new field to the set of available prime fields.
::mlir::Operation * materializeConstant(::mlir::OpBuilder &builder, ::mlir::Attribute value, ::mlir::Type type, ::mlir::Location loc) override
Materialize a single constant operation from a given attribute value with the desired resultant type.
::llvm::LogicalResult verify(::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, ::mlir::StringAttr fieldName)
const ::llzk::Field & getField() const
::mlir::StringAttr getFieldName() const
static FeltType get(::mlir::MLIRContext *context, ::mlir::StringAttr fieldName)
void writeAPInt(mlir::DialectBytecodeWriter &writer, const llvm::APInt &value)
Write an APInt with its bit width, so the bytecode reader can use MLIR's native APInt payload encodin...
mlir::FailureOr< llvm::APInt > readAPInt(mlir::DialectBytecodeReader &reader)
Read an APInt written by writeAPInt.
OwningEmitErrorFn wrapNonNullableInFlightDiagnostic(llvm::function_ref< mlir::InFlightDiagnostic()> emitError)
This implements the bytecode interface for the LLZK dialect.
static mlir::FailureOr< llvm::APInt > parse(mlir::AsmParser &parser)