27#include <mlir/Dialect/Arith/IR/Arith.h>
28#include <mlir/Dialect/SCF/IR/SCF.h>
29#include <mlir/Dialect/Utils/IndexingUtils.h>
30#include <mlir/IR/Attributes.h>
31#include <mlir/IR/BuiltinOps.h>
32#include <mlir/IR/Diagnostics.h>
33#include <mlir/IR/SymbolTable.h>
34#include <mlir/IR/ValueRange.h>
35#include <mlir/Interfaces/FunctionImplementation.h>
36#include <mlir/Support/LogicalResult.h>
38#include <llvm/ADT/ArrayRef.h>
39#include <llvm/ADT/Twine.h>
59bool isValidTarget(Operation *op) {
60 if (
auto fnOp = dyn_cast<FuncDefOp>(op)) {
62 return fnOp->getParentOfType<
StructDefOp>() ==
nullptr;
65 return isa<StructDefOp>(op);
68struct TargetTypeInfo {
69 FunctionType funcType {};
70 ArrayAttr argAttrs {};
73FailureOr<TargetTypeInfo> getTargetTypeInfo(Operation *op) {
74 if (
auto fnOp = dyn_cast<FuncDefOp>(op)) {
76 FunctionType fnTy = fnOp.getFunctionType();
77 ArrayRef<Type> curInputs = fnTy.getInputs(), curResults = fnTy.getResults();
78 SmallVector<Type> newInputs;
79 newInputs.reserve(curInputs.size() + curResults.size());
80 newInputs.insert(newInputs.end(), curInputs.begin(), curInputs.end());
81 newInputs.insert(newInputs.end(), curResults.begin(), curResults.end());
83 auto newFnTy = fnTy.clone(newInputs, {});
85 ArrayAttr curArgAttrs = fnOp.getArgAttrsAttr(), curResAttrs = fnOp.getResAttrsAttr();
86 ArrayAttr newArgAttrsAttr {};
87 if (curArgAttrs || curResAttrs) {
88 auto *ctx = op->getContext();
89 SmallVector<Attribute> newArgAttrs;
91 newArgAttrs.reserve(newInputs.size());
93 newArgAttrs.insert(newArgAttrs.end(), curArgAttrs.begin(), curArgAttrs.end());
96 newArgAttrs.insert(newArgAttrs.end(), curInputs.size(), DictionaryAttr::get(ctx));
99 newArgAttrs.insert(newArgAttrs.end(), curResAttrs.begin(), curResAttrs.end());
102 newArgAttrs.insert(newArgAttrs.end(), curResults.size(), DictionaryAttr::get(ctx));
104 newArgAttrsAttr = ArrayAttr::get(ctx, newArgAttrs);
107 return TargetTypeInfo {
109 .argAttrs = newArgAttrsAttr,
112 if (
auto structOp = dyn_cast<StructDefOp>(op)) {
113 if (structOp.hasComputeConstrain()) {
114 auto fnOp = structOp.getConstrainFuncOp();
115 return TargetTypeInfo {
116 .funcType = fnOp.getFunctionType(),
117 .argAttrs = fnOp.getArgAttrsAttr(),
120 FuncDefOp productFn = structOp.getProductFuncOp();
124 ArrayRef<Type> curInputs = fnTy.getInputs();
126 SmallVector<Type> newInputs;
127 newInputs.reserve(curInputs.size() + 1);
128 newInputs.push_back(structOp.getType());
129 newInputs.insert(newInputs.end(), curInputs.begin(), curInputs.end());
131 auto newFnTy = fnTy.clone(newInputs, {});
133 auto *ctx = op->getContext();
135 ArrayAttr newArgAttrsAttr = curArgAttrs;
137 SmallVector<Attribute> newArgAttrs;
138 newArgAttrs.reserve(curArgAttrs.size() + 1);
139 newArgAttrs.push_back(DictionaryAttr::get(ctx));
140 newArgAttrs.insert(newArgAttrs.end(), curArgAttrs.begin(), curArgAttrs.end());
141 newArgAttrsAttr = ArrayAttr::get(ctx, newArgAttrs);
143 return TargetTypeInfo {
145 .argAttrs = newArgAttrsAttr,
153enum class ForbiddenRequireConditionKind : uint8_t {
160struct ForbiddenRequireCondition {
161 ForbiddenRequireConditionKind kind;
162 llvm::SmallSetVector<Location, 2> sourceLocs;
167struct ForbiddenIncludedPrecondition {
168 std::optional<Location> calleePreconditionLoc = std::nullopt;
169 ForbiddenRequireConditionKind kind;
170 llvm::SmallSetVector<Location, 2> sourceLocs;
174struct ForbiddenIncludedPreconditions {
176 llvm::SmallVector<ForbiddenIncludedPrecondition> failures;
179std::optional<ForbiddenRequireCondition> classifyForbiddenConditionProvenance(
185 return ForbiddenRequireCondition {
186 .kind = ForbiddenRequireConditionKind::StructMember,
191 return ForbiddenRequireCondition {
192 .kind = ForbiddenRequireConditionKind::FunctionReturn,
199std::optional<ForbiddenIncludedPreconditions>
200classifyForbiddenIncludedPrecondition(ModuleOp module,
IncludeOp includeOp) {
201 SymbolTableCollection tables;
203 if (failed(calleeTarget)) {
212 ForbiddenIncludedPreconditions result {.includeOp = includeOp, .failures = {}};
213 for (
const auto &failure : summary.failures) {
217 result.failures.push_back(
218 ForbiddenIncludedPrecondition {
219 .calleePreconditionLoc = failure.preconditionLoc,
220 .kind = ForbiddenRequireConditionKind::StructMember,
221 .sourceLocs = failure.influenceInfo.structMemberLocs,
229 result.failures.push_back(
230 ForbiddenIncludedPrecondition {
231 .calleePreconditionLoc = failure.preconditionLoc,
232 .kind = ForbiddenRequireConditionKind::FunctionReturn,
238 return result.failures.empty() ? std::nullopt
239 : std::optional<ForbiddenIncludedPreconditions>(result);
244LogicalResult emitForbiddenPrecondition(
246 llvm::ArrayRef<Location> sourceLocs = {}
249 case ForbiddenRequireConditionKind::MainContract:
250 return preCondOp->emitOpError(
251 "cannot appear directly in a contract that targets the main entry-point struct"
253 case ForbiddenRequireConditionKind::StructMember: {
254 InFlightDiagnostic diag =
255 preCondOp->emitOpError(
"condition cannot be derived from a struct member value");
256 for (
auto sourceLoc : sourceLocs) {
257 diag.attachNote(sourceLoc) <<
"forbidden struct member value originates here";
261 case ForbiddenRequireConditionKind::FunctionReturn: {
262 return preCondOp->emitOpError(
"condition cannot be derived from a function return value");
265 llvm_unreachable(
"unknown forbidden require condition kind");
268LogicalResult emitForbiddenIncludedPreconditions(
269 IncludeOp includeOp, llvm::ArrayRef<ForbiddenIncludedPrecondition> failures
271 bool sawStructMember =
false;
272 bool sawFunctionReturn =
false;
273 for (
const ForbiddenIncludedPrecondition &failure : failures) {
274 sawStructMember |= failure.kind == ForbiddenRequireConditionKind::StructMember;
275 sawFunctionReturn |= failure.kind == ForbiddenRequireConditionKind::FunctionReturn;
278 InFlightDiagnostic diag = [&]() -> InFlightDiagnostic {
279 if (sawStructMember && sawFunctionReturn) {
280 return includeOp.emitOpError(
281 "includes preconditions whose conditions cannot be derived from forbidden sources"
284 if (sawStructMember) {
285 return includeOp.emitOpError(
286 "includes preconditions whose conditions cannot be derived from a struct member value"
289 return includeOp.emitOpError(
290 "includes preconditions whose conditions cannot be derived from a function return value"
294 for (
const ForbiddenIncludedPrecondition &failure : failures) {
295 if (failure.calleePreconditionLoc) {
296 diag.attachNote(*failure.calleePreconditionLoc) <<
"included precondition triggered here";
298 for (Location sourceLoc : failure.sourceLocs) {
299 diag.attachNote(sourceLoc) <<
"forbidden struct member value originates here";
313void ContractOp::initializeEmptyBody(
314 OpBuilder &builder, OperationState &state, FunctionType functionType
316 Region *body = state.addRegion();
317 auto *entryBlock =
new Block();
319 SmallVector<Location> argLocs(functionType.getNumInputs(), state.location);
320 entryBlock->addArguments(functionType.getInputs(), argLocs);
321 body->push_back(entryBlock);
323 ContractOp::ensureTerminator(*body, builder, state.location);
327 OpBuilder &odsBuilder, OperationState &odsState, StringRef name, llvm::StringRef target
329 build(odsBuilder, odsState, name, SymbolRefAttr::get(odsBuilder.getContext(), target));
333 ::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::StringRef name,
334 ::mlir::SymbolRefAttr target
339 SymbolTableCollection tables;
341 FailureOr<SymbolLookupResultUntyped> targetRes =
343 if (failed(targetRes)) {
346 Operation *targetOp = targetRes->get();
347 if (!isValidTarget(targetOp)) {
350 FailureOr<TargetTypeInfo> infoRes = getTargetTypeInfo(targetOp);
351 if (failed(infoRes)) {
354 TargetTypeInfo &info = *infoRes;
355 build(odsBuilder, odsState, name, target, info.funcType, info.argAttrs);
359 if (index < this->getNumArguments()) {
360 DictionaryAttr res = function_interface_impl::getArgAttrDict(*
this, index);
361 return res ? res.contains(PublicAttr::name) :
false;
369 if (index >= getNumArguments()) {
379 assert(index < getNumArguments() &&
"argument index out of range");
388 if (!requireParent && getOperation()->getParentOp() ==
nullptr) {
389 return SymbolRefAttr::get(getOperation());
392 assert(succeeded(res));
399 if (failed(rootRes)) {
400 return emitOpError().append(
"could not lookup root module");
402 FailureOr<SymbolLookupResultUntyped> targetRes =
404 if (failed(targetRes)) {
405 return emitOpError().append(
"could not find target \"@",
getTarget(),
"\"");
416 Operation *targetOp = targetRes->get();
417 if (!isValidTarget(targetOp)) {
419 .append(
"target \"",
getTargetAttr(),
"\" is not a supported contract target")
420 .attachNote(targetOp->getLoc())
421 .append(
"target defined here");
423 FailureOr<TargetTypeInfo> targetInfoRes = getTargetTypeInfo(targetOp);
424 if (failed(targetInfoRes)) {
426 .append(
"unsupported target type \"", targetOp->getName(),
"\"")
427 .attachNote(targetOp->getLoc())
428 .append(
"target defined here");
430 TargetTypeInfo &targetInfo = *targetInfoRes;
431 if (targetInfo.funcType != contractTy) {
433 .append(
"contract type does not match target type")
434 .attachNote(targetOp->getLoc())
435 .append(
"target defined here");
440 "contract arg attributes ",
getArgAttrsAttr(),
" does not match target arg attributes ",
443 .attachNote(targetOp->getLoc())
444 .append(
"target defined here");
456 SmallVector<OpAsmParser::Argument> entryArgs;
457 SmallVector<DictionaryAttr> resultAttrs;
458 SmallVector<Type> resultTypes;
459 auto &builder = parser.getBuilder();
463 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(), result.attributes)) {
468 if (parser.parseKeyword(
"for")) {
472 SymbolRefAttr targetAttr;
473 if (parser.parseCustomAttributeWithFallback(
474 targetAttr, parser.getBuilder().getType<::mlir::NoneType>()
484 SMLoc signatureLocation = parser.getCurrentLocation();
485 bool isVariadic =
false;
487 if (function_interface_impl::parseFunctionSignature(
488 parser,
false, entryArgs, isVariadic, resultTypes, resultAttrs
492 assert(isVariadic ==
false);
494 if (!resultTypes.empty() || !resultAttrs.empty()) {
498 std::string errorMessage;
499 SmallVector<Type> argTypes;
500 argTypes.reserve(entryArgs.size());
501 for (
auto &arg : entryArgs) {
502 argTypes.push_back(arg.type);
504 Type type = builder.getFunctionType(argTypes, resultTypes);
506 return parser.emitError(signatureLocation)
507 <<
"failed to construct function type" << (errorMessage.empty() ?
"" :
": ")
510 result.addAttribute(typeAttrName, TypeAttr::get(type));
513 NamedAttrList parsedAttributes;
514 SMLoc attributeDictLocation = parser.getCurrentLocation();
515 if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes)) {
521 for (StringRef disallowed :
522 {SymbolTable::getVisibilityAttrName(), SymbolTable::getSymbolAttrName(),
523 typeAttrName.getValue()}) {
524 if (parsedAttributes.get(disallowed)) {
525 return parser.emitError(attributeDictLocation,
"'")
527 <<
"' is an inferred attribute and should not be specified in the "
528 "explicit attribute dictionary";
531 result.attributes.append(parsedAttributes);
534 function_interface_impl::addArgAndResultAttrs(
535 builder, result, entryArgs, resultAttrs, argAttrsName,
536 StringAttr::get(parser.getContext())
540 auto *body = result.addRegion();
541 SMLoc loc = parser.getCurrentLocation();
542 if (parser.parseRegion(
551 return parser.emitError(loc,
"expected non-empty contract body");
554 ContractOp::ensureTerminator(*body, parser.getBuilder(), result.location);
566 p.printAttributeWithoutType(
getTarget());
570 function_interface_impl::printFunctionSignature(
571 p, *
this, argTypes,
false, ArrayRef<Type>()
573 function_interface_impl::printFunctionAttributes(
578 Region &body = getRegion();
590 return emitOpError() <<
'\'' <<
ARG_NAME_ATTR_NAME <<
"' is only valid on function arguments";
593 if (ArrayAttr argAttrs = getAllArgAttrs()) {
594 llvm::DenseSet<StringAttr> seenNames;
595 for (
auto [i, attr] : llvm::enumerate(argAttrs)) {
596 auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr);
604 auto argName = llvm::dyn_cast<StringAttr>(argNameAttr);
607 <<
" must be a string attribute";
609 if (!llvm::isa<NoneType>(argName.getType())) {
611 <<
" must not have an explicit type";
613 if (argName.getValue().empty()) {
615 <<
" must not be empty";
617 if (!seenNames.insert(argName).second) {
619 << argName.getValue() <<
"\" on argument " << i;
628 WalkResult res = this->walk<WalkOrder::PreOrder>([
this](Operation *op) {
629 if (isa<ModuleOp, TemplateOp, FuncDefOp, StructDefOp>(op)) {
631 "cannot be nested within '", getOperation()->getName(),
"' operations"
633 return WalkResult::interrupt();
635 return WalkResult::advance();
637 return failure(res.wasInterrupted());
647 SmallVector<PreconditionOpInterface> preconditionOps =
648 walkCollect<PreconditionOpInterface>(*
this);
649 SmallVector<IncludeOp> includeOps = walkCollect<IncludeOp>(*
this);
650 if (preconditionOps.empty() && includeOps.empty()) {
654 bool targetsMainStruct =
false;
656 SymbolTableCollection tables;
658 targetsMainStruct = succeeded(structTarget) && structTarget->get().isMainComponent();
662 if (targetsMainStruct) {
663 return emitForbiddenPrecondition(preCond, ForbiddenRequireConditionKind::MainContract);
667 ModuleOp module = getOperation()->getParentOfType<ModuleOp>();
669 return emitOpError(
"must have a parent module to analyze condition provenance");
673 if (
auto forbidden = classifyForbiddenConditionProvenance(module, preCond, *
this)) {
674 return emitForbiddenPrecondition(
675 preCond, forbidden->kind, forbidden->sourceLocs.getArrayRef()
681 if (
auto forbidden = classifyForbiddenIncludedPrecondition(module, includeOp)) {
682 return emitForbiddenIncludedPreconditions(forbidden->includeOp, forbidden->failures);
689FailureOr<SymbolLookupResult<StructDefOp>>
706 return getArgument(0);
714 OpBuilder &odsBuilder, OperationState &odsState, SymbolRefAttr callee, ValueRange argOperands,
715 ArrayRef<Attribute> templateParams
717 odsState.addOperands(argOperands);
721 props.setCallee(callee);
726 OpBuilder &odsBuilder, OperationState &odsState, SymbolRefAttr callee,
727 ArrayRef<ValueRange> mapOperands, DenseI32ArrayAttr numDimsPerMap, ValueRange argOperands,
728 ArrayRef<Attribute> templateParams
730 odsState.addOperands(argOperands);
732 odsBuilder, odsState, mapOperands, numDimsPerMap,
735 props.setCallee(callee);
744 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(paramFromIncludeOp)) {
746 std::optional<Type> declaredType = targetParam.
getTypeOpt();
747 if (!declaredType || !llvm::isa<TypeVarType>(*declaredType)) {
748 auto diag = this->emitOpError().append(
749 "wildcard `?` can only be used for template parameters with `!poly.tvar` "
750 "type restriction, but parameter \"@",
751 targetParam.getName(),
"\" has "
754 diag.append(
"type restriction ", *declaredType);
756 diag.append(
"no type restriction");
763 if (std::optional<Type> declaredType = targetParam.
getTypeOpt()) {
765 bool compatible =
false;
766 if (llvm::isa<TypeVarType>(*declaredType)) {
767 compatible = llvm::isa<TypeAttr>(paramFromIncludeOp);
768 }
else if (llvm::isa<FeltType>(*declaredType)) {
769 compatible = llvm::isa<FeltConstAttr, IntegerAttr>(paramFromIncludeOp) &&
771 }
else if (llvm::isa<IndexType, IntegerType>(*declaredType)) {
775 compatible = llvm::isa<IntegerAttr>(paramFromIncludeOp) &&
778 llvm_unreachable(
"inconsistent with `isValidConstReadType()`");
781 return this->emitOpError().append(
782 "instantiation value '", paramFromIncludeOp,
"' is not compatible with parameter \"@",
783 targetParam.getName(),
"\" type restriction ", *declaredType
791 llvm::iterator_range<Region::op_iterator<TemplateParamOp>> targetParamDefs
795 assert((callParams.size() == llvm::range_size(targetParamDefs)) &&
"pre-condition");
797 for (
auto [paramOp, attr] : llvm::zip_equal(targetParamDefs, callParams.getValue())) {
806 llvm::iterator_range<Region::op_iterator<TemplateParamOp>> targetParamDefs,
811 assert((callParams.size() == llvm::range_size(targetParamDefs)) &&
"pre-condition");
813 for (
auto [paramOp, attr] : llvm::zip_equal(targetParamDefs, callParams.getValue())) {
815 if (
isDynamic(llvm::dyn_cast<IntegerAttr>(attr))) {
818 auto it = unifications.find({FlatSymbolRefAttr::get(paramOp.getNameAttr()),
Side::RHS});
819 if (it != unifications.end() && !
typeParamsUnify({attr}, {it->second})) {
820 return this->emitOpError().append(
821 "template instantiation value '", attr,
"' for parameter \"@", paramOp.getName(),
822 "\" conflicts with value '", it->second,
"' inferred from function type signature"
831struct IncludeOpVerifier {
832 explicit IncludeOpVerifier(
IncludeOp *c) : includeOp(c) {}
833 virtual ~IncludeOpVerifier() =
default;
835 LogicalResult verify() {
838 LogicalResult aggregateResult = success();
839 if (failed(verifyInputs())) {
840 aggregateResult = failure();
842 if (failed(verifyTemplateParams())) {
843 aggregateResult = failure();
845 return aggregateResult;
849 IncludeOp *includeOp;
851 virtual LogicalResult verifyInputs() = 0;
852 virtual LogicalResult verifyTemplateParams() = 0;
854 LogicalResult verifyNoTemplateInstantiations() {
856 return includeOp->emitOpError().append(
857 "can only have template instantiations when targeting a templated contract"
864struct KnownTargetVerifier :
public IncludeOpVerifier {
865 KnownTargetVerifier(IncludeOp *c, SymbolLookupResult<ContractOp> &&tgtRes)
866 : IncludeOpVerifier(c), tgt(*tgtRes), tgtType(tgt.getFunctionType()),
867 includeSymNames(tgtRes.getNamespace()) {}
869 LogicalResult verifyInputs()
override {
870 return verifyTypesMatch(includeOp->
getArgOperands().getTypes(), tgtType.getInputs(),
"operand");
873 LogicalResult verifyTemplateParams()
override {
874 Operation *tgtOp = tgt.getOperation();
884 auto realParams = tgtOpParent.getConstOps<TemplateParamOp>();
889 llvm::SmallDenseSet<SymbolRefAttr> referencedInSignature;
893 bool allParamsReferenced = llvm::all_of(realParams, [&](TemplateParamOp p) {
894 return referencedInSignature.contains(FlatSymbolRefAttr::get(p.getNameAttr()));
896 if (allParamsReferenced) {
899 return includeOp->emitOpError().append(
900 "must provide template instantiation parameters when calling \"@", tgt.getSymName(),
901 "\" because not all template parameters of \"@", tgtOpParent.getSymName(),
902 "\" appear in the function type signature"
908 return llzk::InFlightDiagnosticWrapper(this->includeOp->emitOpError());
914 size_t numTemplateParams = llvm::range_size(realParams);
915 if (callParams.size() != numTemplateParams) {
916 return includeOp->emitOpError().append(
917 "template instantiation has ", callParams.size(),
" parameter(s) but \"@",
918 tgtOpParent.getSymName(),
"\" expects ", numTemplateParams,
" template parameter(s)"
933 if (failed(unifyResult)) {
939 return verifyNoTemplateInstantiations();
944 template <
typename T>
946 verifyTypesMatch(ValueTypeRange<T> includeOpTypes, ArrayRef<Type> tgtTypes,
const char *aspect) {
947 if (tgtTypes.size() != includeOpTypes.size()) {
948 return includeOp->emitOpError()
949 .append(
"incorrect number of ", aspect,
"s for callee, expected ", tgtTypes.size())
950 .attachNote(tgt.getLoc())
951 .append(
"callee defined here");
953 for (
unsigned i = 0, e = tgtTypes.size(); i != e; ++i) {
954 if (!
typesUnify(includeOpTypes[i], tgtTypes[i], includeSymNames)) {
955 return includeOp->emitOpError().append(
956 aspect,
" type mismatch: expected type ", tgtTypes[i],
", but found ",
957 includeOpTypes[i],
" for ", aspect,
" number ", i
965 FunctionType tgtType;
966 std::vector<llvm::StringRef> includeSymNames;
980 return emitOpError(
"requires a 'callee' symbol reference attribute");
985 if (calleeAttr.getNestedReferences().size() == 1) {
987 if (
auto constParam = parent.getConstNamed<
TemplateParamOp>(calleeAttr.getRootReference())) {
988 return this->emitError(
"expected parameterized callee to target a struct function")
989 .attachNote(constParam->getLoc())
1003 if (failed(tgtOpt)) {
1005 << calleeAttr <<
'"';
1007 return KnownTargetVerifier(
this, std::move(*tgtOpt)).verify();
1011 return FunctionType::get(getContext(),
getArgOperands().getTypes(), {});
1017 return unifications;
1022FailureOr<SymbolLookupResult<ContractOp>>
1024 Operation *thisOp = this->getOperation();
1026 assert(succeeded(root));
1031 SymbolTableCollection tables;
1033 return succeeded(callee) && callee->get().hasStructTarget();
1037 SymbolTableCollection tables;
1039 assert(succeeded(callee) &&
"include callee must resolve");
1040 if (!callee->get().hasStructTarget()) {
1043 assert(getNumOperands() > 0 &&
"include op must have a self operand");
1044 return getOperand(0);
1056 llvm::SmallVector<ValueRange, 4> output;
1057 output.reserve(input.size());
1058 output.insert(output.end(), input.begin(), input.end());
1063 FailureOr<SymbolLookupResult<ContractOp>> res =
1068 if (res->isManaged()) {
1070 "IncludeOp::resolveCallableInTable: cannot return "
1071 "pointer to a managed Operation since it would cause memory errors. "
1072 "Consider running -llzk-inline-includes to avoid encountering managed Operations."
1080 SymbolTableCollection tables;
This file contains an analysis and utilities for determining if a verif precondition is dependent,...
::mlir::FunctionType getFunctionType()
::mlir::ArrayAttr getArgAttrsAttr()
::std::optional<::mlir::Type > getTypeOpt()
::mlir::StringAttr getFunctionTypeAttrName()
::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()
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.
::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<::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()
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::StringAttr sym_name, ::mlir::SymbolRefAttr target, ::mlir::TypeAttr function_type, ::mlir::ArrayAttr arg_attrs={})
::llvm::StringRef getSymName()
::mlir::LogicalResult verifyTemplateParamCompatibility(::mlir::Attribute paramFromCallOp, ::llzk::polymorphic::TemplateParamOp targetParam)
Check type compatibility of the given template parameter value from this CallOp against the declared ...
::mlir::ArrayAttr getTemplateParamsAttr()
::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()
Required by CallOpInterface.
::mlir::SymbolRefAttr getCallee()
::mlir::Value getSelfValue()
Return the "self" value (i.e.
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::FunctionType getTypeSignature()
Return the FunctionType inferred from the arg operands of this CallOp.
::mlir::LogicalResult verifyTemplateParamsMatchInferred(::llvm::iterator_range<::mlir::Region::op_iterator<::llzk::polymorphic::TemplateParamOp > > targetParamDefs, const UnificationMap &unifications)
Verify that each template parameter value provided in this CallOp is consistent with the value inferr...
::mlir::FailureOr< UnificationMap > unifyTypeSignature(::mlir::FunctionType other)
Attempt type unfication between the inferred FunctionType from this CallOp (as LHS) and the given Fun...
::mlir::Operation * resolveCallableInTable(::mlir::SymbolTableCollection *symbolTable)
Required by CallOpInterface.
static ::llvm::SmallVector<::mlir::ValueRange > toVectorOfValueRange(::mlir::OperandRangeRange)
Allocate consecutive storage of the ValueRange instances in the parameter so it can be passed to the ...
::mlir::CallInterfaceCallable getCallableForCallee()
Return the callee of this operation.
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)
void getSymbolsUsedIn(mlir::Type t, llvm::SmallDenseSet< mlir::SymbolRefAttr > &symbolsUsed)
Add all symbols used within the given Type to the provided set.
mlir::DenseMap< std::pair< mlir::SymbolRefAttr, Side >, mlir::Attribute > UnificationMap
Optional result from type unifications.
FailureOr< SmallVector< Attribute > > forceIntAttrTypes(ArrayRef< Attribute > attrList, EmitErrorFn emitError)
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)
bool isDynamic(IntegerAttr intAttr)
std::function< InFlightDiagnosticWrapper()> OwningEmitErrorFn
This type is required in cases like the functions below to take ownership of the lambda so it is not ...
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool typeParamsUnify(const ArrayRef< Attribute > &lhsParams, const ArrayRef< Attribute > &rhsParams, UnificationMap *unifications)
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)
FailureOr< SymbolRefAttr > getPathFromRoot(SymbolOpInterface to, ModuleOp *foundRoot)
bool isValidConstReadType(Type type)
Summary of forbidden precondition influence along with representative source locations for each forbi...
ForbiddenPreconditionInfluence influence
llvm::SmallSetVector< mlir::Location, 2 > structMemberLocs