41 if (ShapedType::isDynamic(high.getSExtValue())) {
44 os << low <<
':' << high;
58 auto ll = APSInt(std::get<0>(l)), lu = APSInt(std::get<1>(l));
59 auto rl = APSInt(std::get<0>(r)), ru = APSInt(std::get<1>(r));
80 unsigned requiredBits = idx.getSignificantBits();
81 auto hash = llvm::hash_value(idx.trunc(requiredBits));
85 return llvm::hash_value(std::get<0>(r)) ^ llvm::hash_value(std::get<1>(r));
108 return std::move(sDef.value());
111std::vector<ConstrainRef>
113 std::vector<ConstrainRef> res = {root};
114 for (
const ConstrainRef &child : root.getAllChildren(tables,
mod)) {
115 auto recursiveChildren = getAllConstrainRefs(tables,
mod, child);
116 res.insert(res.end(), recursiveChildren.begin(), recursiveChildren.end());
122 std::vector<ConstrainRef> res;
125 structDef == fnOp->getParentOfType<
StructDefOp>(),
"function must be within the given struct"
129 ensure(succeeded(modOp),
"could not lookup module from struct " + Twine(structDef.getName()));
131 SymbolTableCollection tables;
132 for (
auto a : fnOp.getArguments()) {
134 res.insert(res.end(), argRes.begin(), argRes.end());
141 auto createOp = dyn_cast_if_present<CreateStructOp>(selfVal.getDefiningOp());
142 ensure(createOp,
"self value should originate from struct.new operation");
144 res.insert(res.end(), selfRes.begin(), selfRes.end());
150std::vector<ConstrainRef>
152 std::vector<ConstrainRef> res;
155 fieldDef->getParentOfType<
StructDefOp>() == structDef,
"Field " + Twine(fieldDef.getName()) +
156 " is not a field of struct " +
157 Twine(structDef.getName())
160 ensure(succeeded(modOp),
"could not lookup module from struct " + Twine(structDef.getName()));
163 BlockArgument self = constrainFnOp.getArguments().front();
166 SymbolTableCollection tables;
172 return std::get<FeltConstantOp>(*constantVal).getType();
174 return std::get<arith::ConstantIndexOp>(*constantVal).getType();
176 return std::get<ConstReadOp>(*constantVal).getType();
178 int array_derefs = 0;
179 int idx = fieldRefs.size() - 1;
180 while (idx >= 0 && fieldRefs[idx].
isIndex()) {
185 Type currTy =
nullptr;
187 currTy = fieldRefs[idx].getField().getType();
192 while (array_derefs > 0) {
193 currTy = dyn_cast<ArrayType>(currTy).getElementType();
205 if (root != prefix.root || fieldRefs.size() < prefix.fieldRefs.size()) {
208 for (
size_t i = 0; i < prefix.fieldRefs.size(); i++) {
209 if (fieldRefs[i] != prefix.fieldRefs[i]) {
221 std::vector<ConstrainRefIndex> suffix;
222 for (
size_t i = prefix.fieldRefs.size(); i < fieldRefs.size(); i++) {
223 suffix.push_back(fieldRefs[i]);
228FailureOr<ConstrainRef>
234 if (failed(suffix)) {
238 auto newSignalUsage = other;
239 newSignalUsage.fieldRefs.insert(newSignalUsage.fieldRefs.end(), suffix->begin(), suffix->end());
240 return newSignalUsage;
243std::vector<ConstrainRef>
245 std::vector<ConstrainRef> res;
247 for (int64_t i = 0; i < arrayTy.getDimSize(0); i++) {
249 res.push_back(childRef);
259 std::vector<ConstrainRef> res;
267 auto structDefCopy = structDefRes;
269 tables, SymbolRefAttr::get(f.getContext(), f.getSymNameAttr()), std::move(structDefCopy),
272 ensure(succeeded(fieldLookup),
"could not get SymbolLookupResult of existing FieldDefOp");
276 res.push_back(childRef);
281std::vector<ConstrainRef>
284 if (
auto structTy = dyn_cast<StructType>(ty)) {
286 }
else if (
auto arrayType = dyn_cast<ArrayType>(ty)) {
299 auto constRead = std::get<ConstReadOp>(*constantVal);
300 auto structDefOp = constRead->getParentOfType<
StructDefOp>();
301 ensure(structDefOp,
"struct template should have a struct parent");
302 os <<
'@' << structDefOp.getName() <<
"<[@" << constRead.getConstName() <<
"]>";
311 for (
auto f : fieldRefs) {
312 os <<
"[" << f <<
"]";
323 return (root == rhs.root) && (fieldRefs == rhs.fieldRefs) && (constantVal == rhs.constantVal);
335 return safeLt(lhsInt, rhsInt);
345 return safeLt(lhsVal, rhsVal);
354 auto lhsName = std::get<ConstReadOp>(*constantVal).getConstName();
355 auto rhsName = std::get<ConstReadOp>(*rhs.constantVal).getConstName();
356 return lhsName.compare(rhsName) < 0;
374 }
else if (lhsOp > rhsOp) {
378 llvm_unreachable(
"unhandled operator< case");
381 for (
size_t i = 0; i < fieldRefs.size() && i < rhs.fieldRefs.size(); i++) {
382 if (fieldRefs[i] < rhs.fieldRefs[i]) {
384 }
else if (fieldRefs[i] > rhs.fieldRefs[i]) {
388 return fieldRefs.size() < rhs.fieldRefs.size();
401 for (
auto f : val.fieldRefs) {
416 insert(rhs.begin(), rhs.end());
422 std::vector<ConstrainRef> sortedRefs(rhs.begin(), rhs.end());
423 std::sort(sortedRefs.begin(), sortedRefs.end());
424 for (
auto it = sortedRefs.begin(); it != sortedRefs.end();) {
427 if (it != sortedRefs.end()) {
This file defines helpers for manipulating APInts/APSInts for large numbers and operations over those...
This file defines methods symbol lookup across LLZK operations and included files.
component::FieldDefOp getField() const
void print(mlir::raw_ostream &os) const
bool isIndexRange() const
bool operator<(const ConstrainRefIndex &rhs) const
ConstrainRefIndex(component::FieldDefOp f)
IndexRange getIndexRange() const
mlir::APInt getIndex() const
ConstrainRefSet & join(const ConstrainRefSet &rhs)
Defines a reference to a llzk object within a constrain function call.
mlir::APInt getConstantFeltValue() const
bool operator<(const ConstrainRef &rhs) const
component::CreateStructOp getCreateStructOp() const
bool isValidPrefix(const ConstrainRef &prefix) const
Returns true iff prefix is a valid prefix of this reference.
void print(mlir::raw_ostream &os) const
bool isConstantFelt() const
bool isTemplateConstant() const
mlir::APInt getConstantIndexValue() const
bool isConstantIndex() const
mlir::Type getType() const
std::vector< ConstrainRef > getAllChildren(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod) const
Get all direct children of this ConstrainRef, assuming this ref is not a scalar.
ConstrainRef(mlir::BlockArgument b)
mlir::FailureOr< std::vector< ConstrainRefIndex > > getSuffix(const ConstrainRef &prefix) const
If prefix is a valid prefix of this reference, return the suffix that remains after removing the pref...
bool operator==(const ConstrainRef &rhs) const
bool isBlockArgument() const
mlir::FailureOr< ConstrainRef > translate(const ConstrainRef &prefix, const ConstrainRef &other) const
Create a new reference with prefix replaced with other iff prefix is a valid prefix for this referenc...
mlir::BlockArgument getBlockArgument() const
ConstrainRef createChild(ConstrainRefIndex r) const
bool isCreateStructOp() const
static std::vector< ConstrainRef > getAllConstrainRefs(mlir::SymbolTableCollection &tables, mlir::ModuleOp mod, ConstrainRef root)
Produce all possible ConstraintRefs that are present starting from the given root.
bool isConstantInt() const
mlir::APInt getConstantValue() const
unsigned getInputNum() const
static constexpr ::llvm::StringLiteral getOperationName()
::llzk::function::FuncDefOp getConstrainFuncOp()
Gets the FuncDefOp that defines the constrain function in this structure, if present.
::mlir::FailureOr< SymbolLookupResult< StructDefOp > > getDefinition(::mlir::SymbolTableCollection &symbolTable, ::mlir::Operation *op) const
Gets the struct op that defines this struct.
::mlir::Value getSelfValueFromCompute()
Return the "self" value (i.e.
bool isStructCompute()
Return true iff the function is within a StructDefOp and named FUNC_NAME_COMPUTE.
FailureOr< ModuleOp > getRootModule(Operation *from)
void ensure(bool condition, llvm::Twine errMsg)
bool safeEq(const llvm::APSInt &lhs, const llvm::APSInt &rhs)
bool safeLt(const llvm::APSInt &lhs, const llvm::APSInt &rhs)
mlir::FailureOr< SymbolLookupResultUntyped > lookupSymbolIn(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, Within &&lookupWithin, mlir::Operation *origin, bool reportMissing=true)
raw_ostream & operator<<(raw_ostream &os, const ConstrainRef &rhs)
ExpressionValue mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
SymbolLookupResult< StructDefOp > getStructDef(SymbolTableCollection &tables, ModuleOp mod, StructType ty)
Lookup a StructDefOp from a given StructType.
std::vector< ConstrainRef > getAllChildren(SymbolTableCollection &tables, ModuleOp mod, ArrayType arrayTy, ConstrainRef root)
size_t operator()(const ConstrainRefIndex &c) const
size_t operator()(const ConstrainRef &val) const