From d2c929546fbda631e2c180c8bbff26a159ec4396 Mon Sep 17 00:00:00 2001
From: Russel Arbore <russel.jma@gmail.com>
Date: Mon, 23 Dec 2024 16:41:08 -0800
Subject: [PATCH] Don't visit invalid dynamic constants

---
 hercules_cg/src/cpu.rs     | 10 +++++++---
 hercules_cg/src/rt.rs      |  6 +++++-
 hercules_ir/src/ir.rs      | 10 +++++++++-
 hercules_opt/src/inline.rs |  5 ++++-
 hercules_opt/src/pass.rs   |  4 +++-
 juno_frontend/src/lib.rs   |  4 ++--
 6 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/hercules_cg/src/cpu.rs b/hercules_cg/src/cpu.rs
index eb76a47d..080c195a 100644
--- a/hercules_cg/src/cpu.rs
+++ b/hercules_cg/src/cpu.rs
@@ -114,8 +114,8 @@ impl<'a> CPUContext<'a> {
             .map(|idx| (NodeID::new(idx), LLVMBlock::default()))
             .collect();
 
-        // Emit calculation of dynamic constants into the start block. Just
-        // calculate every dynamic constant, and let LLVM clean them up.
+        // Emit calculation of dynamic constants into the start block. Calculate
+        // every valid dynamic constant, and let LLVM clean them up.
         self.codegen_dynamic_constants(
             blocks.get_mut(&NodeID::new(0)).unwrap(),
             self.function.num_dynamic_constants,
@@ -212,7 +212,11 @@ impl<'a> CPUContext<'a> {
                 let term = &mut blocks.get_mut(&id).unwrap().term;
                 write!(term, "  ret {}\n", self.get_value(data, true))?
             }
-            _ => panic!("PANIC: Can't lower {:?}.", self.function.nodes[id.idx()]),
+            _ => panic!(
+                "PANIC: Can't lower {:?} in {}.",
+                self.function.nodes[id.idx()],
+                self.function.name
+            ),
         }
         Ok(())
     }
diff --git a/hercules_cg/src/rt.rs b/hercules_cg/src/rt.rs
index ddbc8f53..47b739dc 100644
--- a/hercules_cg/src/rt.rs
+++ b/hercules_cg/src/rt.rs
@@ -455,7 +455,11 @@ impl<'a> RTContext<'a> {
                     write!(block, "                }}\n")?;
                 }
             }
-            _ => panic!("PANIC: Can't lower {:?}.", func.nodes[id.idx()]),
+            _ => panic!(
+                "PANIC: Can't lower {:?} in {}.",
+                func.nodes[id.idx()],
+                func.name
+            ),
         }
         Ok(())
     }
diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs
index 4127d6c3..f6356dfd 100644
--- a/hercules_ir/src/ir.rs
+++ b/hercules_ir/src/ir.rs
@@ -596,7 +596,10 @@ pub fn constants_bottom_up(constants: &Vec<Constant>) -> impl Iterator<Item = Co
 /*
  * Create an iterator that traverses all the dynamic constants in the module
  * bottom up. This uses a coroutine to make iteratively traversing the dynamic
- * constant DAGs easier.
+ * constant DAGs easier. This bottom-up visitor will ignore dynamic constants
+ * that reference non-sensical IDs. These are artifacts left over by the process
+ * of subsituting dynamic constants during some transformation passes, and
+ * shouldn't be used by any nodes.
  */
 pub fn dynamic_constants_bottom_up(
     dynamic_constants: &Vec<DynamicConstant>,
@@ -621,6 +624,11 @@ pub fn dynamic_constants_bottom_up(
                     // We have to yield the children of this node before
                     // this node itself. We keep track of which nodes have
                     // yielded using visited.
+                    if left.idx() >= visited.len() || right.idx() >= visited.len() {
+                        // This is an invalid dynamic constant and should be
+                        // skipped.
+                        continue;
+                    }
                     let can_yield = visited[left.idx()] && visited[right.idx()];
                     if can_yield {
                         visited.set(id.idx(), true);
diff --git a/hercules_opt/src/inline.rs b/hercules_opt/src/inline.rs
index 1c485ecc..9ab15874 100644
--- a/hercules_opt/src/inline.rs
+++ b/hercules_opt/src/inline.rs
@@ -45,6 +45,9 @@ pub fn inline(editors: &mut [FunctionEditor], callgraph: &CallGraph) {
     // Step 4: run inlining on each function individually. Iterate the functions
     // in topological order.
     for to_inline_id in topo {
+        if editors[to_inline_id.idx()].func().entry {
+            continue;
+        }
         // Since Rust cannot analyze the accesses into an array of mutable
         // references, we need to do some weirdness here to simultaneously get:
         // 1. A mutable reference to the function we're modifying.
@@ -181,7 +184,7 @@ fn inline_func(
                     // as the new references we just made in the first step. We
                     // actually want to institute all the updates
                     // *simultaneously*, hence the two step maneuver.
-                    let first_dc = edit.num_dynamic_constants() + 1;
+                    let first_dc = edit.num_dynamic_constants() + 100;
                     for (dc_a, dc_n) in zip(dcs_a, first_dc..) {
                         substitute_dynamic_constants_in_node(
                             *dc_a,
diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs
index 58251c42..ce53916b 100644
--- a/hercules_opt/src/pass.rs
+++ b/hercules_opt/src/pass.rs
@@ -867,7 +867,9 @@ impl PassManager {
                     let mut rust_rt = String::new();
                     let mut llvm_ir = String::new();
                     for idx in 0..self.module.functions.len() {
-                        if self.module.functions[idx].entry {
+                        if self.module.functions[idx].entry
+                            || callgraph.num_callees(FunctionID::new(idx)) != 0
+                        {
                             rt_codegen(
                                 FunctionID::new(idx),
                                 &self.module,
diff --git a/juno_frontend/src/lib.rs b/juno_frontend/src/lib.rs
index 4ff5d9fc..b18b2979 100644
--- a/juno_frontend/src/lib.rs
+++ b/juno_frontend/src/lib.rs
@@ -184,8 +184,8 @@ pub fn compile_ir(
     if x_dot {
         pm.add_pass(hercules_opt::pass::Pass::Xdot(true));
     }
-    add_pass!(pm, verify, Forkify);
-    add_pass!(pm, verify, ForkGuardElim);
+    //add_pass!(pm, verify, Forkify);
+    //add_pass!(pm, verify, ForkGuardElim);
     add_verified_pass!(pm, verify, DCE);
     add_pass!(pm, verify, Outline);
     add_pass!(pm, verify, InterproceduralSROA);
-- 
GitLab