]> Repositorios git - scryer-prolog.git/commitdiff
backtrack on emission of unsafe register instructions on internal branches
authorMark <[email protected]>
Fri, 23 Jun 2023 00:28:10 +0000 (18:28 -0600)
committerMark <[email protected]>
Fri, 23 Jun 2023 20:11:31 +0000 (14:11 -0600)
src/codegen.rs
src/debray_allocator.rs
src/machine/disjuncts.rs

index 794ec65b2d98adcd6cbc188841f50415158212dd..000c0e65165a01a7767eb01e751ec12b1b85451e 100644 (file)
@@ -103,25 +103,15 @@ impl BranchCodeStack {
 
             for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() {
                 if inner_idx + 1 == inner_len {
-                    jump_span -= code.len() + 1; // = jump_span.saturating_sub(code.len() + 1);
+                    jump_span -= code.len() + 1;
                 } else {
                     jump_span -= code.len() + 1;
                     code.push_back(instr!("jmp_by_call", jump_span as usize));
 
-                    // saturate at 0 if underflow happens, which only
-                    // happens when jump_span is no longer needed
-                    // anyway. still, we don't want to panic at
-                    // underflow.
                     jump_span -= 1;
                 }
             }
         }
-
-        // eliminate terminating jump instruction in last arm of last
-        // branch.
-        // self.stack.last_mut()
-        //     .and_then(|branch| branch.last_mut())
-        //     .map(|code| code.pop_back());
     }
 
     fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque {
@@ -1242,14 +1232,6 @@ impl<'b> CodeGenerator<'b> {
             code.extend(code_segment.into_iter());
         }
 
-        /*
-        for line in &code {
-            println!("{:?}", line);
-        }
-
-        println!("");
-        */
-
         Ok(code)
     }
 }
index 2f8d442ef464bb1e4ed2ad909689d556085acfed..2cd853c7dfc9d9f270126924d6f6ee0a94261e58 100644 (file)
@@ -75,7 +75,17 @@ impl DebrayAllocator {
         self.branch_stack.push(BranchOccurrences::new(num_branches));
     }
 
+    pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
+        let num_branches = self.branch_stack.len();
+        let current_branch = self.branch_stack.last()
+            .map(|occurrences| occurrences.current_branch)
+            .unwrap_or(0);
+
+        BranchDesignator((num_branches, current_branch))
+    }
+
     pub(crate) fn add_branch(&mut self) {
+        let branch_designator = self.current_branch_designator();
         let branch_occurrences = self.branch_stack.last_mut().unwrap();
 
         for var_num in branch_occurrences.subsumed_hits.drain(..) {
@@ -83,11 +93,11 @@ impl DebrayAllocator {
                 VarAlloc::Perm(_, ref mut allocation) => {
                     match allocation {
                         PermVarAllocation::Done { shallow_safety, deep_safety, .. } => {
-                            if !shallow_safety.unneeded() {
+                            if !shallow_safety.is_unneeded(branch_designator) {
                                 branch_occurrences.shallow_safety.insert(var_num);
                             }
 
-                            if !deep_safety.unneeded() {
+                            if !deep_safety.is_unneeded(branch_designator) {
                                 branch_occurrences.deep_safety.insert(var_num);
                             }
                         }
@@ -128,6 +138,8 @@ impl DebrayAllocator {
                       (deep_safety, shallow_safety)
                   });
 
+        let branch_designator = self.current_branch_designator();
+
         let (deep_safety, shallow_safety) = match self.branch_stack.last_mut() {
             Some(latest_branch) => {
                 latest_branch.deep_safety.union_with(&deep_safety);
@@ -143,10 +155,12 @@ impl DebrayAllocator {
                 VarAlloc::Perm(_, ref mut allocation) => {
                     let shallow_safety = VarSafetyStatus::needed_if(
                         shallow_safety.contains(var_num),
+                        branch_designator,
                     );
 
                     let deep_safety = VarSafetyStatus::needed_if(
                         deep_safety.contains(var_num),
+                        branch_designator,
                     );
 
                     *allocation = PermVarAllocation::Done { shallow_safety, deep_safety };
@@ -415,10 +429,12 @@ impl DebrayAllocator {
     pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) {
         match &self.var_data.records[var_num].allocation {
             &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => {
+                let branch_designator = self.current_branch_designator();
+
                 match &mut self.var_data.records[perm_var_num].allocation {
                     VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
-                        *deep_safety = VarSafetyStatus::Unneeded;
-                        *shallow_safety = VarSafetyStatus::Unneeded;
+                        *deep_safety = VarSafetyStatus::unneeded(branch_designator);
+                        *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
                     }
                     _ => unreachable!()
                 }
@@ -429,14 +445,16 @@ impl DebrayAllocator {
     }
 
     fn mark_safe_var(&mut self, var_num: usize, lvl: Level, term_loc: GenContext) {
+        let branch_designator = self.current_branch_designator();
+
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
                 // GetVariable in head chunk is considered safe.
                 if lvl == Level::Deep {
-                    *deep_safety = VarSafetyStatus::Unneeded;
-                    *shallow_safety = VarSafetyStatus::Unneeded;
+                    *deep_safety = VarSafetyStatus::unneeded(branch_designator);
+                    *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
                 } else if term_loc == GenContext::Head {
-                    *shallow_safety = VarSafetyStatus::Unneeded;
+                    *shallow_safety = VarSafetyStatus::GloballyUnneeded;
                 } else {
                     if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() {
                         match &mut self.var_data.records[temp_var_num].allocation {
@@ -449,7 +467,7 @@ impl DebrayAllocator {
                 }
             }
             VarAlloc::Temp { ref mut safety, .. } => {
-                *safety = VarSafetyStatus::Unneeded;
+                *safety = VarSafetyStatus::GloballyUnneeded;
             }
             _ => {
                 unreachable!()
@@ -463,20 +481,22 @@ impl DebrayAllocator {
         r: RegType,
         arg_c: usize,
     ) -> Instruction {
+        let branch_designator = self.current_branch_designator();
+
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => {
-                if !self.in_tail_position || shallow_safety.unneeded() {
+                if !self.in_tail_position || shallow_safety.is_unneeded(branch_designator) {
                     Target::argument_to_value(r, arg_c)
                 } else {
-                    *shallow_safety = VarSafetyStatus::Unneeded;
+                    *shallow_safety = VarSafetyStatus::unneeded(branch_designator);
                     Target::unsafe_argument_to_value(r, arg_c)
                 }
             }
             VarAlloc::Temp { ref mut safety, .. } => {
-                if safety.unneeded() {
+                if safety.is_unneeded(branch_designator) {
                     Target::argument_to_value(r, arg_c)
                 } else {
-                    *safety = VarSafetyStatus::Unneeded;
+                    *safety = VarSafetyStatus::GloballyUnneeded;
                     Target::unsafe_argument_to_value(r, arg_c)
                 }
             }
@@ -491,20 +511,22 @@ impl DebrayAllocator {
         var_num: usize,
         r: RegType,
     ) -> Instruction {
+        let branch_designator = self.current_branch_designator();
+
         match &mut self.var_data.records[var_num].allocation {
             VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => {
-                if deep_safety.unneeded() {
+                if deep_safety.is_unneeded(branch_designator) {
                     Target::subterm_to_value(r)
                 } else {
-                    *deep_safety = VarSafetyStatus::Unneeded;
+                    *deep_safety = VarSafetyStatus::unneeded(branch_designator);
                     Target::unsafe_subterm_to_value(r)
                 }
             }
             VarAlloc::Temp { ref mut safety, .. } => {
-                if safety.unneeded() {
+                if safety.is_unneeded(branch_designator) {
                     Target::subterm_to_value(r)
                 } else {
-                    *safety = VarSafetyStatus::Unneeded;
+                    *safety = VarSafetyStatus::unneeded(branch_designator);
                     Target::unsafe_subterm_to_value(r)
                 }
             }
index 1b65ef9ee5efab1a4111c4668f286b7503bac83f..a701dba32b929258587f4a7051d5b05f435f5250 100644 (file)
@@ -839,12 +839,3 @@ impl BranchMap {
         var_data
     }
 }
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn disjunct_compilation() {
-        let mut wam = MachineState::new();
-        let mut op_dir = default_op_dir();
-    }
-}