LLZK
3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Toggle main menu visibility
Loading...
Searching...
No Matches
Ops.cpp
Go to the documentation of this file.
1
//===-- Ops.cpp - Cast operation implementations ----------------*- C++ -*-===//
2
//
3
// Part of the LLZK Project, under the Apache License v2.0.
4
// See LICENSE.txt for license information.
5
// Copyright 2025 Veridise Inc.
6
// SPDX-License-Identifier: Apache-2.0
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "
llzk/Dialect/Cast/IR/Ops.h
"
11
12
#include "
llzk/Dialect/Cast/IR/Enums.h
"
13
#include "
llzk/Dialect/Felt/IR/Attrs.h
"
14
#include "
llzk/Dialect/Felt/IR/Ops.h
"
15
#include "
llzk/Dialect/Function/IR/Ops.h
"
16
#include "
llzk/Dialect/LLZK/IR/AttributeHelper.h
"
17
#include "
llzk/Util/BuilderHelper.h
"
18
19
#include <mlir/Dialect/Arith/IR/Arith.h>
20
#include <mlir/Support/LLVM.h>
21
22
#include <llvm/ADT/STLExtras.h>
23
#include <llvm/ADT/TypeSwitch.h>
24
25
// TableGen'd implementation files
26
#define GET_OP_CLASSES
27
#include "
llzk/Dialect/Cast/IR/Ops.cpp.inc
"
28
using namespace
mlir
;
29
30
static
inline
ParseResult
31
parseOptionalOverflowSemantics(OpAsmParser &parser, llzk::cast::OverflowSemanticsAttr &overflow) {
32
StringRef keyword;
33
if
(failed(parser.parseOptionalKeyword(&keyword))) {
34
return
success();
35
}
36
37
std::optional<llzk::cast::OverflowSemantics> semantics =
38
llzk::cast::symbolizeOverflowSemantics
(keyword);
39
if
(!semantics) {
40
return
parser.emitError(parser.getCurrentLocation()) <<
"expected overflow semantics keyword"
;
41
}
42
43
overflow = llzk::cast::OverflowSemanticsAttr::get(parser.getContext(), *semantics);
44
return
success();
45
}
46
47
static
inline
void
48
printOptionalOverflowSemantics(OpAsmPrinter &printer, llzk::cast::OverflowSemanticsAttr overflow) {
49
if
(!overflow || overflow.getValue() ==
llzk::cast::OverflowSemantics::ASSERT
) {
50
return
;
51
}
52
53
printer <<
' '
<<
stringifyOverflowSemantics
(overflow.getValue());
54
}
55
56
namespace
llzk::cast
{
57
58
bool
IntToFeltOp::isCompatibleReturnTypes
(::mlir::TypeRange lhs, ::mlir::TypeRange rhs) {
59
return
lhs.size() == rhs.size() && llvm::all_of(llvm::zip_equal(lhs, rhs), [](
auto
pair) {
60
auto
[lhsType, rhsType] = pair;
61
auto
lhsFeltType = llvm::dyn_cast<llzk::felt::FeltType>(lhsType);
62
auto
rhsFeltType = llvm::dyn_cast<llzk::felt::FeltType>(rhsType);
63
64
// If both types are felts but NOT structurally equal then check if the types are valid
65
// with the additional consideration that lhs is allowed to NOT have
66
// a declared field.
67
if
(lhsFeltType && rhsFeltType && lhsFeltType != rhsFeltType) {
68
// If we reached this point we know that the felts are not equal and that only the lhs is
69
// allowed to not have a declared field. Thus, rhs must have a declared field. If lhs has a
70
// declared field, then, since they are not structurally equal, it must be a different field
71
// than rhs. With all that, the types are compatible if lhs does not have a field, so we can
72
// simply return that.
73
return
!lhsFeltType.hasField();
74
}
75
76
// Any other case gets handled by standard equality.
77
return
lhsType == rhsType;
78
});
79
}
80
81
LogicalResult
IntToFeltOp::canonicalize
(
IntToFeltOp
op, ::mlir::PatternRewriter &rewriter) {
82
// Instead of casting an arith.constant to felt, just generate a felt.const
83
if
(!op.
getValue
().getDefiningOp()) {
84
return
failure();
85
}
86
87
return
llvm::TypeSwitch<Operation *, LogicalResult>(op.
getValue
().getDefiningOp())
88
.Case<arith::ConstantIndexOp, arith::ConstantIntOp>([&rewriter, &op](
auto
constOp) {
89
rewriter.replaceOpWithNewOp<
felt::FeltConstantOp
>(
90
op, felt::FeltConstAttr::get(op->getContext(),
toAPInt
(constOp.value()), op.getType())
91
);
92
return
success();
93
}).Default([](
auto
) {
return
failure(); });
94
}
95
96
ParseResult
97
IntToFeltOp::parseOptionalOverflowSemantics
(OpAsmParser &parser, OverflowSemanticsAttr &overflow) {
98
return ::parseOptionalOverflowSemantics(parser, overflow);
99
}
100
101
void
IntToFeltOp::printOptionalOverflowSemantics
(
102
OpAsmPrinter &printer,
IntToFeltOp
/*op*/
, OverflowSemanticsAttr overflow
103
) {
104
::printOptionalOverflowSemantics
(printer, overflow);
105
}
106
107
LogicalResult
FeltToIndexOp::canonicalize
(
FeltToIndexOp
op, ::mlir::PatternRewriter &rewriter) {
108
// Instead of casting a felt.const to index, just generate an arith.constant
109
if
(
auto
constOp = op.
getValue
().getDefiningOp<
felt::FeltConstantOp
>()) {
110
auto
value = constOp.getValue().getValue();
111
if
(value.getBitWidth() <= 64) {
112
rewriter.replaceOpWithNewOp<arith::ConstantIndexOp>(op, value.getSExtValue());
113
return
success();
114
}
115
}
116
return
failure();
117
}
118
119
ParseResult
FeltToIndexOp::parseOptionalOverflowSemantics
(
120
OpAsmParser &parser, OverflowSemanticsAttr &overflow
121
) {
122
return ::parseOptionalOverflowSemantics(parser, overflow);
123
}
124
125
void
FeltToIndexOp::printOptionalOverflowSemantics
(
126
OpAsmPrinter &printer,
FeltToIndexOp
/*op*/
, OverflowSemanticsAttr overflow
127
) {
128
::printOptionalOverflowSemantics
(printer, overflow);
129
}
130
131
}
// namespace llzk::cast
AttributeHelper.h
BuilderHelper.h
Enums.h
Ops.cpp.inc
Ops.h
Attrs.h
Ops.h
Ops.h
llzk::cast::FeltToIndexOp
Definition
Ops.h.inc:125
llzk::cast::FeltToIndexOp::getValue
::mlir::TypedValue<::llzk::felt::FeltType > getValue()
Definition
Ops.h.inc:161
llzk::cast::FeltToIndexOp::canonicalize
::llvm::LogicalResult canonicalize(FeltToIndexOp op, ::mlir::PatternRewriter &rewriter)
Definition
Ops.cpp:107
llzk::cast::FeltToIndexOp::printOptionalOverflowSemantics
static void printOptionalOverflowSemantics(::mlir::OpAsmPrinter &printer, FeltToIndexOp op, ::llzk::cast::OverflowSemanticsAttr overflow)
Definition
Ops.cpp:125
llzk::cast::FeltToIndexOp::parseOptionalOverflowSemantics
::mlir::ParseResult parseOptionalOverflowSemantics(::mlir::OpAsmParser &parser, ::llzk::cast::OverflowSemanticsAttr &overflow)
Definition
Ops.cpp:119
llzk::cast::IntToFeltOp
Definition
Ops.h.inc:375
llzk::cast::IntToFeltOp::printOptionalOverflowSemantics
static void printOptionalOverflowSemantics(::mlir::OpAsmPrinter &printer, IntToFeltOp op, ::llzk::cast::OverflowSemanticsAttr overflow)
Definition
Ops.cpp:101
llzk::cast::IntToFeltOp::parseOptionalOverflowSemantics
::mlir::ParseResult parseOptionalOverflowSemantics(::mlir::OpAsmParser &parser, ::llzk::cast::OverflowSemanticsAttr &overflow)
Definition
Ops.cpp:97
llzk::cast::IntToFeltOp::isCompatibleReturnTypes
static bool isCompatibleReturnTypes(::mlir::TypeRange lhs, ::mlir::TypeRange rhs)
Definition
Ops.cpp:58
llzk::cast::IntToFeltOp::canonicalize
::llvm::LogicalResult canonicalize(IntToFeltOp op, ::mlir::PatternRewriter &rewriter)
Definition
Ops.cpp:81
llzk::cast::IntToFeltOp::getValue
::mlir::TypedValue<::mlir::Type > getValue()
Definition
Ops.h.inc:411
llzk::felt::FeltConstantOp
Definition
Ops.h.inc:766
llzk::cast
Definition
Ops.cpp:56
llzk::cast::stringifyOverflowSemantics
::llvm::StringRef stringifyOverflowSemantics(OverflowSemantics val)
Definition
Enums.cpp.inc:12
llzk::cast::symbolizeOverflowSemantics
::std::optional< OverflowSemantics > symbolizeOverflowSemantics(::llvm::StringRef str)
Definition
Enums.cpp.inc:22
llzk::cast::OverflowSemantics::ASSERT
@ ASSERT
Definition
Enums.h.inc:14
llzk::toAPInt
APInt toAPInt(const DynamicAPInt &val, unsigned bitWidth)
Definition
DynamicAPIntHelper.cpp:143
mlir
Definition
ValueModel.h:30
lib
Dialect
Cast
IR
Ops.cpp
Generated by
1.17.0
Copyright 2025 Veridise Inc. under the Apache License v2.0. Copyright 2026 Project LLZK under the Apache License v2.0.