1//===-- OpInterfaces.td ------------------------------------*- tablegen -*-===//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2026 Project LLZK
6// SPDX-License-Identifier: Apache-2.0
8//===----------------------------------------------------------------------===//
10#ifndef LLZK_VERIF_OP_INTERFACES
11#define LLZK_VERIF_OP_INTERFACES
13include "mlir/IR/Interfaces.td"
14include "mlir/Interfaces/SideEffectInterfaces.td"
15include "mlir/Interfaces/MemorySlotInterfaces.td"
16include "mlir/IR/SymbolInterfaces.td"
18def ConditionOpInterface
19 : OpInterface<"ConditionOpInterface", [DeclareOpInterfaceMethods<
20 MemoryEffectsOpInterface>]> {
22 Common interface for precondition and postcondition operations.
24 This declares the `MemoryEffectsOpInterface`, which, like the `cf.assert` (MLIR `cf` dialect)
25 and `bool.assert` (LLZK `bool` dialect) ops, adds a MemWrite affect to model program termination.
27 let cppNamespace = "::llzk::verif";
30 // Requires implementors to have a condition argument
31 InterfaceMethod<[{Gets the SSA Value for the condition operand.}],
32 "::mlir::TypedValue<::mlir::IntegerType>", "getCondition",
36def PreconditionOpInterface
37 : OpInterface<"PreconditionOpInterface", [ConditionOpInterface]> {
39 Common interface for precondition operations (i.e., `require_*`).
41 let cppNamespace = "::llzk::verif";
44def PostconditionOpInterface
45 : OpInterface<"PostconditionOpInterface", [ConditionOpInterface]> {
47 Common interface for postcondition operations (i.e., `ensure_*`).
49 let cppNamespace = "::llzk::verif";
52def InvariantTarget : OpInterface<"InvariantTargetOpInterface"> {
54 Interface implemented by operations that can be targeted by a loop invariant.
56 Targets are referenced by a label that implementations of this interface must provide.
58 let cppNamespace = "::llzk::verif";
61 [InterfaceMethod<[{Gets the label of the loop, if available.}],
62 "::mlir::FailureOr<::mlir::StringRef>", "getLabel",
64 auto attr = ::mlir::dyn_cast_or_null<::mlir::StringAttr>($_op->getDiscardableAttr("loop_label"));
65 if (!attr) return ::mlir::failure();
66 return attr.getValue();
69 [{Gets the types of the values that the invariant binds inside its body.}],
70 "::mlir::SmallVector<::mlir::Type>", "getArgumentTypes", (ins)>,
74def ContractTarget : OpInterface<"ContractTargetOpInterface", [Symbol]> {
76 Interface implemented by operations that can be targeted by a contract.
78 Targets are referenced by name so implementations of this interface must also implement the `Symbol` interface.
80 let cppNamespace = "::llzk::verif";
82 let methods = [InterfaceMethod<
83 [{Gets the ops that can be targeted by invariant ops.}],
84 "::llvm::SmallVector<::llzk::verif::InvariantTargetOpInterface>",
86 auto op = $_op; // walkCollect expects an l-value but the expansion of $_op is not.
87 return walkCollect<::llzk::verif::InvariantTargetOpInterface>(op);
90 let extraClassDeclaration = [{
91 /// Emulates the static method with the same name found in operations.
92 static ::mlir::StringLiteral getOperationName() {
93 return ::mlir::StringLiteral("contract target interface implementation");
98#endif // LLZK_VERIF_OP_INTERFACES