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