Skip to content

Commit f7f89fb

Browse files
committed
mcsat: gate preprocessor diag prints on YICES_PP_TRACE; trim windows CI
Two fixes / aids for the windows-latest|release|--enable-thread-safety --enable-mcsat mcsat_tuples failure investigation: 1. Gate every preprocessor.c TEMP DIAG stderr print behind an env var YICES_PP_TRACE. The existing prints were unconditional, so they leaked into the regression-test stderr stream and broke ~21 mcsat regression tests (`make test`) that diff stderr against expected output. With the gate, the prints are silent unless the env var is set, so: - `make test` regressions are clean again on every CI config - the prints are still available when needed: set YICES_PP_TRACE=1 (any non-empty / non-"0" value) before running the failing binary. Implementation: a tiny static helper `pp_diag_enabled()` reads the env var once (cached in a static int -- benign one-time race under --enable-thread-safety), and a `PP_DIAG(...)` macro wraps fprintf(stderr,...)+fflush(stderr). All call sites switched in build_value_from_flat, preprocessor_build_tuple_model, and preprocessor_build_model. Verified locally: mcsat_tuples -> 0 "[pp_build|build_value" lines YICES_PP_TRACE=1 mcsat_tuples -> 631 "[pp_build|build_value" lines 2. Trim Windows CI to only the failing config and only the API tests so each iteration takes ~10 minutes instead of an hour: - Matrix: mode=[release], config-opt=[--enable-thread-safety --enable-mcsat] (was 2x3=6 jobs, now 1). - Test step: just `make check-api` with YICES_PP_TRACE=1 exported, so mcsat_tuples emits the full preprocessor trace. The `make test` regression sweep is dropped for now. Both changes are TEMP and clearly commented; the original matrix and test step are restored at the end of this debugging session.
1 parent e19b027 commit f7f89fb

2 files changed

Lines changed: 80 additions & 88 deletions

File tree

.github/workflows/windows_ci.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ on:
66
jobs:
77
build:
88
strategy:
9+
# TEMP: while debugging the windows-latest|release|--enable-thread-safety
10+
# --enable-mcsat failure in mcsat_tuples.exe, restrict the matrix to only
11+
# the failing config so each iteration takes ~10 minutes instead of an hour.
12+
# Restore the full matrix [debug, release] x [' ', --enable-thread-safety,
13+
# --enable-thread-safety --enable-mcsat] once the failure is fixed.
914
matrix:
1015
os: [windows-latest]
11-
mode: [debug, release]
12-
config-opt: [' ', --enable-thread-safety, --enable-thread-safety --enable-mcsat]
16+
mode: [release]
17+
config-opt: [--enable-thread-safety --enable-mcsat]
1318

1419
name: ${{ matrix.os }}|${{ matrix.mode }}|${{ matrix.config-opt}}
1520
runs-on: ${{ matrix.os }}
@@ -94,11 +99,19 @@ jobs:
9499
export LD_LIBRARY_PATH=/usr/local/lib/:${LD_LIBRARY_PATH} &&
95100
make OPTION=mingw64 MODE=${{ matrix.mode }}
96101
97-
- name: Run Yices API Tests
102+
# TEMP: while debugging the mcsat_tuples failure, run only check-api
103+
# (the API tests, which include mcsat_tuples) with YICES_PP_TRACE=1 so
104+
# the verbose MCSAT preprocessor diagnostics are emitted. We skip the
105+
# `make test` regression suite (much slower and not relevant to this
106+
# bug) to keep iteration time short. Restore the full
107+
# make OPTION=mingw64 MODE=... check-api &&
108+
# make OPTION=mingw64 MODE=... test
109+
# step once the failure is fixed.
110+
- name: Run Yices API Tests (with PP diagnostics)
98111
shell: bash
99112
env:
100113
CYGWIN: winsymlinks:native binmode
114+
YICES_PP_TRACE: "1"
101115
run: >-
102116
export PATH=/tools/dynamic_gmp/bin:/tools/static_gmp/bin:$PATH &&
103-
make OPTION=mingw64 MODE=${{ matrix.mode }} check-api &&
104-
make OPTION=mingw64 MODE=${{ matrix.mode }} test
117+
make OPTION=mingw64 MODE=${{ matrix.mode }} check-api

src/mcsat/preprocessor.c

Lines changed: 62 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@
4040
#include "yices.h"
4141
#include "api/yices_api_lock_free.h"
4242

43+
#include <stdlib.h>
44+
45+
/* TEMP DIAG: stderr trace macro, gated on env var YICES_PP_TRACE so the
46+
* diagnostic prints don't pollute regression-test stderr (regression
47+
* tests diff stderr against expected output). Set YICES_PP_TRACE=1 in CI
48+
* runs that need to debug the Windows MinGW release+thread-safety
49+
* failure. To be removed along with every PP_DIAG call site once the
50+
* failure is pinpointed. */
51+
static int pp_diag_enabled(void) {
52+
static int cached = -1;
53+
if (cached < 0) {
54+
const char* s = getenv("YICES_PP_TRACE");
55+
cached = (s != NULL && s[0] != '\0' && s[0] != '0') ? 1 : 0;
56+
}
57+
return cached;
58+
}
59+
#define PP_DIAG(...) do { if (pp_diag_enabled()) { fprintf(stderr, __VA_ARGS__); fflush(stderr); } } while (0)
60+
4361
void preprocessor_construct(preprocessor_t* pre, term_table_t* terms, jmp_buf* handler, const mcsat_options_t* options) {
4462
pre->terms = terms;
4563
init_term_manager(&pre->tm, terms);
@@ -2461,43 +2479,35 @@ static value_t merge_blasted_function_value(preprocessor_t* pre, value_table_t*
24612479
static
24622480
value_t build_value_from_flat(preprocessor_t* pre, value_table_t* vtbl, type_t tau, const value_t* flat, uint32_t* idx) {
24632481
type_table_t* types = pre->terms->types;
2464-
fprintf(stderr, "[build_value_from_flat] enter tau=%d idx=%u\n", (int) tau, (unsigned) *idx);
2465-
fflush(stderr);
2482+
PP_DIAG("[build_value_from_flat] enter tau=%d idx=%u\n", (int) tau, (unsigned) *idx);
24662483

24672484
if (type_kind(types, tau) == TUPLE_TYPE) {
24682485
tuple_type_t* tuple = tuple_type_desc(types, tau);
24692486
uint32_t i, n = tuple->nelem;
2470-
fprintf(stderr, "[build_value_from_flat] TUPLE n=%u\n", (unsigned) n);
2471-
fflush(stderr);
2487+
PP_DIAG("[build_value_from_flat] TUPLE n=%u\n", (unsigned) n);
24722488
value_t elem[n];
24732489
for (i = 0; i < n; ++i) {
24742490
elem[i] = build_value_from_flat(pre, vtbl, tuple->elem[i], flat, idx);
24752491
if (elem[i] == null_value) {
2476-
fprintf(stderr, "[build_value_from_flat] TUPLE elem %u null\n", (unsigned) i);
2477-
fflush(stderr);
2492+
PP_DIAG("[build_value_from_flat] TUPLE elem %u null\n", (unsigned) i);
24782493
return null_value;
24792494
}
24802495
}
2481-
fprintf(stderr, "[build_value_from_flat] TUPLE calling vtbl_mk_tuple\n");
2482-
fflush(stderr);
2496+
PP_DIAG("[build_value_from_flat] TUPLE calling vtbl_mk_tuple\n");
24832497
value_t r = vtbl_mk_tuple(vtbl, n, elem);
2484-
fprintf(stderr, "[build_value_from_flat] TUPLE vtbl_mk_tuple -> %d\n", (int) r);
2485-
fflush(stderr);
2498+
PP_DIAG("[build_value_from_flat] TUPLE vtbl_mk_tuple -> %d\n", (int) r);
24862499
return r;
24872500
} else if (type_kind(types, tau) == FUNCTION_TYPE) {
24882501
uint32_t n = type_leaf_count(pre, tau);
2489-
fprintf(stderr, "[build_value_from_flat] FUNCTION n_leaves=%u\n", (unsigned) n);
2490-
fflush(stderr);
2502+
PP_DIAG("[build_value_from_flat] FUNCTION n_leaves=%u\n", (unsigned) n);
24912503
value_t v = merge_blasted_function_value(pre, vtbl, tau, flat + *idx, n);
24922504
*idx += n;
2493-
fprintf(stderr, "[build_value_from_flat] FUNCTION merge -> %d new_idx=%u\n", (int) v, (unsigned) *idx);
2494-
fflush(stderr);
2505+
PP_DIAG("[build_value_from_flat] FUNCTION merge -> %d new_idx=%u\n", (int) v, (unsigned) *idx);
24952506
return v;
24962507
} else {
24972508
value_t v = flat[*idx];
24982509
(*idx)++;
2499-
fprintf(stderr, "[build_value_from_flat] LEAF v=%d new_idx=%u\n", (int) v, (unsigned) *idx);
2500-
fflush(stderr);
2510+
PP_DIAG("[build_value_from_flat] LEAF v=%d new_idx=%u\n", (int) v, (unsigned) *idx);
25012511
return v;
25022512
}
25032513
}
@@ -2696,30 +2706,26 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
26962706
uint32_t i;
26972707

26982708
/* TEMP DIAG (windows release+thread-safety mcsat_tuples failure) */
2699-
fprintf(stderr, "[pp_build_tuple] enter, atoms=%u\n",
2709+
PP_DIAG("[pp_build_tuple] enter, atoms=%u\n",
27002710
(unsigned) pre->tuple_blast_atoms.size);
2701-
fflush(stderr);
27022711
for (i = 0; i < pre->tuple_blast_atoms.size; ++i) {
27032712
term_t atom = pre->tuple_blast_atoms.data[i];
27042713
ivector_t leaves;
27052714
type_t tau = term_type(pre->terms, atom);
27062715
uint32_t n, j;
27072716

2708-
fprintf(stderr, "[pp_build_tuple] i=%u atom=%d tau=%d\n",
2717+
PP_DIAG("[pp_build_tuple] i=%u atom=%d tau=%d\n",
27092718
(unsigned) i, (int) atom, (int) tau);
2710-
fflush(stderr);
27112719

27122720
if (model_find_term_value(model, atom) != null_value) {
2713-
fprintf(stderr, "[pp_build_tuple] atom already mapped, continue\n");
2714-
fflush(stderr);
2721+
PP_DIAG("[pp_build_tuple] atom already mapped, continue\n");
27152722
continue;
27162723
}
27172724

27182725
init_ivector(&leaves, 0);
27192726
tuple_blast_get(pre, atom, &leaves);
27202727
n = leaves.size;
2721-
fprintf(stderr, "[pp_build_tuple] n_leaves=%u\n", (unsigned) n);
2722-
fflush(stderr);
2728+
PP_DIAG("[pp_build_tuple] n_leaves=%u\n", (unsigned) n);
27232729
if (n == 0) {
27242730
delete_ivector(&leaves);
27252731
continue;
@@ -2728,12 +2734,10 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
27282734
value_t leaf_vals[n];
27292735
bool ok = true;
27302736
for (j = 0; j < n; ++j) {
2731-
fprintf(stderr, "[pp_build_tuple] j=%u leaf=%d\n",
2737+
PP_DIAG("[pp_build_tuple] j=%u leaf=%d\n",
27322738
(unsigned) j, (int) leaves.data[j]);
2733-
fflush(stderr);
27342739
value_t v = model_get_term_value(model, leaves.data[j]);
2735-
fprintf(stderr, "[pp_build_tuple] model_get_term_value -> %d\n", (int) v);
2736-
fflush(stderr);
2740+
PP_DIAG("[pp_build_tuple] model_get_term_value -> %d\n", (int) v);
27372741
if (v < 0) {
27382742
/* The blasted leaf was never assigned a value by the mcsat
27392743
* search (typical for unconstrained tuple components) and
@@ -2745,21 +2749,18 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
27452749
* vtbl_make_object handles bool / arith / bv / tuple /
27462750
* function / scalar uniformly. */
27472751
type_t leaf_tau = term_type(pre->terms, leaves.data[j]);
2748-
fprintf(stderr, "[pp_build_tuple] leaf_tau=%d, calling vtbl_make_object\n",
2752+
PP_DIAG("[pp_build_tuple] leaf_tau=%d, calling vtbl_make_object\n",
27492753
(int) leaf_tau);
2750-
fflush(stderr);
27512754
v = vtbl_make_object(vtbl, leaf_tau);
2752-
fprintf(stderr, "[pp_build_tuple] vtbl_make_object -> %d\n", (int) v);
2753-
fflush(stderr);
2755+
PP_DIAG("[pp_build_tuple] vtbl_make_object -> %d\n", (int) v);
27542756
if (v < 0) {
27552757
ok = false;
27562758
break;
27572759
}
27582760
}
27592761
leaf_vals[j] = v;
27602762
}
2761-
fprintf(stderr, "[pp_build_tuple] leaf loop done, ok=%d\n", (int) ok);
2762-
fflush(stderr);
2763+
PP_DIAG("[pp_build_tuple] leaf loop done, ok=%d\n", (int) ok);
27632764
if (!ok) {
27642765
/* vtbl_make_object failed for some leaf: the type cannot be
27652766
* inhabited concretely (extremely unusual -- e.g. a malformed
@@ -2778,11 +2779,9 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
27782779
}
27792780

27802781
if (type_kind(types, tau) == FUNCTION_TYPE) {
2781-
fprintf(stderr, "[pp_build_tuple] FUNCTION_TYPE branch\n");
2782-
fflush(stderr);
2782+
PP_DIAG("[pp_build_tuple] FUNCTION_TYPE branch\n");
27832783
value_t f = merge_blasted_function_value(pre, vtbl, tau, leaf_vals, n);
2784-
fprintf(stderr, "[pp_build_tuple] merge_blasted_function_value -> %d\n", (int) f);
2785-
fflush(stderr);
2784+
PP_DIAG("[pp_build_tuple] merge_blasted_function_value -> %d\n", (int) f);
27862785
if (f >= 0) {
27872786
model_map_term(model, atom, f);
27882787
} else if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
@@ -2793,20 +2792,16 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
27932792
trace_term_ln(pre->tracer, pre->terms, atom);
27942793
}
27952794
} else {
2796-
fprintf(stderr, "[pp_build_tuple] non-FUNCTION branch, calling build_value_from_flat\n");
2797-
fflush(stderr);
2795+
PP_DIAG("[pp_build_tuple] non-FUNCTION branch, calling build_value_from_flat\n");
27982796
uint32_t idx = 0;
27992797
value_t v = build_value_from_flat(pre, vtbl, tau, leaf_vals, &idx);
2800-
fprintf(stderr, "[pp_build_tuple] build_value_from_flat -> %d (idx=%u)\n",
2798+
PP_DIAG("[pp_build_tuple] build_value_from_flat -> %d (idx=%u)\n",
28012799
(int) v, (unsigned) idx);
2802-
fflush(stderr);
28032800
if (v >= 0) {
2804-
fprintf(stderr, "[pp_build_tuple] model_map_term(atom=%d, v=%d)\n",
2801+
PP_DIAG("[pp_build_tuple] model_map_term(atom=%d, v=%d)\n",
28052802
(int) atom, (int) v);
2806-
fflush(stderr);
28072803
model_map_term(model, atom, v);
2808-
fprintf(stderr, "[pp_build_tuple] model_map_term OK\n");
2809-
fflush(stderr);
2804+
PP_DIAG("[pp_build_tuple] model_map_term OK\n");
28102805
} else if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
28112806
mcsat_trace_printf(pre->tracer,
28122807
"preprocessor_build_tuple_model: dropping tuple atom ");
@@ -2817,11 +2812,9 @@ void preprocessor_build_tuple_model(preprocessor_t* pre, model_t* model) {
28172812
}
28182813

28192814
delete_ivector(&leaves);
2820-
fprintf(stderr, "[pp_build_tuple] end of iteration i=%u\n", (unsigned) i);
2821-
fflush(stderr);
2815+
PP_DIAG("[pp_build_tuple] end of iteration i=%u\n", (unsigned) i);
28222816
}
2823-
fprintf(stderr, "[pp_build_tuple] exit\n");
2824-
fflush(stderr);
2817+
PP_DIAG("[pp_build_tuple] exit\n");
28252818
}
28262819

28272820
static term_t build_term_from_flat(preprocessor_t* pre, type_t tau, const term_t* flat, uint32_t* idx);
@@ -3065,15 +3058,13 @@ void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
30653058
evaluator_t eval;
30663059
bool eval_inited = false;
30673060
/* TEMP DIAG (windows release+thread-safety mcsat_tuples failure) */
3068-
fprintf(stderr, "[pp_build_model] enter, has_alias=%d, eqs=%u\n",
3061+
PP_DIAG("[pp_build_model] enter, has_alias=%d, eqs=%u\n",
30693062
(int) model->has_alias, (unsigned) pre->equalities_list.size);
3070-
fflush(stderr);
30713063
for (i = 0; i < pre->equalities_list.size; ++ i) {
30723064
term_t eq = pre->equalities_list.data[i];
30733065
term_t eq_var = preprocessor_get_eq_solved_var(pre, eq);
3074-
fprintf(stderr, "[pp_build_model] i=%u eq=%d eq_var=%d\n",
3066+
PP_DIAG("[pp_build_model] i=%u eq=%d eq_var=%d\n",
30753067
(unsigned) i, (int) eq, (int) eq_var);
3076-
fflush(stderr);
30773068
if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
30783069
mcsat_trace_printf(pre->tracer, "eq = ");
30793070
trace_term_ln(pre->tracer, pre->terms, eq);
@@ -3084,29 +3075,24 @@ void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
30843075
// Some equalities are solved, but then reasserted in the solver
30853076
// these already have a model
30863077
if (model_find_term_value(model, eq_var) != null_value) {
3087-
fprintf(stderr, "[pp_build_model] already mapped, continue\n");
3088-
fflush(stderr);
3078+
PP_DIAG("[pp_build_model] already mapped, continue\n");
30893079
continue;
30903080
}
30913081
// Some equalities are marked, but not solved. These we skip as they
30923082
// are already set in the model
30933083
if (preprocessor_get(pre, eq_var) == eq_var) {
3094-
fprintf(stderr, "[pp_build_model] not solved, continue\n");
3095-
fflush(stderr);
3084+
PP_DIAG("[pp_build_model] not solved, continue\n");
30963085
continue;
30973086
}
30983087
term_kind_t eq_kind = term_kind(pre->terms, eq);
3099-
fprintf(stderr, "[pp_build_model] eq_kind=%d\n", (int) eq_kind);
3100-
fflush(stderr);
3088+
PP_DIAG("[pp_build_model] eq_kind=%d\n", (int) eq_kind);
31013089
composite_term_t* eq_desc = get_composite(pre->terms, eq_kind, eq);
3102-
fprintf(stderr, "[pp_build_model] eq_desc=%p arity=%u\n",
3090+
PP_DIAG("[pp_build_model] eq_desc=%p arity=%u\n",
31033091
(void*) eq_desc, eq_desc ? (unsigned) eq_desc->arity : 0u);
3104-
fflush(stderr);
31053092
term_t eq_subst = eq_desc->arity > 1
31063093
? (eq_desc->arg[0] == eq_var ? eq_desc->arg[1] : eq_desc->arg[0])
31073094
: zero_term;
3108-
fprintf(stderr, "[pp_build_model] eq_subst=%d\n", (int) eq_subst);
3109-
fflush(stderr);
3095+
PP_DIAG("[pp_build_model] eq_subst=%d\n", (int) eq_subst);
31103096
if (model->has_alias) {
31113097
/* Standard path: record the substitution and let the model
31123098
* evaluator resolve eq_var lazily via eval_term(eq_subst). */
@@ -3125,31 +3111,25 @@ void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
31253111
* If eval fails (e.g., eq_subst transitively depends on another
31263112
* not-yet-mapped eq_var), fall back to a fresh default value. */
31273113
if (!eval_inited) {
3128-
fprintf(stderr, "[pp_build_model] init_evaluator\n"); fflush(stderr);
3114+
PP_DIAG("[pp_build_model] init_evaluator\n");
31293115
init_evaluator(&eval, model);
31303116
eval_inited = true;
3131-
fprintf(stderr, "[pp_build_model] init_evaluator OK\n"); fflush(stderr);
3117+
PP_DIAG("[pp_build_model] init_evaluator OK\n");
31323118
}
3133-
fprintf(stderr, "[pp_build_model] eval_in_model(%d)\n", (int) eq_subst);
3134-
fflush(stderr);
3119+
PP_DIAG("[pp_build_model] eval_in_model(%d)\n", (int) eq_subst);
31353120
value_t v = eval_in_model(&eval, eq_subst);
3136-
fprintf(stderr, "[pp_build_model] eval_in_model -> v=%d\n", (int) v);
3137-
fflush(stderr);
3121+
PP_DIAG("[pp_build_model] eval_in_model -> v=%d\n", (int) v);
31383122
if (v < 0) {
31393123
type_t eq_var_tau = term_type(pre->terms, eq_var);
3140-
fprintf(stderr, "[pp_build_model] vtbl_make_object(tau=%d)\n", (int) eq_var_tau);
3141-
fflush(stderr);
3124+
PP_DIAG("[pp_build_model] vtbl_make_object(tau=%d)\n", (int) eq_var_tau);
31423125
v = vtbl_make_object(model_get_vtbl(model), eq_var_tau);
3143-
fprintf(stderr, "[pp_build_model] vtbl_make_object -> v=%d\n", (int) v);
3144-
fflush(stderr);
3126+
PP_DIAG("[pp_build_model] vtbl_make_object -> v=%d\n", (int) v);
31453127
}
31463128
if (v >= 0) {
3147-
fprintf(stderr, "[pp_build_model] model_map_term(eq_var=%d, v=%d)\n",
3129+
PP_DIAG("[pp_build_model] model_map_term(eq_var=%d, v=%d)\n",
31483130
(int) eq_var, (int) v);
3149-
fflush(stderr);
31503131
model_map_term(model, eq_var, v);
3151-
fprintf(stderr, "[pp_build_model] model_map_term OK\n");
3152-
fflush(stderr);
3132+
PP_DIAG("[pp_build_model] model_map_term OK\n");
31533133
} else if (trace_enabled(pre->tracer, "mcsat::preprocess")) {
31543134
mcsat_trace_printf(pre->tracer,
31553135
"preprocessor_build_model: failed to bind eq_var ");
@@ -3159,15 +3139,14 @@ void preprocessor_build_model(preprocessor_t* pre, model_t* model) {
31593139
}
31603140

31613141
if (eval_inited) {
3162-
fprintf(stderr, "[pp_build_model] delete_evaluator\n"); fflush(stderr);
3142+
PP_DIAG("[pp_build_model] delete_evaluator\n");
31633143
delete_evaluator(&eval);
3164-
fprintf(stderr, "[pp_build_model] delete_evaluator OK\n"); fflush(stderr);
3144+
PP_DIAG("[pp_build_model] delete_evaluator OK\n");
31653145
}
31663146

3167-
fprintf(stderr, "[pp_build_model] calling preprocessor_build_tuple_model\n");
3168-
fflush(stderr);
3147+
PP_DIAG("[pp_build_model] calling preprocessor_build_tuple_model\n");
31693148
preprocessor_build_tuple_model(pre, model);
3170-
fprintf(stderr, "[pp_build_model] exit\n"); fflush(stderr);
3149+
PP_DIAG("[pp_build_model] exit\n");
31713150
}
31723151

31733152

0 commit comments

Comments
 (0)