LLZK 2.1.1
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
ForbiddenPreconditionInfluence.h
Go to the documentation of this file.
1//===-- ForbiddenPreconditionInfluence.h ------------------------*- C++ -*-===//
2//
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
7//
8//===----------------------------------------------------------------------===//
15//===----------------------------------------------------------------------===//
16
17#pragma once
18
20
21#include <mlir/Dialect/SCF/IR/SCF.h>
22#include <mlir/Interfaces/CallInterfaces.h>
23
24#include <llvm/ADT/DenseMap.h>
25#include <llvm/ADT/DenseSet.h>
26#include <llvm/ADT/SetVector.h>
27#include <llvm/ADT/SmallVector.h>
28
29#include <optional>
30
31namespace llzk::verif {
32
36enum class ForbiddenPreconditionInfluence : uint8_t {
37 None = 0,
38 StructMember = 1 << 0,
40};
41
62
63inline llvm::hash_code hash_value(const ForbiddenPreconditionInfluenceInfo &info) {
64 return llvm::hash_combine(
65 info.influence,
66 llvm::hash_combine_range(info.structMemberLocs.begin(), info.structMemberLocs.end())
67 );
68}
69
72 return static_cast<ForbiddenPreconditionInfluence>(
73 static_cast<uint8_t>(lhs) | static_cast<uint8_t>(rhs)
74 );
75}
76
79 lhs = lhs | rhs;
80 return lhs;
81}
82
84inline bool any(ForbiddenPreconditionInfluence influence) {
85 return static_cast<uint8_t>(influence) != 0;
86}
87
89inline bool
91 return (static_cast<uint8_t>(influence) & static_cast<uint8_t>(flag)) != 0;
92}
93
103
104template <typename T, typename... Args>
105inline ForbiddenPreconditionInfluenceInfo
106mergeInfluenceInfo(const T &first, const T &next, Args... others) {
107 T merged = mergeInfluenceInfo(first, next);
108 return mergeInfluenceInfo(merged, others...);
109}
110
111namespace detail {
112
115
123 mlir::Operation *callable {};
124 llvm::SmallVector<InfluenceInfo> argInfluences;
125 unsigned resultNumber {};
126
127 bool operator==(const CallableSummaryKey &other) const {
128 return callable == other.callable && resultNumber == other.resultNumber &&
130 }
131};
132
133struct CallableSummaryKeyInfo : llvm::DenseMapInfo<CallableSummaryKey> {
135 return {llvm::DenseMapInfo<mlir::Operation *>::getEmptyKey(), {}, 0};
136 }
137
139 return {llvm::DenseMapInfo<mlir::Operation *>::getTombstoneKey(), {}, 0};
140 }
141
142 static unsigned getHashValue(const CallableSummaryKey &key) {
143 return llvm::hash_combine(
144 key.callable, key.resultNumber,
145 llvm::hash_combine_range(key.argInfluences.begin(), key.argInfluences.end())
146 );
147 }
148
149 static bool isEqual(const CallableSummaryKey &lhs, const CallableSummaryKey &rhs) {
150 return lhs == rhs;
151 }
152};
153
161 std::optional<mlir::Location> preconditionLoc = std::nullopt;
163};
164
174 llvm::SmallVector<IncludedContractFailure> failures;
175
176 explicit operator bool() const { return !failures.empty(); }
177};
178
186 mlir::Operation *contract {};
187 llvm::SmallVector<InfluenceInfo> argInfluences;
189
190 bool operator==(const IncludedContractSummaryKey &other) const {
191 return contract == other.contract && argInfluences == other.argInfluences &&
193 }
194};
195
196struct IncludedContractSummaryKeyInfo : llvm::DenseMapInfo<IncludedContractSummaryKey> {
198 return {llvm::DenseMapInfo<mlir::Operation *>::getEmptyKey(), {}};
199 }
200
202 return {llvm::DenseMapInfo<mlir::Operation *>::getTombstoneKey(), {}};
203 }
204
205 static unsigned getHashValue(const IncludedContractSummaryKey &key) {
206 return llvm::hash_combine(
208 llvm::hash_combine_range(key.argInfluences.begin(), key.argInfluences.end())
209 );
210 }
211
212 static bool
214 return lhs == rhs;
215 }
216};
217
226public:
228 explicit ForbiddenInfluenceAnalyzer(mlir::ModuleOp owningModule) : module(owningModule) {}
229
231 InfluenceInfo analyzeContractValue(verif::ContractOp contract, mlir::Value value);
232
237
241 mlir::CallableOpInterface callableOp, llvm::ArrayRef<InfluenceInfo> argInfluences,
242 unsigned resultNumber
243 );
244
248 verif::ContractOp calleeContract, llvm::ArrayRef<InfluenceInfo> argInfluences,
249 InfluenceInfo inheritedControlInfluence = InfluenceInfo::None()
250 );
251
255
256private:
265 class AnalysisFrame {
266 public:
268 AnalysisFrame(
269 ForbiddenInfluenceAnalyzer &parentAnalyzer, mlir::CallableOpInterface callableOp,
270 llvm::ArrayRef<InfluenceInfo> argInfluenceInfos,
271 InfluenceInfo inheritedControlInfluence = InfluenceInfo::None()
272 );
273
275 InfluenceInfo analyzeValue(mlir::Value value);
276
279 InfluenceInfo analyzePreconditionOp(verif::PreconditionOpInterface preCondOp);
280
282 IncludedContractSummary analyzeIncludeOp(verif::IncludeOp includeOp);
283
284 private:
287 InfluenceInfo analyzeControlAncestors(mlir::Operation *op);
288
290 InfluenceInfo analyzeAncestorControl(mlir::Operation *ancestor, mlir::Operation *nestedOp);
291
293 InfluenceInfo analyzeBlockArgument(mlir::BlockArgument blockArg);
294
296 InfluenceInfo analyzeCallResult(mlir::CallOpInterface call, mlir::OpResult callRes);
297
299 InfluenceInfo analyzeIfResult(mlir::scf::IfOp ifOp, mlir::OpResult ifRes);
300
302 InfluenceInfo analyzeForResult(mlir::scf::ForOp forOp, mlir::OpResult forRes);
303
307 analyzeExecuteRegionResult(mlir::scf::ExecuteRegionOp execOp, mlir::OpResult execRes);
308
310 InfluenceInfo analyzeWhileResult(mlir::scf::WhileOp whileOp, mlir::OpResult whileRes);
311
313 llvm::DenseMap<mlir::Value, InfluenceInfo> valueCache;
314 llvm::DenseMap<mlir::Operation *, InfluenceInfo> controlAncestorCache;
315 llvm::DenseSet<mlir::Value> activeValues;
316 InfluenceInfo inheritedControlInfluence = InfluenceInfo::None();
317 };
318
321 static InfluenceInfo
322 classifyContractArgument(verif::ContractOp contract, mlir::BlockArgument arg);
323
324 mlir::ModuleOp module;
325 llvm::DenseMap<CallableSummaryKey, InfluenceInfo, CallableSummaryKeyInfo> callableSummaryCache;
326 llvm::DenseSet<CallableSummaryKey, CallableSummaryKeyInfo> activeSummaries;
327 llvm::DenseMap<
328 IncludedContractSummaryKey, IncludedContractSummary, IncludedContractSummaryKeyInfo>
329 includedContractSummaryCache;
330 llvm::DenseSet<IncludedContractSummaryKey, IncludedContractSummaryKeyInfo>
331 activeIncludedSummaries;
332 llvm::DenseMap<ContractOp, AnalysisFrame> cachedFrames;
333};
334
335} // namespace detail
336
340 mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value
341) {
342 return detail::ForbiddenInfluenceAnalyzer(module).analyzeContractValue(contract, value);
343}
344
352
355 mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value
356) {
357 return analyzeForbiddenPreconditionInfluenceInfo(module, contract, value).influence;
358}
359
363 mlir::ModuleOp module, mlir::CallableOpInterface callableOp,
364 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences, unsigned resultNumber
365) {
367 callableOp, argInfluences, resultNumber
368 );
369}
370
374 mlir::ModuleOp module, mlir::CallableOpInterface callableOp,
375 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences, unsigned resultNumber
376) {
378 module, callableOp, argInfluences, resultNumber
379 )
380 .influence;
381}
382
386 mlir::ModuleOp module, verif::ContractOp calleeContract,
387 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences
388) {
390 calleeContract, argInfluences
391 );
392}
393
398 mlir::ModuleOp module, verif::ContractOp contract, verif::IncludeOp includeOp
399) {
400 return detail::ForbiddenInfluenceAnalyzer(module).analyzeIncludedOp(contract, includeOp);
401}
402
403} // namespace llzk::verif
Interprocedural verifier-local analysis for forbidden precondition influence.
InfluenceInfo analyzeCallableResult(mlir::CallableOpInterface callableOp, llvm::ArrayRef< InfluenceInfo > argInfluences, unsigned resultNumber)
Summarize the forbidden influence of one callable result under the given argument influences.
IncludedContractSummary analyzeIncludedOp(verif::ContractOp contract, verif::IncludeOp includeOp)
Check whether an include op becomes invalid under its caller's operand bindings and enclosing SCF con...
InfluenceInfo analyzePreconditionOp(verif::ContractOp contract, verif::PreconditionOpInterface preCondOp)
Classify the forbidden influence reaching a precondition op, including both the condition operand and...
InfluenceInfo analyzeContractValue(verif::ContractOp contract, mlir::Value value)
Classify the forbidden influence reaching a value inside a contract body.
IncludedContractSummary analyzeIncludedContract(verif::ContractOp calleeContract, llvm::ArrayRef< InfluenceInfo > argInfluences, InfluenceInfo inheritedControlInfluence=InfluenceInfo::None())
Check whether an included contract becomes invalid under caller-provided operand influences,...
ForbiddenInfluenceAnalyzer(mlir::ModuleOp owningModule)
Create a verifier-local analyzer for one LLZK module.
ForbiddenPreconditionInfluence Influence
ForbiddenPreconditionInfluenceInfo InfluenceInfo
ForbiddenPreconditionInfluence analyzeForbiddenPreconditionCallableResult(mlir::ModuleOp module, mlir::CallableOpInterface callableOp, llvm::ArrayRef< ForbiddenPreconditionInfluenceInfo > argInfluences, unsigned resultNumber)
Analyze whether a callable result depends on forbidden precondition sources under a caller-provided a...
ForbiddenPreconditionInfluenceInfo analyzeForbiddenPreconditionCallableResultInfo(mlir::ModuleOp module, mlir::CallableOpInterface callableOp, llvm::ArrayRef< ForbiddenPreconditionInfluenceInfo > argInfluences, unsigned resultNumber)
Analyze whether a callable result depends on forbidden precondition sources under a caller-provided a...
detail::IncludedContractSummary analyzeForbiddenIncludedContractSummary(mlir::ModuleOp module, verif::ContractOp calleeContract, llvm::ArrayRef< ForbiddenPreconditionInfluenceInfo > argInfluences)
Analyze whether including a contract with caller-provided operand influence summaries would trigger a...
ForbiddenPreconditionInfluenceInfo mergeInfluenceInfo(ForbiddenPreconditionInfluenceInfo lhs, const ForbiddenPreconditionInfluenceInfo &rhs)
Merge two forbidden-influence summaries, preserving the first known source location for each forbidde...
detail::IncludedContractSummary analyzeForbiddenIncludedOpSummary(mlir::ModuleOp module, verif::ContractOp contract, verif::IncludeOp includeOp)
Analyze whether a specific include op triggers forbidden preconditions in the callee,...
ForbiddenPreconditionInfluenceInfo analyzeForbiddenPreconditionInfluenceInfo(mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value)
Analyze whether a contract value depends on forbidden precondition sources and recover representative...
ForbiddenPreconditionInfluence operator|(ForbiddenPreconditionInfluence lhs, ForbiddenPreconditionInfluence rhs)
ForbiddenPreconditionInfluence
Sources of information that are not allowed in contract preconditions.
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 ...
ForbiddenPreconditionInfluence analyzeForbiddenPreconditionInfluence(mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value)
Analyze whether a contract value depends on forbidden precondition sources.
llvm::hash_code hash_value(const ForbiddenPreconditionInfluenceInfo &info)
ForbiddenPreconditionInfluence & operator|=(ForbiddenPreconditionInfluence &lhs, ForbiddenPreconditionInfluence rhs)
bool any(ForbiddenPreconditionInfluence influence)
Return true when the influence set contains at least one classification.
Summary of forbidden precondition influence along with representative source locations for each forbi...
static ForbiddenPreconditionInfluenceInfo StructMember()
llvm::SmallSetVector< mlir::Location, 2 > structMemberLocs
bool operator==(const ForbiddenPreconditionInfluenceInfo &other) const
static ForbiddenPreconditionInfluenceInfo None()
static ForbiddenPreconditionInfluenceInfo FunctionReturn()
static unsigned getHashValue(const CallableSummaryKey &key)
static bool isEqual(const CallableSummaryKey &lhs, const CallableSummaryKey &rhs)
Cache key for one interprocedural callable-result summary query.
bool operator==(const CallableSummaryKey &other) const
One included precondition that becomes illegal under a specific caller binding.
static bool isEqual(const IncludedContractSummaryKey &lhs, const IncludedContractSummaryKey &rhs)
static unsigned getHashValue(const IncludedContractSummaryKey &key)
Cache key for one interprocedural included-contract summary query.
bool operator==(const IncludedContractSummaryKey &other) const
Summary of all included-contract precondition failures under a specific caller binding.
llvm::SmallVector< IncludedContractFailure > failures