LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
IntervalAnalysisPass.cpp
Go to the documentation of this file.
1//===-- IntervalAnalysisPass.cpp --------------------------------*- 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//===----------------------------------------------------------------------===//
13//===----------------------------------------------------------------------===//
14
18#include "llzk/Util/Constants.h"
20
21#include <llvm/ADT/STLExtras.h>
22#include <llvm/ADT/SmallVector.h>
23#include <llvm/Support/Debug.h>
24#include <llvm/Support/ErrorHandling.h>
25
26namespace llzk {
27
28#define DEBUG_TYPE "llzk-interval-analysis-pass"
29
30#define GEN_PASS_DECL_INTERVALANALYSISPRINTERPASS
31#define GEN_PASS_DEF_INTERVALANALYSISPRINTERPASS
33
34using namespace component;
35
37 : public impl::IntervalAnalysisPrinterPassBase<IntervalAnalysisPrinterPass> {
38 llvm::raw_ostream &os;
39
40public:
41 explicit IntervalAnalysisPrinterPass(llvm::raw_ostream &ostream)
43
44protected:
45 void runOnOperation() override {
46 markAllAnalysesPreserved();
47
48 // Suppress false positive from `clang-tidy`
49 // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
50 auto modOp = llvm::dyn_cast<mlir::ModuleOp>(getOperation());
51 if (!modOp) {
52 constexpr const char *msg = "IntervalAnalysisPrinterPass error: should be run on ModuleOp!";
53 getOperation()->emitError(msg).report();
54 return;
55 }
56
57 // Initialize to the fallback field value
58 FieldRef selectedField = Field::getField("bn128");
59 if (!fieldName.empty()) {
60 auto fieldLookupRes = Field::tryGetField(fieldName.c_str());
61 if (mlir::failed(fieldLookupRes)) {
62 modOp->emitError()
63 .append(
64 "IntervalAnalysisPrinterPass error: unknown field \"", fieldName, "\" specified"
65 )
66 .report();
67 return;
68 }
69 selectedField = fieldLookupRes.value();
70 LLVM_DEBUG(
71 llvm::dbgs() << "[IntervalAnalysisPrinterPass] using explicit -field override '"
72 << selectedField.get().name() << "'\n";
73 );
74 } else if (auto detectedField = tryDetectSpecifiedField(modOp)) {
75 selectedField = detectedField.value();
76 LLVM_DEBUG(
77 llvm::dbgs() << "[IntervalAnalysisPrinterPass] detected module field '"
78 << selectedField.get().name() << "' from module felt usage\n";
79 );
80 } else {
81 modOp->emitWarning() << "could not detect a unique module field; falling back to '"
82 << selectedField.get().name() << "'";
83 LLVM_DEBUG(
84 llvm::dbgs() << "[IntervalAnalysisPrinterPass] no explicit or detectable module field; "
85 "falling back to '"
86 << selectedField.get().name() << "'\n";
87 );
88 }
89
90 auto &mia = getAnalysis<ModuleIntervalAnalysis>();
91 mia.setField(selectedField);
92 mia.setPropagateInputConstraints(propagateInputConstraints);
93 auto am = getAnalysisManager();
94 mia.ensureAnalysisRun(am);
95
96 for (const auto &[s, si] : mia.getCurrentResults()) {
97 auto &structDef = const_cast<StructDefOp &>(s);
98 auto fullName = getPathFromTopRoot(structDef);
99 ensure(
100 mlir::succeeded(fullName),
101 "could not resolve fully qualified name of struct " + mlir::Twine(structDef.getName())
102 );
103 os << fullName.value() << ' ';
105 }
106 }
107};
108
109std::unique_ptr<mlir::Pass>
110createIntervalAnalysisPrinterPass(llvm::raw_ostream &os = llvm::errs()) {
111 return std::make_unique<IntervalAnalysisPrinterPass>(os);
112}
113
114} // namespace llzk
static llvm::FailureOr< std::reference_wrapper< const Field > > tryGetField(llvm::StringRef fieldName)
Get a Field from a given field name string, or failure if the field is not defined.
Definition Field.cpp:50
static const Field & getField(llvm::StringRef fieldName, EmitErrorFn errFn)
Get a Field from a given field name string.
IntervalAnalysisPrinterPass(llvm::raw_ostream &ostream)
std::reference_wrapper< const Field > FieldRef
Typealias for a stable reference to a known Field.
Definition Field.h:152
void ensure(bool condition, const llvm::Twine &errMsg)
std::unique_ptr< mlir::Pass > createIntervalAnalysisPrinterPass(llvm::raw_ostream &os=llvm::errs())
FailureOr< SymbolRefAttr > getPathFromTopRoot(SymbolOpInterface to, ModuleOp *foundRoot)
std::optional< std::reference_wrapper< const Field > > tryDetectSpecifiedField(mlir::Operation *root)
Try to detect a uniquely used field from the enclosing LLZK module.