LLZK 0.1.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
LLZKValidationPasses.cpp
Go to the documentation of this file.
1//===-- LLZKValidationPasses.cpp - LLZK validation passes -------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
14//===----------------------------------------------------------------------===//
15
18
19#include <mlir/IR/BuiltinOps.h>
21// Include the generated base pass class definitions.
22namespace llzk {
23#define GEN_PASS_DEF_MEMBERWRITEVALIDATORPASS
25} // namespace llzk
27using namespace mlir;
28using namespace llzk;
29using namespace llzk::component;
30using namespace llzk::function;
31
32namespace {
33class MemberWriteValidatorPass
34 : public llzk::impl::MemberWriteValidatorPassBase<MemberWriteValidatorPass> {
35 void runOnOperation() override {
36 StructDefOp structDef = getOperation();
37 FuncDefOp computeFunc = structDef.getComputeFuncOp();
38
39 // Initialize map with all member names mapped to nullptr (i.e., no write found).
40 llvm::StringMap<MemberWriteOp> memberNameToWriteOp;
41 for (MemberDefOp x : structDef.getMemberDefs()) {
42 memberNameToWriteOp[x.getSymName()] = nullptr;
43 }
44 // Search the function body for writes, store them in the map and emit warning if multiple
45 // writes to the same member are found.
46 for (Block &block : computeFunc.getBody()) {
47 for (Operation &op : block) {
48 if (MemberWriteOp write = dyn_cast<MemberWriteOp>(op)) {
49 // `MemberWriteOp::verifySymbolUses()` ensures MemberWriteOp only target the containing
50 // "self" struct. That means the target of the MemberWriteOp must be in
51 // `memberNameToWriteOp` so using 'at()' will not abort.
52 assert(structDef.getType() == write.getComponent().getType());
53 StringRef writeToMemberName = write.getMemberName();
54 if (MemberWriteOp earlierWrite = memberNameToWriteOp.at(writeToMemberName)) {
55 auto diag = write.emitWarning().append(
56 "found multiple writes to '", MemberDefOp::getOperationName(), "' named \"@",
57 writeToMemberName, '"'
58 );
59 diag.attachNote(earlierWrite.getLoc()).append("earlier write here");
60 diag.report();
61 }
62 memberNameToWriteOp[writeToMemberName] = write;
63 }
64 }
65 }
66 // Finally, report a warning if any member was not written at all.
67 for (auto &[a, b] : memberNameToWriteOp) {
68 if (!b) {
69 computeFunc.emitWarning()
70 .append(
72 "\" missing write to '", MemberDefOp::getOperationName(), "' named \"@", a, '"'
73 )
74 .report();
75 }
76 }
77
78 markAllAnalysesPreserved();
79 }
80};
81} // namespace
82
83std::unique_ptr<mlir::Pass> llzk::createMemberWriteValidatorPass() {
84 return std::make_unique<MemberWriteValidatorPass>();
85};
static constexpr ::llvm::StringLiteral getOperationName()
Definition Ops.h.inc:353
StructType getType(::std::optional<::mlir::ArrayAttr > constParams={})
Gets the StructType representing this struct.
::std::vector< MemberDefOp > getMemberDefs()
Get all MemberDefOp in this structure.
Definition Ops.cpp:416
::llzk::function::FuncDefOp getComputeFuncOp()
Gets the FuncDefOp that defines the compute function in this structure, if present,...
Definition Ops.cpp:426
static constexpr ::llvm::StringLiteral getOperationName()
Definition Ops.h.inc:583
::mlir::Region & getBody()
Definition Ops.h.inc:607
constexpr char FUNC_NAME_COMPUTE[]
Symbol name for the witness generation (and resp.
Definition Constants.h:16
std::unique_ptr< mlir::Pass > createMemberWriteValidatorPass()