LLZK 3.0.0
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 = 1U << 0U,
39 FunctionReturn = 1U << 1U,
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, const 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> {
134 static unsigned getHashValue(const CallableSummaryKey &key) {
135 return llvm::hash_combine(
136 key.callable, key.resultNumber,
137 llvm::hash_combine_range(key.argInfluences.begin(), key.argInfluences.end())
138 );
139 }
140
141 static bool isEqual(const CallableSummaryKey &lhs, const CallableSummaryKey &rhs) {
142 return lhs == rhs;
143 }
144};
145
153 std::optional<mlir::Location> preconditionLoc = std::nullopt;
155};
156
166 llvm::SmallVector<IncludedContractFailure> failures;
167
168 explicit operator bool() const { return !failures.empty(); }
169};
170
178 mlir::Operation *contract {};
179 llvm::SmallVector<InfluenceInfo> argInfluences;
181
182 bool operator==(const IncludedContractSummaryKey &other) const {
183 return contract == other.contract && argInfluences == other.argInfluences &&
185 }
186};
187
188struct IncludedContractSummaryKeyInfo : llvm::DenseMapInfo<IncludedContractSummaryKey> {
189 static unsigned getHashValue(const IncludedContractSummaryKey &key) {
190 return llvm::hash_combine(
192 llvm::hash_combine_range(key.argInfluences.begin(), key.argInfluences.end())
193 );
194 }
195
196 static bool
198 return lhs == rhs;
199 }
200};
201
210public:
212 explicit ForbiddenInfluenceAnalyzer(mlir::ModuleOp owningModule) : module(owningModule) {}
213
215 InfluenceInfo analyzeContractValue(verif::ContractOp contract, mlir::Value value);
216
221
225 mlir::CallableOpInterface callableOp, llvm::ArrayRef<InfluenceInfo> argInfluences,
226 unsigned resultNumber
227 );
228
232 verif::ContractOp calleeContract, llvm::ArrayRef<InfluenceInfo> argInfluences,
233 const InfluenceInfo &inheritedControlInfluence = InfluenceInfo::None()
234 );
235
239
240private:
249 class AnalysisFrame {
250 public:
252 AnalysisFrame(
253 ForbiddenInfluenceAnalyzer &parentAnalyzer, mlir::CallableOpInterface callableOp,
254 llvm::ArrayRef<InfluenceInfo> argInfluenceInfos,
255 InfluenceInfo inheritedControlInfluence = InfluenceInfo::None()
256 );
257
259 InfluenceInfo analyzeValue(mlir::Value value);
260
263 InfluenceInfo analyzePreconditionOp(verif::PreconditionOpInterface preCondOp);
264
266 IncludedContractSummary analyzeIncludeOp(verif::IncludeOp includeOp);
267
268 private:
271 InfluenceInfo analyzeControlAncestors(mlir::Operation *op);
272
274 InfluenceInfo analyzeAncestorControl(mlir::Operation *ancestor, mlir::Operation *nestedOp);
275
277 InfluenceInfo analyzeBlockArgument(mlir::BlockArgument blockArg);
278
280 InfluenceInfo analyzeCallResult(mlir::CallOpInterface call, mlir::OpResult callRes);
281
283 InfluenceInfo analyzeIfResult(mlir::scf::IfOp ifOp, mlir::OpResult ifRes);
284
286 InfluenceInfo analyzeForResult(mlir::scf::ForOp forOp, mlir::OpResult forRes);
287
291 analyzeExecuteRegionResult(mlir::scf::ExecuteRegionOp execOp, mlir::OpResult execRes);
292
294 InfluenceInfo analyzeWhileResult(mlir::scf::WhileOp whileOp, mlir::OpResult whileRes);
295
297 llvm::DenseMap<mlir::Value, InfluenceInfo> valueCache;
298 llvm::DenseMap<mlir::Operation *, InfluenceInfo> controlAncestorCache;
299 llvm::DenseSet<mlir::Value> activeValues;
300 InfluenceInfo inheritedControlInfluence = InfluenceInfo::None();
301 };
302
305 static InfluenceInfo
306 classifyContractArgument(verif::ContractOp contract, mlir::BlockArgument arg);
307
308 mlir::ModuleOp module;
309 llvm::DenseMap<CallableSummaryKey, InfluenceInfo, CallableSummaryKeyInfo> callableSummaryCache;
310 llvm::DenseSet<CallableSummaryKey, CallableSummaryKeyInfo> activeSummaries;
311 llvm::DenseMap<
312 IncludedContractSummaryKey, IncludedContractSummary, IncludedContractSummaryKeyInfo>
313 includedContractSummaryCache;
314 llvm::DenseSet<IncludedContractSummaryKey, IncludedContractSummaryKeyInfo>
315 activeIncludedSummaries;
316 llvm::DenseMap<ContractOp, AnalysisFrame> cachedFrames;
317};
318
319} // namespace detail
320
324 mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value
325) {
326 return detail::ForbiddenInfluenceAnalyzer(module).analyzeContractValue(contract, value);
327}
328
336
339 mlir::ModuleOp module, verif::ContractOp contract, mlir::Value value
340) {
341 return analyzeForbiddenPreconditionInfluenceInfo(module, contract, value).influence;
342}
343
347 mlir::ModuleOp module, mlir::CallableOpInterface callableOp,
348 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences, unsigned resultNumber
349) {
351 callableOp, argInfluences, resultNumber
352 );
353}
354
358 mlir::ModuleOp module, mlir::CallableOpInterface callableOp,
359 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences, unsigned resultNumber
360) {
362 module, callableOp, argInfluences, resultNumber
363 )
364 .influence;
365}
366
370 mlir::ModuleOp module, verif::ContractOp calleeContract,
371 llvm::ArrayRef<ForbiddenPreconditionInfluenceInfo> argInfluences
372) {
374 calleeContract, argInfluences
375 );
376}
377
382 mlir::ModuleOp module, verif::ContractOp contract, verif::IncludeOp includeOp
383) {
384 return detail::ForbiddenInfluenceAnalyzer(module).analyzeIncludedOp(contract, includeOp);
385}
386
387} // 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 analyzeIncludedContract(verif::ContractOp calleeContract, llvm::ArrayRef< InfluenceInfo > argInfluences, const InfluenceInfo &inheritedControlInfluence=InfluenceInfo::None())
Check whether an included contract becomes invalid under caller-provided operand 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.
ForbiddenInfluenceAnalyzer(mlir::ModuleOp owningModule)
Create a verifier-local analyzer for one LLZK module.
Common interface for constant parameter-like symbol operations that can be defined within a TemplateO...
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