1+ /*
2+ * Copyright (c) 2025, Trail of Bits, Inc.
3+ *
4+ * This source code is licensed in accordance with the terms specified in
5+ * the LICENSE file found in the root directory of this source tree.
6+ */
7+
8+ #ifndef CONTRACT_DIALECT
9+ #define CONTRACT_DIALECT
10+
11+ include "mlir/IR/OpBase.td"
12+ include "mlir/IR/AttrTypeBase.td"
13+ include "mlir/IR/EnumAttr.td"
14+
15+ // Dialect
16+ def Contract_Dialect : Dialect {
17+ let name = "contracts";
18+ let cppNamespace = "contracts";
19+ let summary = "Static contracts as attributes";
20+ let description = [{ Declarative pre/post conditions attached to operations. }];
21+ }
22+
23+ // cmp predicate
24+ def CmpKind : I32EnumAttr<"CmpKind", "comparison predicate", [
25+ I32EnumAttrCase<"eq", 0>,
26+ I32EnumAttrCase<"ne", 1>,
27+ I32EnumAttrCase<"slt", 2>,
28+ I32EnumAttrCase<"sle", 3>,
29+ I32EnumAttrCase<"sgt", 4>,
30+ I32EnumAttrCase<"sge", 5>,
31+ I32EnumAttrCase<"ult", 6>,
32+ I32EnumAttrCase<"ule", 7>,
33+ I32EnumAttrCase<"ugt", 8>,
34+ I32EnumAttrCase<"uge", 9>
35+ ]> { let cppNamespace = "::contracts"; }
36+
37+ // Positional operand reference: $0, $1, ...
38+ def VarRefAttr : AttrDef<Contract_Dialect, "varref"> {
39+ let summary = "Positional operand reference";
40+ let parameters = (ins "uint64_t":$index);
41+ let mnemonic = "varref";
42+ let assemblyFormat = "`<` $index `>`";
43+ }
44+
45+ // Integer literal
46+ def ConstIntAttr : AttrDef<Contract_Dialect, "iconst"> {
47+ let summary = "Integer constant";
48+ let parameters = (ins "mlir::IntegerAttr":$value);
49+ let mnemonic = "iconst";
50+ let assemblyFormat = "`<` $value `>`";
51+ }
52+
53+ // cmp clause: (lhs pred rhs) where rhs is var or const
54+ def CmpClauseAttr : AttrDef<Contract_Dialect, "cmp"> {
55+ let summary = "Integer comparison clause";
56+ let parameters = (ins
57+ "::contracts::CmpKind":$pred,
58+ "::contracts::VarRefAttr":$lhs,
59+ OptionalParameter<"::contracts::VarRefAttr">:$rhsVar,
60+ OptionalParameter<"::contracts::ConstIntAttr">:$rhsConst
61+ );
62+ let mnemonic = "cmp";
63+ let genVerifyDecl = 1;
64+ let assemblyFormat = "`<` $pred `,` $lhs (`,` $rhsVar^)? (`,` $rhsConst^)? `>`";
65+ }
66+
67+ // Boolean aggregators
68+ def AllOfAttr : AttrDef<Contract_Dialect, "all_of"> {
69+ let summary = "Conjunction of clauses";
70+ let parameters = (ins ArrayRefParameter<"mlir::Attribute">:$clauses);
71+ let mnemonic = "all_of";
72+ let assemblyFormat = "`<` `[` $clauses `]` `>`";
73+ }
74+ def AnyOfAttr : AttrDef<Contract_Dialect, "any_of"> {
75+ let summary = "Disjunction of clauses";
76+ let parameters = (ins ArrayRefParameter<"mlir::Attribute">:$clauses);
77+ let mnemonic = "any_of";
78+ let assemblyFormat = "`<` `[` $clauses `]` `>`";
79+ }
80+
81+ // Top-level contract you attach to an op
82+ def StaticContractAttr : AttrDef<Contract_Dialect, "static"> {
83+ let summary = "Static contract container";
84+ let parameters = (ins
85+ "mlir::StringAttr":$message,
86+ "mlir::Attribute":$expr // CmpClauseAttr | AllOfAttr | AnyOfAttr
87+ );
88+ let mnemonic = "static";
89+ let genVerifyDecl = 1;
90+ let assemblyFormat = "`<` `message` `=` $message `,` $expr `>`";
91+ }
92+
93+ #endif // CONTRACT_DIALECT
0 commit comments