From b8ccebbf24d9f70da6a0e2cfae11fb6164f01aaa Mon Sep 17 00:00:00 2001 From: bakaq Date: Sat, 1 Feb 2025 15:53:15 -0300 Subject: [PATCH 1/2] Fix bug in finding arity for verify attributes --- src/machine/dispatch.rs | 36 +++++++++++++++++-- .../scryer/cli/issues/compilation_bug.in/a.pl | 17 +++++++++ .../scryer/cli/issues/compilation_bug.in/b.pl | 30 ++++++++++++++++ .../scryer/cli/issues/compilation_bug.in/c.pl | 19 ++++++++++ tests/scryer/cli/issues/compilation_bug.stdin | 2 ++ .../scryer/cli/issues/compilation_bug.stdout | 2 ++ tests/scryer/cli/issues/compilation_bug.toml | 2 ++ 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 tests/scryer/cli/issues/compilation_bug.in/a.pl create mode 100644 tests/scryer/cli/issues/compilation_bug.in/b.pl create mode 100644 tests/scryer/cli/issues/compilation_bug.in/c.pl create mode 100644 tests/scryer/cli/issues/compilation_bug.stdin create mode 100644 tests/scryer/cli/issues/compilation_bug.stdout create mode 100644 tests/scryer/cli/issues/compilation_bug.toml diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 635de289c..a5ebe291d 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -566,7 +566,38 @@ impl Machine { let mut p = self.machine_st.p; let mut arity = 0; + self.indices.code_dir.sort_by(|_, a, _, b| a.cmp(b)); + + let predicate_idx = self + .indices + .code_dir + .binary_search_by_key(&p, |_, x| x.get().p() as usize) + .unwrap_or_else(|x| x - 1); + + let current_pred_limit = self + .indices + .code_dir + .get_index(predicate_idx + 1) + .map(|x| x.1.p() as usize); + while self.code[p].is_head_instr() { + //println!("{}: {:?}", p, &self.code[p]); + //println!("{} {:?}", arity, self.code[p]); + for r in self.code[p].registers() { + //println!("reg {:?}", r); + if let RegType::Temp(t) = r { + arity = std::cmp::max(arity, t); + } + } + + p += 1; + } + + let p_interrupt = p; + + while p < self.code.len() + && current_pred_limit.map(|x| p < x).unwrap_or(true) + { for r in self.code[p].registers() { if let RegType::Temp(t) = r { arity = std::cmp::max(arity, t); @@ -577,14 +608,15 @@ impl Machine { } let instr = std::mem::replace( - &mut self.code[p], + &mut self.code[p_interrupt], Instruction::VerifyAttrInterrupt(arity), ); self.code[VERIFY_ATTR_INTERRUPT_LOC] = instr; - self.machine_st.attr_var_init.cp = p; + self.machine_st.attr_var_init.cp = p_interrupt; } &Instruction::VerifyAttrInterrupt(arity) => { + //println!("VerifyAttr arity: {arity}"); // let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity(); // let arity = std::cmp::max(arity, self.machine_st.num_of_args); self.run_verify_attr_interrupt(arity); diff --git a/tests/scryer/cli/issues/compilation_bug.in/a.pl b/tests/scryer/cli/issues/compilation_bug.in/a.pl new file mode 100644 index 000000000..baf223ada --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.in/a.pl @@ -0,0 +1,17 @@ +% Issue 2706 +:- use_module(library(atts)). +:- use_module(library(lists)). +:- use_module(library(iso_ext)). + +:- attribute a/1. + +verify_attributes(_,_, []). + +asdf([_|Xs], N) :- + true, + N1 is N - 1, + asdf(Xs, N1). + +test_a :- + put_atts(A, a(1)), + call_with_inference_limit(asdf(A, 1), 1000, _). diff --git a/tests/scryer/cli/issues/compilation_bug.in/b.pl b/tests/scryer/cli/issues/compilation_bug.in/b.pl new file mode 100644 index 000000000..b6f5539eb --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.in/b.pl @@ -0,0 +1,30 @@ +% Issue 2632 + +% Repro for cycle detection crash +:- use_module(library(lists)). +:- use_module(library(clpz)). +:- use_module(library(error)). +:- use_module(library(lambda)). +:- use_module(library(debug)). + +clpz:monotonic. + +q_r(T/N, T:U) :- 0 #=< #T, 0 #=< #U, #N #= T + U. + +qs_Ts_Us(Qs, ΣTs, ΣUs) :- + maplist(\Q^T^U^(q_r(Q, T:U)), Qs, Ts, Us), + intlist_partsums(Ts, ΣTs), + intlist_partsums(Us, ΣUs). + +%% Utility predicates used above: + +intlist_partsums([X|Xs], [X|Ss]) :- + intlist_partsums_acc(Xs, Ss, X). + +intlist_partsums_acc([], [], _). +intlist_partsums_acc([X|Xs], [S|Ss], A) :- + #S #= #X + #A, + intlist_partsums_acc(Xs, Ss, S). + +test_b :- + once(qs_Ts_Us(_, [1,3], [5,9])). diff --git a/tests/scryer/cli/issues/compilation_bug.in/c.pl b/tests/scryer/cli/issues/compilation_bug.in/c.pl new file mode 100644 index 000000000..a93848bea --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.in/c.pl @@ -0,0 +1,19 @@ +% Issue 2809 + +:- use_module(library(freeze)). + +main1 :- + freeze(Minor,true), + cbor_minor_value1(Minor, []). + +main2 :- + freeze(Minor,true), + cbor_minor_value2(Minor, []). + +cbor_minor_value1(24, S0) :- numbytes_number(1, S0). + +cbor_minor_value2(24, S0) :- S0=S1, numbytes_number(1, S1). + +numbytes_number(_, []). + +test_c :- main1. diff --git a/tests/scryer/cli/issues/compilation_bug.stdin b/tests/scryer/cli/issues/compilation_bug.stdin new file mode 100644 index 000000000..ab869cd29 --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.stdin @@ -0,0 +1,2 @@ +use_module(a), use_module(b), use_module(c). +\+ \+ (test_a, test_b, test_c). diff --git a/tests/scryer/cli/issues/compilation_bug.stdout b/tests/scryer/cli/issues/compilation_bug.stdout new file mode 100644 index 000000000..99f1c7157 --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.stdout @@ -0,0 +1,2 @@ + true. + true. diff --git a/tests/scryer/cli/issues/compilation_bug.toml b/tests/scryer/cli/issues/compilation_bug.toml new file mode 100644 index 000000000..a83959d8b --- /dev/null +++ b/tests/scryer/cli/issues/compilation_bug.toml @@ -0,0 +1,2 @@ +# issue 2706 +args = ["-f", "--no-add-history"] From 6d80c843e61774c821a5a605c6063795ab38ea5e Mon Sep 17 00:00:00 2001 From: bakaq Date: Wed, 5 Feb 2025 02:22:59 -0300 Subject: [PATCH 2/2] Scan entire predicate in InstallVerifyAttr --- src/machine/dispatch.rs | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index a5ebe291d..57d3e5ae0 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -563,9 +563,9 @@ impl Machine { self.machine_st.cp = self.machine_st.attr_var_init.cp; } - let mut p = self.machine_st.p; - let mut arity = 0; + let p = self.machine_st.p; + // Find the boundaries of the current predicate self.indices.code_dir.sort_by(|_, a, _, b| a.cmp(b)); let predicate_idx = self @@ -574,38 +574,41 @@ impl Machine { .binary_search_by_key(&p, |_, x| x.get().p() as usize) .unwrap_or_else(|x| x - 1); - let current_pred_limit = self + let current_pred_start = self .indices .code_dir - .get_index(predicate_idx + 1) - .map(|x| x.1.p() as usize); - - while self.code[p].is_head_instr() { - //println!("{}: {:?}", p, &self.code[p]); - //println!("{} {:?}", arity, self.code[p]); - for r in self.code[p].registers() { - //println!("reg {:?}", r); - if let RegType::Temp(t) = r { - arity = std::cmp::max(arity, t); - } - } + .get_index(predicate_idx) + .map(|x| x.1.p() as usize) + .unwrap(); - p += 1; - } + debug_assert!(current_pred_start <= p); - let p_interrupt = p; + let current_pred_end = self + .indices + .code_dir + .get_index(predicate_idx + 1) + .map(|x| x.1.p() as usize) + .unwrap_or(self.code.len()); - while p < self.code.len() - && current_pred_limit.map(|x| p < x).unwrap_or(true) - { - for r in self.code[p].registers() { - if let RegType::Temp(t) = r { - arity = std::cmp::max(arity, t); - } - } + debug_assert!(current_pred_end >= p); + debug_assert!(current_pred_end <= self.code.len()); - p += 1; - } + // Find point to insert the interrupt + let p_interrupt = p + self.code[p..current_pred_end] + .iter() + .position(|x| !x.is_head_instr()) + .unwrap(); + + // Scan registers of all instructions to find out how many to save + let arity = self.code[current_pred_start..current_pred_end] + .iter() + .flat_map(Instruction::registers) + .flat_map(|r| match r { + RegType::Temp(t) => Some(t), + _ => None, + }) + .max() + .unwrap_or(0); let instr = std::mem::replace( &mut self.code[p_interrupt], @@ -616,9 +619,6 @@ impl Machine { self.machine_st.attr_var_init.cp = p_interrupt; } &Instruction::VerifyAttrInterrupt(arity) => { - //println!("VerifyAttr arity: {arity}"); - // let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity(); - // let arity = std::cmp::max(arity, self.machine_st.num_of_args); self.run_verify_attr_interrupt(arity); } &Instruction::Add(ref a1, ref a2, t) => {