From 89c037b3490b7092a5a452fa80fe7a4952f51afe Mon Sep 17 00:00:00 2001
From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com>
Date: Fri, 21 Mar 2025 09:52:57 +1300
Subject: [PATCH] opt_expr: Avoid visitor lambda

---
 passes/opt/opt_expr.cc | 89 +++++++++++++++++++++---------------------
 1 file changed, 44 insertions(+), 45 deletions(-)

diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index d9da82d4e..5b63214ad 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -490,50 +490,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 		handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID::R, assign_map, invert_map);	
 	}
 
-	std::vector<Cell*> module_cells = module->cells();
-	auto visitor = [&](auto&& do_action) {
-		if (sort_fails >= effort) {
-			for (auto cell : module_cells)
-				if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type))
-				do_action(cell);
-		} else {
-			TopoSort<RTLIL::Cell*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
-			dict<RTLIL::SigBit, Cell*> outbit_to_cell;
-
-			for (auto cell : module->cells())
-			if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
-				for (auto &conn : cell->connections())
-				if (yosys_celltypes.cell_output(cell->type, conn.first))
-				for (auto bit : assign_map(conn.second))
-					outbit_to_cell[bit] = cell;
-				cells.node(cell);
-			}
-
-			for (auto cell : module->cells())
-			if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
-				const int r_index = cells.node(cell);
-				for (auto &conn : cell->connections())
-				if (yosys_celltypes.cell_input(cell->type, conn.first))
-				for (auto bit : assign_map(conn.second))
-				if (outbit_to_cell.count(bit))
-					cells.edge(cells.node(outbit_to_cell.at(bit)), r_index);
-			}
-
-			if (!cells.sort()) {
-				// There might be a combinational loop, or there might be constants on the output of cells. 'check' may find out more.
-				// ...unless this is a coarse-grained cell loop, but not a bit loop, in which case it won't, and all is good.
-				log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", log_id(module));
-				sort_fails++;
-				if (sort_fails >= effort)
-					log("Effort of %d exceeded, no longer attempting toposort on module %s.\n",
-						effort, log_id(module));
-			}
-			for (auto cell : cells.sorted) {
-				do_action(cell);
-			}
-		}
-	};
-	visitor([&](auto& cell)
+	auto do_action = [&](auto& cell)
 	{
 #define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0)
 #define ACTION_DO_Y(_v_) ACTION_DO(ID::Y, RTLIL::SigSpec(RTLIL::State::S ## _v_))
@@ -2213,7 +2170,49 @@ skip_alu_split:
 #undef ACTION_DO_Y
 #undef FOLD_1ARG_CELL
 #undef FOLD_2ARG_CELL
-	});
+	};
+
+	std::vector<Cell*> module_cells = module->cells();
+	if (sort_fails >= effort) {
+		for (auto cell : module_cells)
+			if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type))
+			do_action(cell);
+	} else {
+		TopoSort<RTLIL::Cell*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
+		dict<RTLIL::SigBit, Cell*> outbit_to_cell;
+
+		for (auto cell : module->cells())
+		if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
+			for (auto &conn : cell->connections())
+			if (yosys_celltypes.cell_output(cell->type, conn.first))
+			for (auto bit : assign_map(conn.second))
+				outbit_to_cell[bit] = cell;
+			cells.node(cell);
+		}
+
+		for (auto cell : module->cells())
+		if (design->selected(module, cell) && yosys_celltypes.cell_evaluable(cell->type)) {
+			const int r_index = cells.node(cell);
+			for (auto &conn : cell->connections())
+			if (yosys_celltypes.cell_input(cell->type, conn.first))
+			for (auto bit : assign_map(conn.second))
+			if (outbit_to_cell.count(bit))
+				cells.edge(cells.node(outbit_to_cell.at(bit)), r_index);
+		}
+
+		if (!cells.sort()) {
+			// There might be a combinational loop, or there might be constants on the output of cells. 'check' may find out more.
+			// ...unless this is a coarse-grained cell loop, but not a bit loop, in which case it won't, and all is good.
+			log("Couldn't topologically sort cells, optimizing module %s may take a longer time.\n", log_id(module));
+			sort_fails++;
+			if (sort_fails >= effort)
+				log("Effort of %d exceeded, no longer attempting toposort on module %s.\n",
+					effort, log_id(module));
+		}
+		for (auto cell : cells.sorted) {
+			do_action(cell);
+		}
+	}
 }
 
 void replace_const_connections(RTLIL::Module *module) {