26#include <mlir/Dialect/Arith/IR/Arith.h>
27#include <mlir/Dialect/SCF/IR/SCF.h>
28#include <mlir/Dialect/Utils/IndexingUtils.h>
29#include <mlir/IR/Attributes.h>
30#include <mlir/IR/BuiltinOps.h>
31#include <mlir/IR/Diagnostics.h>
32#include <mlir/IR/SymbolTable.h>
33#include <mlir/IR/ValueRange.h>
34#include <mlir/Interfaces/CallInterfaces.h>
35#include <mlir/Interfaces/FunctionImplementation.h>
36#include <mlir/Support/LLVM.h>
37#include <mlir/Support/LogicalResult.h>
39#include <llvm/ADT/ArrayRef.h>
40#include <llvm/ADT/STLExtras.h>
41#include <llvm/ADT/SmallVectorExtras.h>
42#include <llvm/ADT/Twine.h>
63bool isValidTarget(Operation *op) {
64 if (
auto fnOp = dyn_cast<FuncDefOp>(op)) {
66 return fnOp->getParentOfType<
StructDefOp>() ==
nullptr;
69 return isa<StructDefOp>(op);
73 return llvm::any_of(unifications, [](
const auto &entry) {
return !entry.second; });
76struct TargetTypeInfo {
77 FunctionType funcType {};
78 ArrayAttr argAttrs {};
81FailureOr<TargetTypeInfo> getTargetTypeInfo(Operation *op) {
82 if (
auto fnOp = dyn_cast<FuncDefOp>(op)) {
84 FunctionType fnTy = fnOp.getFunctionType();
85 ArrayRef<Type> curInputs = fnTy.getInputs(), curResults = fnTy.getResults();
86 SmallVector<Type> newInputs;
87 newInputs.reserve(curInputs.size() + curResults.size());
88 newInputs.insert(newInputs.end(), curInputs.begin(), curInputs.end());
89 newInputs.insert(newInputs.end(), curResults.begin(), curResults.end());
91 auto newFnTy = fnTy.clone(newInputs, {});
93 ArrayAttr curArgAttrs = fnOp.getArgAttrsAttr(), curResAttrs = fnOp.getResAttrsAttr();
94 ArrayAttr newArgAttrsAttr {};
95 if (curArgAttrs || curResAttrs) {
96 auto *ctx = op->getContext();
97 SmallVector<Attribute> newArgAttrs;
99 newArgAttrs.reserve(newInputs.size());
101 newArgAttrs.insert(newArgAttrs.end(), curArgAttrs.begin(), curArgAttrs.end());
104 newArgAttrs.insert(newArgAttrs.end(), curInputs.size(), DictionaryAttr::get(ctx));
107 newArgAttrs.insert(newArgAttrs.end(), curResAttrs.begin(), curResAttrs.end());
110 newArgAttrs.insert(newArgAttrs.end(), curResults.size(), DictionaryAttr::get(ctx));
112 newArgAttrsAttr = ArrayAttr::get(ctx, newArgAttrs);
115 return TargetTypeInfo {
117 .argAttrs = newArgAttrsAttr,
120 if (
auto structOp = dyn_cast<StructDefOp>(op)) {
121 if (
FuncDefOp fnOp = structOp.getConstrainFuncOp(); fnOp && structOp.getComputeFuncOp()) {
122 return TargetTypeInfo {
123 .funcType = fnOp.getFunctionType(),
124 .argAttrs = fnOp.getArgAttrsAttr(),
127 FuncDefOp productFn = structOp.getProductFuncOp();
133 ArrayRef<Type> curInputs = fnTy.getInputs();
135 SmallVector<Type> newInputs;
136 newInputs.reserve(curInputs.size() + 1);
137 newInputs.push_back(structOp.getType());
138 newInputs.insert(newInputs.end(), curInputs.begin(), curInputs.end());
140 auto newFnTy = fnTy.clone(newInputs, {});
142 auto *ctx = op->getContext();
144 ArrayAttr newArgAttrsAttr = curArgAttrs;
146 SmallVector<Attribute> newArgAttrs;
147 newArgAttrs.reserve(curArgAttrs.size() + 1);
148 newArgAttrs.push_back(DictionaryAttr::get(ctx));
149 newArgAttrs.insert(newArgAttrs.end(), curArgAttrs.begin(), curArgAttrs.end());
150 newArgAttrsAttr = ArrayAttr::get(ctx, newArgAttrs);
152 return TargetTypeInfo {
154 .argAttrs = newArgAttrsAttr,
162enum class ForbiddenRequireConditionKind : uint8_t {
168struct ForbiddenRequireCondition {
169 ForbiddenRequireConditionKind kind;
170 llvm::SmallSetVector<Location, 2> sourceLocs;
175struct ForbiddenIncludedPrecondition {
176 std::optional<Location> calleePreconditionLoc = std::nullopt;
177 ForbiddenRequireConditionKind kind;
178 llvm::SmallSetVector<Location, 2> sourceLocs;
182struct ForbiddenIncludedPreconditions {
184 llvm::SmallVector<ForbiddenIncludedPrecondition> failures;
187std::optional<ForbiddenRequireCondition> classifyForbiddenConditionProvenance(
193 return ForbiddenRequireCondition {
194 .kind = ForbiddenRequireConditionKind::StructMember,
199 return ForbiddenRequireCondition {
200 .kind = ForbiddenRequireConditionKind::FunctionReturn,
207std::optional<ForbiddenIncludedPreconditions>
208classifyForbiddenIncludedPrecondition(ModuleOp module,
IncludeOp includeOp) {
209 SymbolTableCollection tables;
211 if (failed(calleeTarget)) {
220 ForbiddenIncludedPreconditions result {.includeOp = includeOp, .failures = {}};
221 for (
const auto &failure : summary.failures) {
225 result.failures.push_back(
226 ForbiddenIncludedPrecondition {
227 .calleePreconditionLoc = failure.preconditionLoc,
228 .kind = ForbiddenRequireConditionKind::StructMember,
229 .sourceLocs = failure.influenceInfo.structMemberLocs,
237 result.failures.push_back(
238 ForbiddenIncludedPrecondition {
239 .calleePreconditionLoc = failure.preconditionLoc,
240 .kind = ForbiddenRequireConditionKind::FunctionReturn,
246 return result.failures.empty() ? std::nullopt
247 : std::optional<ForbiddenIncludedPreconditions>(result);
252LogicalResult emitForbiddenPrecondition(
254 llvm::ArrayRef<Location> sourceLocs = {}
257 case ForbiddenRequireConditionKind::StructMember: {
258 InFlightDiagnostic diag =
259 preCondOp->emitOpError(
"condition cannot be derived from a struct member value");
260 for (
auto sourceLoc : sourceLocs) {
261 diag.attachNote(sourceLoc) <<
"forbidden struct member value originates here";
265 case ForbiddenRequireConditionKind::FunctionReturn: {
266 return preCondOp->emitOpError(
"condition cannot be derived from a function return value");
269 llvm_unreachable(
"unknown forbidden require condition kind");
272LogicalResult emitForbiddenIncludedPreconditions(
273 IncludeOp includeOp, llvm::ArrayRef<ForbiddenIncludedPrecondition> failures
275 bool sawStructMember =
false;
276 bool sawFunctionReturn =
false;
277 for (
const ForbiddenIncludedPrecondition &failure : failures) {
278 sawStructMember |= failure.kind == ForbiddenRequireConditionKind::StructMember;
279 sawFunctionReturn |= failure.kind == ForbiddenRequireConditionKind::FunctionReturn;
282 InFlightDiagnostic diag = [&]() -> InFlightDiagnostic {
283 if (sawStructMember && sawFunctionReturn) {
284 return includeOp.emitOpError(
285 "includes preconditions whose conditions cannot be derived from forbidden sources"
288 if (sawStructMember) {
289 return includeOp.emitOpError(
290 "includes preconditions whose conditions cannot be derived from a struct member value"
293 return includeOp.emitOpError(
294 "includes preconditions whose conditions cannot be derived from a function return value"
298 for (
const ForbiddenIncludedPrecondition &failure : failures) {
299 if (failure.calleePreconditionLoc) {
300 diag.attachNote(failure.calleePreconditionLoc) <<
"included precondition triggered here";
302 for (Location sourceLoc : failure.sourceLocs) {
303 diag.attachNote(sourceLoc) <<
"forbidden struct member value originates here";
317void ContractOp::initializeEmptyBody(
318 OpBuilder &builder, OperationState &state, FunctionType functionType
320 Region *body = state.addRegion();
321 auto *entryBlock =
new Block();
323 SmallVector<Location> argLocs(functionType.getNumInputs(), state.location);
324 entryBlock->addArguments(functionType.getInputs(), argLocs);
325 body->push_back(entryBlock);
327 ContractOp::ensureTerminator(*body, builder, state.location);
331 OpBuilder &odsBuilder, OperationState &odsState, StringRef name, llvm::StringRef target
333 build(odsBuilder, odsState, name, SymbolRefAttr::get(odsBuilder.getContext(), target));
337 ::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::StringRef name,
338 ::mlir::SymbolRefAttr target
343 SymbolTableCollection tables;
345 FailureOr<SymbolLookupResultUntyped> targetRes =
347 if (failed(targetRes)) {
350 Operation *targetOp = targetRes->get();
351 if (!isValidTarget(targetOp)) {
354 FailureOr<TargetTypeInfo> infoRes = getTargetTypeInfo(targetOp);
355 if (failed(infoRes)) {
358 TargetTypeInfo &info = *infoRes;
359 build(odsBuilder, odsState, name, target, info.funcType, info.argAttrs);
363 if (index < this->getNumArguments()) {
364 DictionaryAttr res = function_interface_impl::getArgAttrDict(*
this, index);
365 return res ? res.contains(PublicAttr::name) :
false;
373 if (index >= getNumArguments()) {
383 assert(index < getNumArguments() &&
"argument index out of range");
398 if (failed(rootRes)) {
399 return emitOpError().append(
"could not lookup root module");
401 FailureOr<SymbolLookupResultUntyped> targetRes =
403 if (failed(targetRes)) {
404 return emitOpError().append(
"could not find target \"@",
getTarget(),
"\"");
415 Operation *targetOp = targetRes->get();
416 if (!isValidTarget(targetOp)) {
418 .append(
"target \"",
getTargetAttr(),
"\" is not a supported contract target")
419 .attachNote(targetOp->getLoc())
420 .append(
"target defined here");
424 if (targetParentTemplate != contractParentTemplate) {
425 InFlightDiagnostic diag = emitOpError().append(
426 "contract nested in template \"@", contractParentTemplate.getSymName(),
427 "\" must target a symbol in the same template"
429 if (targetParentTemplate) {
430 diag.attachNote(targetParentTemplate.getLoc()).append(
"target template defined here");
432 diag.attachNote(targetOp->getLoc()).append(
"target defined here");
437 FailureOr<TargetTypeInfo> targetInfoRes = getTargetTypeInfo(targetOp);
438 if (failed(targetInfoRes)) {
442 if (isa<StructDefOp>(targetOp)) {
446 .append(
"unsupported target type \"", targetOp->getName(),
"\"")
447 .attachNote(targetOp->getLoc())
448 .append(
"target defined here");
450 TargetTypeInfo &targetInfo = *targetInfoRes;
453 functionTypesUnify(contractTy, targetInfo.funcType, targetRes->getNamespace(), &unifications);
454 if (!unifies || hasConflictingUnifications(unifications)) {
456 .append(
"contract type does not match target type")
457 .attachNote(targetOp->getLoc())
458 .append(
"target defined here");
463 "contract arg attributes ",
getArgAttrsAttr(),
" does not match target arg attributes ",
466 .attachNote(targetOp->getLoc())
467 .append(
"target defined here");
480 SmallVector<OpAsmParser::Argument> entryArgs;
481 SmallVector<DictionaryAttr> resultAttrs;
482 SmallVector<Type> resultTypes;
483 auto &builder = parser.getBuilder();
487 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(), result.attributes)) {
492 if (parser.parseKeyword(
"for")) {
496 SymbolRefAttr targetAttr;
497 if (parser.parseCustomAttributeWithFallback(
498 targetAttr, parser.getBuilder().getType<::mlir::NoneType>()
508 SMLoc signatureLocation = parser.getCurrentLocation();
509 bool isVariadic =
false;
511 if (function_interface_impl::parseFunctionSignatureWithArguments(
512 parser,
false, entryArgs, isVariadic, resultTypes, resultAttrs
516 assert(isVariadic ==
false);
518 if (!resultTypes.empty() || !resultAttrs.empty()) {
522 std::string errorMessage;
523 SmallVector<Type> argTypes;
524 argTypes.reserve(entryArgs.size());
525 for (
auto &arg : entryArgs) {
526 argTypes.push_back(arg.type);
528 Type type = builder.getFunctionType(argTypes, resultTypes);
530 return parser.emitError(signatureLocation)
531 <<
"failed to construct function type" << (errorMessage.empty() ?
"" :
": ")
534 result.addAttribute(typeAttrName, TypeAttr::get(type));
537 NamedAttrList parsedAttributes;
538 SMLoc attributeDictLocation = parser.getCurrentLocation();
539 if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes)) {
545 for (StringRef disallowed :
546 {SymbolTable::getVisibilityAttrName(), SymbolTable::getSymbolAttrName(),
547 typeAttrName.getValue()}) {
548 if (parsedAttributes.get(disallowed)) {
549 return parser.emitError(attributeDictLocation,
"'")
551 <<
"' is an inferred attribute and should not be specified in the "
552 "explicit attribute dictionary";
555 result.attributes.append(parsedAttributes);
558 call_interface_impl::addArgAndResultAttrs(
559 builder, result, entryArgs, resultAttrs, argAttrsName, resAttrsName
563 auto *body = result.addRegion();
564 SMLoc loc = parser.getCurrentLocation();
565 if (parser.parseRegion(
574 return parser.emitError(loc,
"expected non-empty contract body");
577 ContractOp::ensureTerminator(*body, parser.getBuilder(), result.location);
589 p.printAttributeWithoutType(
getTarget());
593 function_interface_impl::printFunctionSignature(
594 p, *
this, argTypes,
false, ArrayRef<Type>()
596 function_interface_impl::printFunctionAttributes(
602 Region &body = getRegion();
614 return emitOpError() <<
'\'' <<
ARG_NAME_ATTR_NAME <<
"' is only valid on function arguments";
617 if (ArrayAttr argAttrs = getAllArgAttrs()) {
618 llvm::DenseSet<StringAttr> seenNames;
619 for (
auto [i, attr] : llvm::enumerate(argAttrs)) {
620 auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr);
628 auto argName = llvm::dyn_cast<StringAttr>(argNameAttr);
631 <<
" must be a string attribute";
633 if (!llvm::isa<NoneType>(argName.getType())) {
635 <<
" must not have an explicit type";
637 if (argName.getValue().empty()) {
639 <<
" must not be empty";
641 if (!seenNames.insert(argName).second) {
643 << argName.getValue() <<
"\" on argument " << i;
652 WalkResult res = this->walk<WalkOrder::PreOrder>([
this](Operation *op) {
653 if (isa<ModuleOp, TemplateOp, FuncDefOp, StructDefOp>(op)) {
655 "cannot be nested within '", getOperation()->getName(),
"' operations"
657 return WalkResult::interrupt();
659 return WalkResult::advance();
661 return failure(res.wasInterrupted());
671 SmallVector<PreconditionOpInterface> preconditionOps =
672 walkCollect<PreconditionOpInterface>(*
this);
673 SmallVector<IncludeOp> includeOps = walkCollect<IncludeOp>(*
this);
674 if (preconditionOps.empty() && includeOps.empty()) {
678 ModuleOp module = getOperation()->getParentOfType<ModuleOp>();
680 return emitOpError(
"must have a parent module to analyze condition provenance");
684 if (
auto forbidden = classifyForbiddenConditionProvenance(module, preCond, *
this)) {
685 return emitForbiddenPrecondition(
686 preCond, forbidden->kind, forbidden->sourceLocs.getArrayRef()
692 if (
auto forbidden = classifyForbiddenIncludedPrecondition(module, includeOp)) {
693 return emitForbiddenIncludedPreconditions(forbidden->includeOp, forbidden->failures);
700FailureOr<SymbolLookupResult<StructDefOp>>
713FailureOr<SymbolLookupResult<ContractTargetOpInterface>>
724 return getArgument(0);
732 OpBuilder &odsBuilder, OperationState &odsState, SymbolRefAttr callee, ValueRange argOperands,
733 ArrayRef<Attribute> templateParams
735 odsState.addOperands(argOperands);
739 props.setCallee(callee);
744 OpBuilder &odsBuilder, OperationState &odsState, SymbolRefAttr callee,
745 ArrayRef<ValueRange> mapOperands, DenseI32ArrayAttr numDimsPerMap, ValueRange argOperands,
746 ArrayRef<Attribute> templateParams
748 odsState.addOperands(argOperands);
750 odsBuilder, odsState, mapOperands, numDimsPerMap,
753 props.setCallee(callee);
759struct IncludeOpVerifier {
760 explicit IncludeOpVerifier(
IncludeOp *c) : includeOp(c) {}
761 virtual ~IncludeOpVerifier() =
default;
763 LogicalResult verify() {
766 LogicalResult aggregateResult = success();
767 if (failed(verifyInputs())) {
768 aggregateResult = failure();
770 if (failed(verifyTemplateParams())) {
771 aggregateResult = failure();
773 return aggregateResult;
777 IncludeOp *includeOp;
779 virtual LogicalResult verifyInputs() = 0;
780 virtual LogicalResult verifyTemplateParams() = 0;
782 LogicalResult verifyNoTemplateInstantiations() {
784 return includeOp->emitOpError().append(
785 "can only have template instantiations when targeting a templated contract"
792struct KnownTargetVerifier :
public IncludeOpVerifier {
793 KnownTargetVerifier(IncludeOp *c, SymbolLookupResult<ContractOp> &&tgtRes)
794 : IncludeOpVerifier(c), shared(c, tgtRes) {}
796 LogicalResult verifyInputs()
override {
797 return shared.verifyTypesMatch(
798 includeOp->
getArgOperands().getTypes(), shared.getTargetType().getInputs(),
"operand"
802 LogicalResult verifyTemplateParams()
override {
803 Operation *tgtOp = shared.getTarget().getOperation();
805 return shared.verifyTemplateInstantiation(tgtOpParent);
808 return verifyNoTemplateInstantiations();
813 llzk::KnownTargetVerifier<IncludeOp, ContractOp> shared;
827 return emitOpError(
"requires a 'callee' symbol reference attribute");
832 if (calleeAttr.getNestedReferences().size() == 1) {
834 if (
auto constParam = parent.getConstNamed<
TemplateParamOp>(calleeAttr.getRootReference())) {
835 return this->emitError(
"expected parameterized callee to target a struct function")
836 .attachNote(constParam->getLoc())
850 if (failed(tgtOpt)) {
852 << calleeAttr <<
'"';
854 return KnownTargetVerifier(
this, std::move(*tgtOpt)).verify();
857FailureOr<SymbolLookupResult<ContractOp>>
859 Operation *thisOp = this->getOperation();
861 assert(succeeded(root));
866 SymbolTableCollection tables;
868 return succeeded(callee) && callee->get().hasStructTarget();
872 SymbolTableCollection tables;
874 assert(succeeded(callee) &&
"include callee must resolve");
875 if (!callee->get().hasStructTarget()) {
878 assert(getNumOperands() > 0 &&
"include op must have a self operand");
879 return getOperand(0);
891 FailureOr<SymbolLookupResult<ContractOp>> res =
896 if (res->isManaged()) {
898 "IncludeOp::resolveCallableInTable: cannot return "
899 "pointer to a managed Operation since it would cause memory errors. "
900 "Consider running -llzk-inline-includes to avoid encountering managed Operations."
908 SymbolTableCollection tables;
917 OpBuilder &odsBuilder, OperationState &odsState, StringRef loop_name,
918 ArrayRef<Type> loop_arg_types, ArrayRef<Location> loop_arg_locs
921 odsBuilder.getStringAttr(loop_name);
923 odsBuilder.getTypeArrayAttr(loop_arg_types);
924 auto region = std::make_unique<Region>();
925 auto &block = region->emplaceBlock();
926 block.addArguments(loop_arg_types, loop_arg_locs);
927 odsState.regions.push_back(std::move(region));
934 auto bodyArgTypes = op->getBody()->getArgumentTypes();
936 if (targetArgTypes.size() != declaredTypes.size()) {
937 return op->emitOpError() <<
"target has " << targetArgTypes.size()
938 <<
" arguments but invariant declared " << declaredTypes.size();
940 if (bodyArgTypes.size() != declaredTypes.size()) {
941 return op->emitOpError() <<
"invariant body has " << targetArgTypes.size()
942 <<
" arguments but declared " << declaredTypes.size();
946 for (
auto [n, types] :
947 llvm::enumerate(llvm::zip_equal(targetArgTypes, bodyArgTypes, declaredTypes))) {
948 auto [targetType, bodyArgType, declaredType] = types;
950 if (targetType != llvm::cast<TypeAttr>(declaredType).getValue()) {
952 op->emitOpError() <<
"target argument #" << n <<
" expected type " << targetType
953 <<
" but invariant declared type " << declaredType;
955 if (bodyArgType != llvm::cast<TypeAttr>(declaredType).getValue()) {
957 op->emitOpError() <<
"invariant argument #" << n <<
" expected type " << targetType
958 <<
" but invariant declared type " << declaredType;
962 return failure(failed);
968 if (failed(invariantTarget)) {
972 return verifyArgTypes(*invariantTarget,
this);
976 if (failed(parser.parseKeyword(
"for"))) {
981 StringAttr loopNameAttr;
982 if (parser.parseSymbolName(loopNameAttr)) {
988 bool isVariadic =
false;
989 SmallVector<OpAsmParser::Argument> entryArgs;
990 SmallVector<DictionaryAttr> resultAttrs;
991 SmallVector<Type> resultTypes;
993 if (function_interface_impl::parseFunctionSignatureWithArguments(
994 parser,
false, entryArgs, isVariadic, resultTypes, resultAttrs
998 assert(isVariadic ==
false);
1000 if (!resultTypes.empty() || !resultAttrs.empty()) {
1004 SmallVector<Type> argTypes = llvm::map_to_vector(entryArgs, [](
auto arg) {
return arg.type; });
1006 parser.getBuilder().getTypeArrayAttr(argTypes);
1008 auto *body = result.addRegion();
1009 SMLoc loc = parser.getCurrentLocation();
1010 if (parser.parseRegion(
1017 if (body->empty()) {
1018 return parser.emitError(loc,
"expected non-empty invariant body");
1029 llvm::interleave(getBody()->getArguments(), [&p](
auto arg) {
1030 p.printRegionArgument(arg);
1031 }, [&p]() { p <<
", "; });
1042 return this->getOperation()->getParentOfType<
ContractOp>();
1047 if (failed(target)) {
1050 SmallVector<InvariantTargetOpInterface> matches;
1051 for (
auto invariantTarget : target->get().getLoops()) {
1052 auto targetLabel = invariantTarget.getLabel();
1053 if (succeeded(targetLabel) && *targetLabel ==
getLoopName()) {
1054 matches.push_back(invariantTarget);
1058 if (matches.size() == 0) {
1059 return emitOpError() <<
"no invariant target with label \"" <<
getLoopName()
1060 <<
"\" found in contract target " << target->get().getNameAttr();
1062 if (matches.size() > 1) {
1063 return emitOpError() <<
"ambiguous label \"" <<
getLoopName() <<
"\" matched " << matches.size()
1064 <<
" invariant targets in contract target " << target->get().getNameAttr();
This file contains an analysis and utilities for determining if a verif precondition is dependent,...
::mlir::FunctionType getFunctionType()
::mlir::ArrayAttr getArgAttrsAttr()
::mlir::StringAttr getFunctionTypeAttrName()
::mlir::StringAttr getResAttrsAttrName()
::llvm::LogicalResult verifyRegions()
void setArgNameAttr(unsigned index, const ::mlir::StringAttr &attr)
Set the function.arg_name attribute for the argument at the given index.
bool hasArgName(unsigned index)
Return true iff the argument at the given index has a function.arg_name attribute.
bool hasArgPublicAttr(unsigned index)
Return true iff the argument at the given index has pub attribute.
static constexpr ::llvm::StringLiteral getOperationName()
::mlir::StringAttr getTargetAttrName()
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::llvm::LogicalResult verify()
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::StringAttr sym_name, ::mlir::SymbolRefAttr target, ::mlir::TypeAttr function_type, ::mlir::ArrayAttr arg_attrs={}, ::mlir::ArrayAttr res_attrs={})
void print(::mlir::OpAsmPrinter &p)
::mlir::FunctionType getFunctionType()
void setArgName(unsigned index, ::llvm::StringRef name)
Set the function.arg_name attribute for the argument at the given index from a string.
::mlir::FailureOr< SymbolLookupResult<::llzk::verif::ContractTargetOpInterface > > getTargetOp(::mlir::SymbolTableCollection &tables)
Return the operation that this contract targets, or failure if it does not target an operation that i...
::std::optional<::mlir::StringAttr > getArgNameAttr(unsigned index)
Return the function.arg_name attribute for the argument at the given index.
::llvm::ArrayRef<::mlir::Type > getArgumentTypes()
Required by FunctionOpInterface.
::mlir::StringAttr getArgAttrsAttrName()
::mlir::SymbolRefAttr getTargetAttr()
::mlir::SymbolRefAttr getFullyQualifiedName(bool requireParent=true)
Return the full name for this contract from the root module, including all surrounding symbol table n...
::mlir::FailureOr< SymbolLookupResult<::llzk::verif::ContractTargetOpInterface > > getTargetOp()
::mlir::FailureOr<::mlir::Value > getSelfValue()
Return the "self" value (i.e.
::mlir::ArrayAttr getArgAttrsAttr()
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
::mlir::SymbolRefAttr getTarget()
FoldAdaptor::Properties Properties
::mlir::FailureOr< SymbolLookupResult< component::StructDefOp > > getStructTarget()
::mlir::FailureOr< SymbolLookupResult< function::FuncDefOp > > getFuncTarget()
::llvm::StringRef getSymName()
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::mlir::SymbolRefAttr getCalleeAttr()
FoldAdaptor::Properties Properties
::mlir::Operation::operand_range getArgOperands()
void setCalleeAttr(::mlir::SymbolRefAttr attr)
::mlir::FailureOr<::llzk::SymbolLookupResult<::llzk::verif::ContractOp > > getCalleeTarget(::mlir::SymbolTableCollection &tables)
Resolve and return the target Contract for this CallOp.
::mlir::Operation * resolveCallable()
::mlir::SymbolRefAttr getCallee()
::mlir::Value getSelfValue()
void setCalleeFromCallable(::mlir::CallInterfaceCallable callee)
Set the callee for this operation.
bool contractTargetsStruct()
Return true iff the contract targets a struct type.
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::SymbolRefAttr callee, ::mlir::ValueRange argOperands={}, ::llvm::ArrayRef<::mlir::Attribute > templateParams={})
::mlir::Operation * resolveCallableInTable(::mlir::SymbolTableCollection *symbolTable)
::mlir::CallInterfaceCallable getCallableForCallee()
Return the callee of this operation.
::mlir::FailureOr<::llzk::verif::InvariantTargetOpInterface > getTarget()
Returns the loop target.
::mlir::ParseResult parse(::mlir::OpAsmParser &parser, ::mlir::OperationState &result)
void print(::mlir::OpAsmPrinter &p)
::mlir::ArrayAttr getLoopArgTypes()
::llvm::StringRef getLoopName()
::llzk::verif::ContractOp getParentContract()
Returns the contract operation that contains this invariant.
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::StringRef loop_name, ::llvm::ArrayRef<::mlir::Type > loop_arg_types={}, ::llvm::ArrayRef<::mlir::Location > loop_arg_locs={})
FoldAdaptor::Properties Properties
::llvm::LogicalResult verify()
::mlir::Region & getRegion()
::mlir::SmallVector<::mlir::Type > getArgumentTypes()
Gets the types of the values that the invariant binds inside its body.
OpClass::Properties & buildInstantiationAttrs(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, mlir::ArrayRef< mlir::ValueRange > mapOperands, mlir::DenseI32ArrayAttr numDimsPerMap, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
OpClass::Properties & buildInstantiationAttrsEmpty(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
constexpr char ARG_NAME_ATTR_NAME[]
Attribute name for source-level function argument names.
detail::IncludedContractSummary analyzeForbiddenIncludedOpSummary(mlir::ModuleOp module, verif::ContractOp contract, verif::IncludeOp includeOp)
Analyze whether a specific include op triggers forbidden preconditions in the callee,...
bool hasInfluence(ForbiddenPreconditionInfluence influence, ForbiddenPreconditionInfluence flag)
Return true when influence contains the requested flag.
ForbiddenPreconditionInfluenceInfo analyzeForbiddenPreconditionOpInfluenceInfo(mlir::ModuleOp module, verif::ContractOp contract, verif::PreconditionOpInterface preCondOp)
Analyze whether a precondition op depends on forbidden sources, including both its condition operand ...
constexpr char FUNC_NAME_COMPUTE[]
Symbol name for the witness generation (and resp.
mlir::FailureOr< SymbolLookupResultUntyped > lookupTopLevelSymbol(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, mlir::Operation *origin, bool reportMissing=true)
constexpr char FUNC_NAME_CONSTRAIN[]
FailureOr< ModuleOp > getRootModule(Operation *from)
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
bool isNullOrEmpty(mlir::ArrayAttr a)
OpClass getParentOfType(mlir::Operation *op)
Return the closest surrounding parent/ancestor operation that is of type 'OpClass'.
constexpr char FUNC_NAME_PRODUCT[]
constexpr T checkedCast(U u) noexcept
mlir::FailureOr< SymbolLookupResult< T > > resolveCallable(mlir::SymbolTableCollection &symbolTable, mlir::CallOpInterface call)
Based on mlir::CallOpInterface::resolveCallable, but using LLZK lookup helpers.
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op)
mlir::FailureOr< SymbolLookupResultUntyped > lookupSymbolIn(mlir::SymbolTableCollection &tables, mlir::SymbolRefAttr symbol, Within &&lookupWithin, mlir::Operation *origin, bool reportMissing=true)
std::function< InFlightDiagnosticWrapper()> OwningEmitErrorFn
This type is required in cases like the functions below to take ownership of the lambda so it is not ...
mlir::SymbolRefAttr getFullyQualifiedName(mlir::SymbolOpInterface symbol, bool requireParent=true)
Return the full name for this symbol from the root module, including any surrounding symbol table nam...
bool functionTypesUnify(FunctionType lhs, FunctionType rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
void addTemplateParams(mlir::OpBuilder &odsBuilder, typename OpClass::Properties &props, llvm::ArrayRef< mlir::Attribute > templateParams)
Summary of forbidden precondition influence along with representative source locations for each forbi...
ForbiddenPreconditionInfluence influence
llvm::SmallSetVector< mlir::Location, 2 > structMemberLocs