LLZK 0.1.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
InlineIncludesPass.cpp
Go to the documentation of this file.
1//===-- LLZKInlineIncludesPass.cpp - -llzk-inline-includes pass -*- 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
19#include <mlir/IR/BuiltinOps.h>
21#include <llvm/Support/LogicalResult.h>
23// Include the generated base pass class definitions.
24namespace llzk::include {
25#define GEN_PASS_DEF_INLINEINCLUDESPASS
27} // namespace llzk::include
29using namespace mlir;
30using namespace llzk::include;
31
32namespace {
33using IncludeStack = std::vector<std::pair<StringRef, Location>>;
34
35inline bool contains(IncludeStack &stack, StringRef &&loc) {
36 auto path_match = [loc](std::pair<StringRef, Location> &p) { return p.first == loc; };
37 return std::find_if(stack.begin(), stack.end(), path_match) != stack.end();
38}
39
40class InlineIncludesPass : public llzk::include::impl::InlineIncludesPassBase<InlineIncludesPass> {
41 void runOnOperation() override {
42 std::vector<std::pair<ModuleOp, IncludeStack>> currLevel = {
43 std::make_pair(getOperation(), IncludeStack())
44 };
45 do {
46 std::vector<std::pair<ModuleOp, IncludeStack>> nextLevel = {};
47 for (std::pair<ModuleOp, IncludeStack> &curr : currLevel) {
48 curr.first.walk([includeStack = std::move(curr.second),
49 &nextLevel](IncludeOp incOp) mutable {
50 // Check for cyclic includes
51 if (contains(includeStack, incOp.getPath())) {
52 auto err = incOp.emitError().append("found cyclic include");
53 for (auto it = includeStack.rbegin(); it != includeStack.rend(); ++it) {
54 err.attachNote(it->second).append("included from here");
55 }
56 err.report();
57 } else {
58 includeStack.push_back(std::make_pair(incOp.getPath(), incOp.getLoc()));
59 FailureOr<ModuleOp> result = incOp.inlineAndErase();
60 if (succeeded(result)) {
61 ModuleOp newMod = std::move(result.value());
62 assert(succeeded(newMod.verify()) && "newMod must pass verification");
63 nextLevel.push_back(make_pair(newMod, includeStack));
64 }
65 }
66 // Advance in either case so as many errors as possible are found in a single run.
67 return WalkResult::advance();
68 });
69 }
70 currLevel = nextLevel;
71 } while (!currLevel.empty());
72
73 if (failed(getOperation().verify())) {
74 signalPassFailure();
75 return;
76 }
77 markAllAnalysesPreserved();
78 }
79};
80
81} // namespace
82
83std::unique_ptr<mlir::Pass> llzk::include::createInlineIncludesPass() {
84 return std::make_unique<InlineIncludesPass>();
85};
std::unique_ptr< mlir::Pass > createInlineIncludesPass()