Repository navigation
JIRA-2258 review aid: Tsavorite-only diff vs upstream 1f368f354 (side-by-side) - #163
akapoor3518 wants to merge 10 commits into
Conversation
Single commit on top of upstream-1f368f354-baseline (the exact commit consolidated-patch.patch is generated against) whose tree matches jira-2258-llama-cpp-sync's tip exactly. This makes the PR comparing this branch against upstream-1f368f354-baseline show only the ~93 files this sync actually changes (Tsavorite backend, build config, new tsi-ggml/JIRA-2258 doc files) instead of the ~3150-file diff PR #162 shows against master (which includes ~1 year of upstream's own already-reviewed commit history landing via the version bump). Not intended to be merged directly -- this is a review aid only. The actual merge path remains PR #162 (jira-2258-llama-cpp-sync -> master).
Per review feedback: raw per-run logs are evidence for reviewing this PR, not permanent reference material every future clone needs to carry forever. Removing them from the tracked tree; the three summary docs (POSIX-COMPARISON-SUMMARY.md, GEMMA4-VALIDATION-SUMMARY.md, TSISIM-VALIDATION-SUMMARY.md) stay -- they already quote the key excerpts (exact outputs, exact op-dispatch tables) inline. Full raw logs to be attached directly to the PR description instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
8 issues found and verified against the latest diff
Not reviewed (too large): consolidated-patch.patch (~12,637 lines), ggml/src/ggml-tsavorite/ggml-tsavorite.cpp (~8,221 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="ggml/src/ggml-backend-impl.h">
<violation number="1" location="ggml/src/ggml-backend-impl.h:142">
P1: When an older dynamically loaded backend reports API version 2, the new host interprets its old `device` and `context` fields as these callbacks. Bump `GGML_BACKEND_API_VERSION` or preserve a compatible `ggml_backend` layout when extending `ggml_backend_i`.</violation>
</file>
<file name="ggml/CMakeLists.txt">
<violation number="1" location="ggml/CMakeLists.txt:334">
P2: After installation, any consumer including `<ggml-tsavorite.h>` fails because this entry ships the header without its private `TestModel.h` and SDK-only `HostShimCAPI.h` dependencies. Make the public header self-contained or package and expose those dependencies before adding it to `GGML_PUBLIC_HEADERS`.</violation>
</file>
<file name="tools/cli/cli.cpp">
<violation number="1" location="tools/cli/cli.cpp:31">
P1: In perf builds, this callback suppresses all ordinary llama warnings and errors because it forwards only `GGML_LOG_LEVEL_TSAVORITE`. Forward `GGML_LOG_LEVEL_WARN` and `GGML_LOG_LEVEL_ERROR` as well, while retaining the Tsavorite level if its diagnostics are required.</violation>
</file>
<file name="ggml/src/ggml-backend-reg.cpp">
<violation number="1" location="ggml/src/ggml-backend-reg.cpp:586">
P1: In non-OLLAMA `GGML_BACKEND_DL` builds, this load attempt always rejects the Tsavorite module for an API-version mismatch. Set `g_ggml_backend_tsavorite_reg.api_version` for every dynamic-build path before loading it.</violation>
</file>
<file name="ggml/src/ggml-backend.cpp">
<violation number="1" location="ggml/src/ggml-backend.cpp:1141">
P1: When a graph contains a view, this block overwrites both the view and its source with the CPU backend. Preserve the source's assigned backend; views should follow it rather than forcing accelerator results onto CPU.</violation>
<violation number="2" location="ggml/src/ggml-backend.cpp:2457">
P1: When a live Tsavorite backend exists, `ggml_backend_cleanup()` finalizes its runtime before the backend is freed. Defer this call until all Tsavorite backends are destroyed, or make teardown ownership explicit, because later `tsi_dealloc` and device release use finalized state.</violation>
</file>
<file name="ggml/include/ggml.h">
<violation number="1" location="ggml/include/ggml.h:714">
P1: When the library and consumer use different perf flags, `struct ggml_tensor` has different size and layout. Keep this public struct layout identical in every build by moving counters out-of-line or exposing the same tail unconditionally, and ensure the build definition reaches all consumers.</violation>
</file>
<file name=".gitmodules">
<violation number="1" location=".gitmodules:2">
P1: In an already-patched checkout, this metadata has no matching `ggml-tsi-kernel` gitlink, so `git submodule update --init --recursive` does nothing and the TSI build fails when `ensure_submodules()` finds the directory missing. Add the pinned `ggml-tsi-kernel` gitlink, or register it before `apply_consolidated_patch()` returns for already-patched trees.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
…e build exclusion Cubic review fixes (PR #163): - ggml-tsavorite.cpp: set g_ggml_backend_tsavorite_reg.api_version on every dynamic-build path, not just OLLAMA, so GGML_BACKEND_DL loads the backend - tools/cli, tools/completion CMakeLists.txt: drop the broken CMAKE_FIND_ROOT_PATH-based rpath-link block (see below) and use target_link_options instead of mutating CMAKE_EXE_LINKER_FLAGS globally - src/llama-context.cpp, include/llama.h, common/sampling.cpp: split the Tsavorite-only perf summary out of llama_perf_context_print() into llama_perf_context_print_tsavorite_summary() so common_perf_print() no longer double-prints the plain load/eval/total-time lines - model-rerun.py: anchor the eval-time regex to the standalone "eval time" line so it doesn't match the "prompt eval time" line's suffix - .github/copilot-instructions.md: add UPSTREAM_BASE_COMMIT to the upstream-sync review scope - CMakeLists.txt: restore LLAMA_OPENSSL default to ON (HTTPS was silently disabled for all builds, not just a cross-compile target that needed it) - ggml/include/ggml-tsavorite.h, ggml-tsavorite.cpp: drop the TestModel.h include from the public header (unused there, and not installed -- any external consumer of the installed header would fail to compile) and include it directly in ggml-tsavorite.cpp instead, which actually needs MemRefDescriptor from it - Proactively fixed 5 more unquoted GGML_TSAVORITE_TARGET STREQUAL comparisons (same crash-the-whole-configure bug as PR #162's fixes) found while auditing the above Real bug found while verifying the rpath-link fix on a full FPGA rebuild: CMAKE_FIND_ROOT_PATH is a 4-entry CMake list set by the ARM toolchain file (its own sysroot search path, unrelated to the Tsavorite SDK), not a single path. Appending "/lib" to it and using it for -L/-rpath-link produced a corrupted multi-entry flag list that broke the FPGA link for every executable target processed after common/CMakeLists.txt with "ld: ... Is a directory". The rpath-link this block was trying to provide is already wired globally via tsi-pkg-build.sh's -DCMAKE_EXE_LINKER_FLAGS (FPGA_TOOLBOX_LIB_DIR / FPGA_RUNTIME_LIB_DIR), so removed the redundant per-target block entirely instead of patching it further. Separate regression found during the same verification, unrelated to cubic: tools/CMakeLists.txt had add_subdirectory(cli) and add_subdirectory(server) nested inside the pre-existing `if (NOT DEFINED GGML_TSAVORITE)` exclusion (the old fork built `main`, llama-cli's pre-refactor name, outside that guard). This sync moved cli under the guard by accident, so llama-cli and llama-server were never built at all with GGML_TSAVORITE=ON, in posix or fpga -- silently breaking model-rerun.py (added in this same PR), which calls build-posix/bin/llama-cli. Moved ui/cli/server out from under the Tsavorite exclusion (gated only by LLAMA_BUILD_SERVER, matching upstream's intent), and moved mtmd out too since llama-server-impl now links it. Verified: full posix + fpga rebuild is clean (0 errors) with all binaries present, including llama-cli and llama-server for the first time under GGML_TSAVORITE=ON. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…te build exclusion Same fix set as jira-2258-llama-cpp-sync@2beaa3bc0 (the real PR #162 branch), carried over here so this review-aid diff reflects the cubic-dev-ai fixes: - ggml-tsavorite.cpp: set g_ggml_backend_tsavorite_reg.api_version on every dynamic-build path, not just OLLAMA - tools/cli, tools/completion CMakeLists.txt: drop the broken CMAKE_FIND_ROOT_PATH-based rpath-link block, use target_link_options - src/llama-context.cpp, include/llama.h, common/sampling.cpp: split the Tsavorite-only perf summary into llama_perf_context_print_tsavorite_summary() so common_perf_print() no longer double-prints the plain perf lines - model-rerun.py: anchor the eval-time regex to the standalone "eval time" line - .github/copilot-instructions.md: add UPSTREAM_BASE_COMMIT to review scope - CMakeLists.txt: restore LLAMA_OPENSSL default to ON - ggml-tsavorite.h/.cpp: drop TestModel.h from the public header, include it directly in ggml-tsavorite.cpp instead - 5 more unquoted GGML_TSAVORITE_TARGET STREQUAL comparisons fixed - tools/CMakeLists.txt: move cli/server/mtmd out of the GGML_TSAVORITE exclusion -- they were never built under Tsavorite at all (pre-existing regression from this sync, unrelated to cubic, found while verifying the rpath-link fix on a full FPGA rebuild) - README.md, docs/build.md: SDK_VERSION export + source-not-exec fixes carried forward from an earlier point in the same sync Verified on jira-2258-llama-cpp-sync: full posix + fpga rebuild clean (0 errors), llama-cli and llama-server now present in both for the first time under GGML_TSAVORITE=ON. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same as jira-2258-llama-cpp-sync@4ff4e3ad0 -- carried over so this review-aid diff matches the real branch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
6 issues found across 31 files (changes from recent commits).
Not reviewed (too large): consolidated-patch.patch (~519 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tools/completion/CMakeLists.txt">
<violation number="1" location="tools/completion/CMakeLists.txt:21">
P1: Direct FPGA builds documented in `README.md` and `docs/build.md` do not receive the global linker flags described here. After removing the target-specific flags, `llama-completion` can fail to link with unresolved transitively-needed `tsi_*` symbols; retain a CMake-side fallback or update the direct-build path to provide these library paths.</violation>
</file>
<file name="ggml/src/ggml-backend-impl.h">
<violation number="1" location="ggml/src/ggml-backend-impl.h:148">
P2: When an older dynamically loaded backend is used, the loader still accepts API version 2 even though `profile` now has a different function type. Bump the backend API version or add an explicit compatibility path for the old callback signature.</violation>
</file>
<file name="common/common.h">
<violation number="1" location="common/common.h:468">
P1: When `GGML_BACKEND_DL=ON`, neither macro reaches `common.h`: CMake skips `GGML_USE_TSAVORITE`, and `GGML_TSAVORITE` is not a compiler definition. `fit_params` therefore remains true, so `common_init_result` can still run the Tsavorite-crashing probe; propagate a Tsavorite definition to `llama-common` for dynamic builds.</violation>
</file>
<file name=".github/copilot-instructions.md">
<violation number="1" location=".github/copilot-instructions.md:16">
P3: This added line violates the repository's ASCII-only documentation rule. Replace the em dash with an ASCII hyphen.</violation>
</file>
<file name="common/CMakeLists.txt">
<violation number="1" location="common/CMakeLists.txt:180">
P1: When FPGA is configured with the documented direct CMake command instead of `tsi-pkg-build.sh`, this branch provides no `-Wl,-rpath-link` for the Tsavorite runtime libraries, so final executable links fail on transitive `tsi_*` dependencies. Expose the required link options through the CMake target/interface, or update the direct-build instructions to pass equivalent flags.</violation>
</file>
<file name="tsi-pkg-build.sh">
<violation number="1" location="tsi-pkg-build.sh:286">
P1: When a sourced build hits a handled failure, this global `set -e` exits the caller shell instead of returning the error as `die()` promises, and skips the `RETURN` cleanup that restores shell options, cwd-related state, and the prior virtual environment. Do not enable errexit in the caller; propagate sourced failures with explicit checks or execute the build in a controlled subshell.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
|
||
| add_executable(${TARGET} main.cpp) | ||
| target_link_libraries(${TARGET} PRIVATE llama-completion-impl) | ||
| # rpath-link for transitively-needed tsi_* symbols on FPGA builds is handled |
There was a problem hiding this comment.
P1: Direct FPGA builds documented in README.md and docs/build.md do not receive the global linker flags described here. After removing the target-specific flags, llama-completion can fail to link with unresolved transitively-needed tsi_* symbols; retain a CMake-side fallback or update the direct-build path to provide these library paths.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/completion/CMakeLists.txt, line 21:
<comment>Direct FPGA builds documented in `README.md` and `docs/build.md` do not receive the global linker flags described here. After removing the target-specific flags, `llama-completion` can fail to link with unresolved transitively-needed `tsi_*` symbols; retain a CMake-side fallback or update the direct-build path to provide these library paths.</comment>
<file context>
@@ -18,13 +18,9 @@ set(TARGET llama-completion)
- target_link_directories(${TARGET} PRIVATE ${SYSROOT_PATH_FOR_LIBRARIES})
-endif()
-endif()
+# rpath-link for transitively-needed tsi_* symbols on FPGA builds is handled
+# globally via -DCMAKE_EXE_LINKER_FLAGS in tsi-pkg-build.sh (FPGA_TOOLBOX_LIB_DIR /
+# FPGA_RUNTIME_LIB_DIR) -- no per-target linker flags needed here.
</file context>
There was a problem hiding this comment.
Good catch - removing that block also removed the only rpath-link source for anyone using the direct/manual cmake flow from README/docs/build.md instead of tsi-pkg-build.sh. Moved the fix up to the top-level CMakeLists.txt instead, using add_link_options() once for the whole fpga build so it applies to every target (llama-cli, llama-completion, llama-server, simple-backend-tsi) regardless of whether tsi-pkg-build.sh or the manual cmake commands are used. Verified with a clean FPGA rebuild.
| int32_t n_gpu_layers = -1; // number of layers to store in VRAM, -1 is auto, <= -2 is all | ||
| int32_t main_gpu = 0; // the GPU that is used for scratch and small tensors | ||
| float tensor_split[128] = {0}; // how split tensors should be distributed across GPUs | ||
| #if defined(GGML_TSAVORITE) || defined(GGML_USE_TSAVORITE) |
There was a problem hiding this comment.
P1: When GGML_BACKEND_DL=ON, neither macro reaches common.h: CMake skips GGML_USE_TSAVORITE, and GGML_TSAVORITE is not a compiler definition. fit_params therefore remains true, so common_init_result can still run the Tsavorite-crashing probe; propagate a Tsavorite definition to llama-common for dynamic builds.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At common/common.h, line 468:
<comment>When `GGML_BACKEND_DL=ON`, neither macro reaches `common.h`: CMake skips `GGML_USE_TSAVORITE`, and `GGML_TSAVORITE` is not a compiler definition. `fit_params` therefore remains true, so `common_init_result` can still run the Tsavorite-crashing probe; propagate a Tsavorite definition to `llama-common` for dynamic builds.</comment>
<file context>
@@ -465,13 +465,20 @@ struct common_params {
int32_t main_gpu = 0; // the GPU that is used for scratch and small tensors
float tensor_split[128] = {0}; // how split tensors should be distributed across GPUs
-#ifdef GGML_TSAVORITE
+#if defined(GGML_TSAVORITE) || defined(GGML_USE_TSAVORITE)
// fit_params (a new upstream feature) constructs a throwaway llama_context per
// device purely to probe its free memory, which initializes that device's ggml
</file context>
There was a problem hiding this comment.
This one I'm not fixing as a #ifdef tweak - it can't actually be fixed that way. GGML_BACKEND_DL is a compile-time flag; whether Tsavorite ends up dynamically loaded is a runtime decision, so no header-level #ifdef can know that at the point common.h is compiled. Closing this properly needs a runtime check (something like "if any loaded backend is tsavorite, disable fit_params"), not a default tweak here. Worth noting: this codebase's own build tooling (tsi-pkg-build.sh) never sets GGML_BACKEND_DL=ON for either posix or fpga, so this specific gap isn't live in any build this repo's scripts actually produce today. Flagging as a real but narrow follow-up.
| target_link_libraries(${TARGET} PUBLIC llama Threads::Threads) | ||
| if (GGML_TSAVORITE) | ||
| if ("${GGML_TSAVORITE_TARGET}" STREQUAL "fpga") | ||
| # rpath-link for transitively-needed tsi_* symbols is handled globally via |
There was a problem hiding this comment.
P1: When FPGA is configured with the documented direct CMake command instead of tsi-pkg-build.sh, this branch provides no -Wl,-rpath-link for the Tsavorite runtime libraries, so final executable links fail on transitive tsi_* dependencies. Expose the required link options through the CMake target/interface, or update the direct-build instructions to pass equivalent flags.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At common/CMakeLists.txt, line 180:
<comment>When FPGA is configured with the documented direct CMake command instead of `tsi-pkg-build.sh`, this branch provides no `-Wl,-rpath-link` for the Tsavorite runtime libraries, so final executable links fail on transitive `tsi_*` dependencies. Expose the required link options through the CMake target/interface, or update the direct-build instructions to pass equivalent flags.</comment>
<file context>
@@ -176,11 +176,14 @@ if (LLAMA_LLGUIDANCE)
if (GGML_TSAVORITE)
- if (${GGML_TSAVORITE_TARGET} STREQUAL fpga)
+ if ("${GGML_TSAVORITE_TARGET}" STREQUAL "fpga")
+ # rpath-link for transitively-needed tsi_* symbols is handled globally via
+ # -DCMAKE_EXE_LINKER_FLAGS in tsi-pkg-build.sh (FPGA_TOOLBOX_LIB_DIR /
+ # FPGA_RUNTIME_LIB_DIR) -- no per-target linker flags needed here. A prior
</file context>
There was a problem hiding this comment.
Same root cause/fix as the tools/cli and tools/completion comments - moved this to a single add_link_options() call in the top-level CMakeLists.txt instead of duplicating (and, before, getting wrong) the same rpath-link logic per-target. Covers the manual-cmake-build gap too now.
| # so this correctly aborts the whole call chain instead of silently | ||
| # continuing with invalid state. cleanup()'s trap restores this (and every | ||
| # other shell option) via __TSI_OLD_SET on every return/exit path below. | ||
| set -e |
There was a problem hiding this comment.
P1: When a sourced build hits a handled failure, this global set -e exits the caller shell instead of returning the error as die() promises, and skips the RETURN cleanup that restores shell options, cwd-related state, and the prior virtual environment. Do not enable errexit in the caller; propagate sourced failures with explicit checks or execute the build in a controlled subshell.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tsi-pkg-build.sh, line 286:
<comment>When a sourced build hits a handled failure, this global `set -e` exits the caller shell instead of returning the error as `die()` promises, and skips the `RETURN` cleanup that restores shell options, cwd-related state, and the prior virtual environment. Do not enable errexit in the caller; propagate sourced failures with explicit checks or execute the build in a controlled subshell.</comment>
<file context>
@@ -277,6 +277,13 @@ export SDK_VERSION
+# so this correctly aborts the whole call chain instead of silently
+# continuing with invalid state. cleanup()'s trap restores this (and every
+# other shell option) via __TSI_OLD_SET on every return/exit path below.
+set -e
__TSI_SCRIPT_PATH="${BASH_SOURCE[0]:-$0}"
__TSI_SCRIPT_DIR="$(cd "$(dirname "${__TSI_SCRIPT_PATH}")" 2>/dev/null && pwd)"
</file context>
There was a problem hiding this comment.
You're right and this is a real problem - verified it empirically. Sourcing this script with set -e active and hitting ANY failing command (not just inside die()) kills the calling shell outright, not just this script, and skips cleanup() entirely since only a RETURN trap is registered for the sourced case, which doesn't fire on an errexit-triggered process exit. Reverted the set -e. The narrower thing it was trying to fix (cmd || die "msg" not aborting the caller when die() returns 1) is still open, but it's a much smaller problem than "sourcing this can kill your terminal" - noted as a known follow-up in a comment at that spot instead.
| // (optional) reset backend state (used by ollama) | ||
| void (*reset) (ggml_backend_t backend); | ||
| // (optional) print backend-specific profiling info | ||
| void (*profile) (ggml_backend_t backend); |
There was a problem hiding this comment.
P2: When an older dynamically loaded backend is used, the loader still accepts API version 2 even though profile now has a different function type. Bump the backend API version or add an explicit compatibility path for the old callback signature.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At ggml/src/ggml-backend-impl.h, line 148:
<comment>When an older dynamically loaded backend is used, the loader still accepts API version 2 even though `profile` now has a different function type. Bump the backend API version or add an explicit compatibility path for the old callback signature.</comment>
<file context>
@@ -145,7 +145,7 @@ extern "C" {
void (*reset) (ggml_backend_t backend);
// (optional) print backend-specific profiling info
- void (*profile) ();
+ void (*profile) (ggml_backend_t backend);
};
</file context>
There was a problem hiding this comment.
Same ABI-version gap as the other comment on this line - agreed it's real, not fixing it tonight. graph_reserve/buffer_size/reset/profile were all added to ggml_backend_i without bumping GGML_BACKEND_API_VERSION (still 2), in an already-merged PR (#158) that ollama's split-binary boundary depends on. Bumping the version now is a real decision about compatibility with whatever's already built against version 2 on the ollama side - not something to do as a side effect of this PR.
| For this PR type, scope review to only: | ||
| - `consolidated-patch.patch` at the repo root — every Tsavorite-specific change, as one | ||
| patch file. This is the actual diff to read. | ||
| - `UPSTREAM_BASE_COMMIT` at the repo root — the upstream SHA this sync vendored forward |
There was a problem hiding this comment.
P3: This added line violates the repository's ASCII-only documentation rule. Replace the em dash with an ASCII hyphen.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/copilot-instructions.md, line 16:
<comment>This added line violates the repository's ASCII-only documentation rule. Replace the em dash with an ASCII hyphen.</comment>
<file context>
@@ -13,6 +13,10 @@ history landing via the version bump — **do not review it file-by-file**.
For this PR type, scope review to only:
- `consolidated-patch.patch` at the repo root — every Tsavorite-specific change, as one
patch file. This is the actual diff to read.
+- `UPSTREAM_BASE_COMMIT` at the repo root — the upstream SHA this sync vendored forward
+ to and that `consolidated-patch.patch` was regenerated against. Check it matches the
+ commit named in the PR title/description; a mismatch here means the patch may not
</file context>
| - `UPSTREAM_BASE_COMMIT` at the repo root — the upstream SHA this sync vendored forward | |
| - `UPSTREAM_BASE_COMMIT` at the repo root - the upstream SHA this sync vendored forward |
There was a problem hiding this comment.
Leaving this one - the rest of this same file already uses em dashes throughout (lines 11, 14, 20, 25, 33, all pre-existing), so changing only my added line would make it inconsistent with the file's own established style rather than fixing anything. If there's an actual desire to convert the whole file to ASCII hyphens that's a one-line sed across the file, happy to do that as its own pass, but not singling out my line.
…8-llama-cpp-sync Same content as jira-2258-llama-cpp-sync commits 26ce0bd/9bc391873/ f491a53/8d592336c, ported here so this review-aid diff stays in sync: - CMakeLists.txt: move FPGA rpath-link to a single global add_link_options() call, applying to every target via tsi-pkg-build.sh or the manual cmake -B build-fpga flow (the earlier per-target-block removal fixed the former but broke the latter) - tsi-pkg-build.sh: revert a dangerous global set -e (verified empirically it can terminate the calling shell and skip cleanup() when sourced) - README.md/docs/build.md: fix Quick Build docs (Option 1/3's exported env vars are silently discarded by parse_args(), which unsets them on every invocation) and soften an overstated sourced-only claim - tools/cli/cli-context.cpp: fix llama-cli hanging forever on any non-interactive invocation (piped/redirected output, no TTY) -- exactly how model-rerun.py invokes it. Pure upstream code, never exercised before since llama-cli was never buildable under Tsavorite until this sync's build-exclusion fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="consolidated-patch.patch">
<violation number="1" location="consolidated-patch.patch:12456">
P1: When the user sends Ctrl-D on an empty prompt, `readline_advanced()` returns an empty buffer without setting `feof(stdin)`, so this condition is false and `cli_context::run()` continues prompting indefinitely. Propagate the readline end-of-stream result through `read_input()` instead of relying only on the C stream EOF flag.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| @@ -0,0 +1,12649 @@ | |||
| diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS | |||
There was a problem hiding this comment.
P1: When the user sends Ctrl-D on an empty prompt, readline_advanced() returns an empty buffer without setting feof(stdin), so this condition is false and cli_context::run() continues prompting indefinitely. Propagate the readline end-of-stream result through read_input() instead of relying only on the C stream EOF flag.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At consolidated-patch.patch, line 12456:
<comment>When the user sends Ctrl-D on an empty prompt, `readline_advanced()` returns an empty buffer without setting `feof(stdin)`, so this condition is false and `cli_context::run()` continues prompting indefinitely. Propagate the readline end-of-stream result through `read_input()` instead of relying only on the C stream EOF flag.</comment>
<file context>
@@ -12404,6 +12426,39 @@ index 8449cdbaf..362cda14b 100644
++ // through llama-cli, previously untested since llama-cli was never
++ // buildable under GGML_TSAVORITE before this sync.
+ if (buffer.empty()) {
++ if (std::feof(stdin)) {
++ break;
++ }
</file context>
There was a problem hiding this comment.
Same fix as the cli-context.cpp comment - see that reply. Patch regenerated to reflect it.
Same content as jira-2258-llama-cpp-sync@249651fdc: - cli-context.cpp: isatty()-based cross-platform EOF fix, replacing the feof(stdin) check that missed Windows' ReadConsoleInputW path - CMakeLists.txt: honor TOOLBOX_DIR (CMake var or env var) before falling back to deriving it from MLIR_COMPILER_DIR - README.md/docs/build.md: corrected inaccurate claim about what sourcing tsi-pkg-build.sh's cleanup trap actually restores Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
Empty-parens function declaration/definition means "unspecified arguments" in C, not "no arguments" - gcc's -Werror=strict-prototypes correctly flags this. This predates the sync (introduced back in 6ef553c) but was never caught since our own posix/FPGA builds use a C++ toolchain throughout; upstream's plain 'ubuntu'/'windows' CI jobs build ggml as C and fail outright on it. Fixed by making both the declaration and definition explicit: ggml_backend_cleanup(void).
A non-default TOOLBOX_DIR only changed the FPGA link/rpath-link lib root, not the shared toolbox include_directories() root -- so setting TOOLBOX_DIR to point at a different toolbox build would link against that build's libs while still compiling against the default build's headers, a real header/library version-mismatch hazard. Hoisted the TOOLBOX_DIR-vs-env-vs-derived resolution into a single TSAVORITE_TOOLBOX_ROOT variable computed once, ahead of the fpga/posix branch, and pointed both the link path and include_directories() at it. Default (no override) behavior is unchanged, verified via full posix and FPGA rebuilds.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="CMakeLists.txt">
<violation number="1" location="CMakeLists.txt:87">
P2: Fresh upstream bootstraps do not receive this fix: `apply_consolidated_patch()` applies `consolidated-patch.patch`, whose `CMakeLists.txt` hunk still uses the old link-path logic and default include path. Regenerate `consolidated-patch.patch` so custom `TOOLBOX_DIR` builds reproduce this change.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
| # point at the same toolbox install (same TOOLBOX_DIR override, if any) -- | ||
| # otherwise a non-default TOOLBOX_DIR would link against one toolbox build | ||
| # while compiling against another's headers. | ||
| if (DEFINED TOOLBOX_DIR AND NOT "${TOOLBOX_DIR}" STREQUAL "") |
There was a problem hiding this comment.
P2: Fresh upstream bootstraps do not receive this fix: apply_consolidated_patch() applies consolidated-patch.patch, whose CMakeLists.txt hunk still uses the old link-path logic and default include path. Regenerate consolidated-patch.patch so custom TOOLBOX_DIR builds reproduce this change.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CMakeLists.txt, line 87:
<comment>Fresh upstream bootstraps do not receive this fix: `apply_consolidated_patch()` applies `consolidated-patch.patch`, whose `CMakeLists.txt` hunk still uses the old link-path logic and default include path. Regenerate `consolidated-patch.patch` so custom `TOOLBOX_DIR` builds reproduce this change.</comment>
<file context>
@@ -79,6 +79,18 @@ if (GGML_TSAVORITE)
+ # point at the same toolbox install (same TOOLBOX_DIR override, if any) --
+ # otherwise a non-default TOOLBOX_DIR would link against one toolbox build
+ # while compiling against another's headers.
+ if (DEFINED TOOLBOX_DIR AND NOT "${TOOLBOX_DIR}" STREQUAL "")
+ set(TSAVORITE_TOOLBOX_ROOT "${TOOLBOX_DIR}")
+ elseif (DEFINED ENV{TOOLBOX_DIR} AND NOT "$ENV{TOOLBOX_DIR}" STREQUAL "")
</file context>
There was a problem hiding this comment.
This one is stale - the review run here caught the window between the CMakeLists.txt fix and the regenerate-patch commit that followed it. consolidated-patch.patch already has TSAVORITE_TOOLBOX_ROOT in the current HEAD (confirmed via grep), so a fresh upstream bootstrap does get this fix. I regenerate the patch as a matching follow-up commit after every CMakeLists.txt change in this PR for exactly this reason.
The previous fix for llama-cli's non-interactive-stdin infinite loop checked isatty() once up front and treated any empty buffer as EOF when non-interactive. That conflated two different things: a genuine end-of-input (Ctrl+D, closed pipe) and an ordinary blank line that happens to appear in piped/redirected input -- both produce an empty buffer after trimming, so a blank line embedded mid-stream caused llama-cli to exit early instead of continuing to read the remaining lines. readline_advanced() already tracked this distinction internally via its local end_of_stream flag, it just never surfaced it. Threaded an optional bool* eof out-param through console::readline() -> readline_simple()/readline_advanced() -> user_turn::read_input() -> cli_context::run(), set true only on genuine getline() failure or Ctrl+D/WEOF, never for a successfully-read empty line. The interactive loop now breaks on eof, not on an empty buffer, which also makes the isatty() heuristic unnecessary -- removed it entirely. Verified: fast single-shot -p sanity run still exits cleanly, and piped multi-line input with an embedded blank line now correctly processes every line and only exits at the real end of the stream, on both posix and FPGA rebuilds.
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="common/console.cpp">
<violation number="1" location="common/console.cpp:1051">
P2: When simple I/O reads a final line without a trailing newline, `std::getline` has already reached EOF but this reset leaves `eof` false. Propagate `std::cin.eof()` or `std::wcin.eof()` after a successful read so piped input does not trigger an extra prompt and read.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
| static bool readline_simple(std::string & line, bool multiline_input) { | ||
| static bool readline_simple(std::string & line, bool multiline_input, bool * eof) { | ||
| if (eof) { | ||
| *eof = false; |
There was a problem hiding this comment.
P2: When simple I/O reads a final line without a trailing newline, std::getline has already reached EOF but this reset leaves eof false. Propagate std::cin.eof() or std::wcin.eof() after a successful read so piped input does not trigger an extra prompt and read.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At common/console.cpp, line 1051:
<comment>When simple I/O reads a final line without a trailing newline, `std::getline` has already reached EOF but this reset leaves `eof` false. Propagate `std::cin.eof()` or `std::wcin.eof()` after a successful read so piped input does not trigger an extra prompt and read.</comment>
<file context>
@@ -1040,15 +1040,24 @@ namespace console {
- static bool readline_simple(std::string & line, bool multiline_input) {
+ static bool readline_simple(std::string & line, bool multiline_input, bool * eof) {
+ if (eof) {
+ *eof = false;
+ }
#if defined(_WIN32)
</file context>
There was a problem hiding this comment.
Checked this against actual behavior - functionally it is not a bug: on the next call, getline() fails against the already-exhausted stream, eof correctly comes back true, and the loop breaks and exits cleanly (verified: piping a final line with no trailing newline into llama-cli still processes the line and exits 0, no hang, no spin).
What you are pointing at is real but cosmetic: one extra bare prompt line gets printed before the loop discovers EOF and exits. That is not unique to the missing-trailing-newline case though - it happens identically for input that DOES end with a newline too, since you cannot know a stream has ended until you attempt a read and get the failure back. Fixing it fully would mean restructuring read_input() to defer printing the prompt until a read has already succeeded, which crosses the layer boundary between console.cpp's return value and cli-context.cpp's prompt logic - a real change, but for a cosmetic artifact rather than a correctness issue, so I am leaving it as-is rather than expanding scope on this pass.
A relative TOOLBOX_DIR would resolve against whatever working directory the compiler and linker each happen to run from at build time, which need not be the same directory or CMAKE_SOURCE_DIR -- so the include and link paths derived from it could silently diverge again despite sharing the same TSAVORITE_TOOLBOX_ROOT variable. get_filename_component(... ABSOLUTE BASE_DIR CMAKE_SOURCE_DIR) resolves it once, consistently, for all three cases (explicit TOOLBOX_DIR, environment TOOLBOX_DIR, and the MLIR_COMPILER_DIR- derived default). No behavior change for the default (already absolute) case, verified via full posix and FPGA rebuilds.
gemma4-validation-logs.zip
posix-validation-logs.zip
tsisim-validation-logs.zip
This PR diffs against
upstream-1f368f354-baseline, a branch pointing at the exactupstream commit (
1f368f354d9edcfea9fd6a1e0989b3e7335a050f) thatconsolidated-patch.patchis generated against. Since both branches share that sameupstream tree, this diff shows only the ~92 files this sync actually changes: the
Tsavorite backend (
ggml/src/ggml-tsavorite/), build config (tsi-pkg-build.sh,tsavorite-model-deployment.yaml, CMake wiring), new regression tests, and theJIRA-2258 validation docs/logs. Companion branch
jira-2258-llama-cpp-sync(PR #162)carries the same content against
origin/masterdirectly, which is why that PR shows~3150 changed files instead — almost all of it is upstream's own already-reviewed
commit history landing via the version bump, not new content.
Why this sync, and why now
origin/masterlast touched upstream at51abc96bdc(2025-09-16). This sync's target,1f368f354(2026-08-13), is ~11 months of upstreamggml-org/llama.cpphistory later.That gap — not a preference for a different branch or approach — is why this lands as
one large, version-bump-style sync consolidating every Tsavorite-specific change
accumulated since 2025-09-16 into one patch file (
consolidated-patch.patch), ratherthan as a normal incremental PR. The stated core motivation was Gemma 4 architecture
support, which didn't exist at all on the pre-sync fork — see the Gemma 4 findings in
docs/jira-2258/gemma4-validation-logs/GEMMA4-VALIDATION-SUMMARY.md.cubic-dev-ai review remediation (2026-08-26)
All 54 cubic-dev-ai comments across two review passes replied to and resolved
(40 in the first pass, 14 more in a second pass triggered by pushing the first round's
fixes — cubic re-reviews on every push).
STREQUAL/$ENV{}bugs (the kind that breakthe whole
cmakeconfigure, not just the guarded branch), missingGGML_APIonggml_backend_cleanup(), an inverted log-level filter inggml_log_internal(), aNaN/Inf-vs-tolerance check that silently passed bad kernel output, backend-cleanup
ordering fixed via a
BackendCleanupGuardRAII pattern (tools/cli/cli.cpp,tools/completion/completion.cpp,tools/server/server.cpp), the.profilebackend callback missing its
backendparameter,api_versionnever set fornon-OLLAMA
GGML_BACKEND_DLbuilds, a duplicate perf-summary print incommon_perf_print(), a regex inmodel-rerun.pymatching the wrong log line,LLAMA_OPENSSLsilently defaulting OFF,ggml-tsavorite.hshipping a public headerthat depended on an uninstalled private header, plus several doc fixes (missing
SDK_VERSIONexports, a nonexistentTSI-VERSIONsetting, missingUPSTREAM_BASE_COMMITfrom the review-scope doc)..gitmodules/ggml-tsi-kernelgitlink flagged asmismatched — confirmed valid via
git ls-tree HEAD, no fix needed.llama-cli/llama-serverwere never built at all underGGML_TSAVORITE=ON,in posix or FPGA, since this sync landed — a nesting bug in
tools/CMakeLists.txt(the old fork built
main,cli's pre-refactor name, outside the Tsavoriteexclusion guard; this sync's port put the new
cli/serversubdirectoriesinside it by accident). This silently broke
model-rerun.py(added in thissame PR), which calls
build-posix/bin/llama-cli. Fixed by movingui/cli/server/mtmdout from under the exclusion, and fixing the FPGA.tzpackagingstep (it only knew to copy
llama-completion) to include the newly-buildablebinaries too.
CMAKE_FIND_ROOT_PATHis a 4-entry CMake list (the ARM toolchain's own sysrootsearch path), not a scalar. The first attempt at a cubic-suggested rpath-link fix
used it as one anyway, which corrupted the FPGA link
(
ld: ... Is a directory) — caught by actually rebuilding, not just trusting agreen
cmake configure. Fixed by moving the rpath-link flags to a singleadd_link_options()call in the top-levelCMakeLists.txt, so it applies toevery target via
tsi-pkg-build.shor the manualcmake -B build-fpga ...flow documented in the README/
docs/build.md.llama-clihung forever on any non-interactive invocation (piped/redirectedoutput, no controlling TTY — exactly how
model-rerun.py, added in this same PR,invokes it via
subprocess.check_output()).cli-context.cpp's main loop, oncethe initial
-pprompt is consumed, callsread_input()for the next turn andtreats an empty returned buffer as "blank line, keep waiting" — correct for a real
interactive TTY session, but on a non-TTY stdin
getwchar()hits EOF instantly andforever, so the loop spins at ~100% CPU rewriting the
>prompt indefinitely,never terminating. This is pure upstream code (
cli-context.cppisn't part of theTsavorite patch) that was simply never exercised before tonight, since
llama-cliwas never buildable under Tsavorite until bug 1 above was fixed. Caught by actually
running the freshly-built binary non-interactively, not just confirming it linked.
Fixed by checking
feof(stdin)before deciding to continue vs. break out of theloop — distinguishes genuine end-of-input from an interactively-submitted blank
line, which were previously indistinguishable from the loop's point of view.
had added a global
set -etotsi-pkg-build.shto make a narrow error-propagationgap more reliable. cubic correctly flagged that as worse than the problem it solved —
verified empirically: sourcing this script with
set -eactive and hitting anyfailing command (not just inside
die()) terminates the calling shell, not justthis script, and skips the cleanup trap entirely. Reverted; the narrower gap it was
trying to close is left as a documented follow-up instead.
drive-by fix without dedicated regression testing would be reckless — flagged in the
GitHub replies for a deliberate follow-up decision, not silently dropped):
ggml_backend_igained new callbacks (PR @FIR-2216 - llama.cpp: expose ggml perf-summary symbols across ollama's split-binary backend boundary #158, already merged, ollama'ssplit-binary boundary depends on it) without bumping
GGML_BACKEND_API_VERSION(still
2) — a real ABI risk for any old dynamically-loaded backend.so.ggml-backend.cpp's view-op scheduling forcing both a view node and its sourceonto the CPU backend is not a new bug — it's the deliberate fix from @FIR-1856 - llam.cpp:Revert Graph Split Optimization Due to Introduce… #120 (the
revert of the graph-split optimization that crashed Qwen and hid OPU usage, @FIR-1834 - Reduce GGML Graph Splits for Tsavorite Backend — Enable L… #118).
struct ggml_tensor's size/layout changing underGGML_PERF/GGML_PERF_RELEASE/GGML_PERF_DETAIL(also from @FIR-2216 - llama.cpp: expose ggml perf-summary symbols across ollama's split-binary backend boundary #158) is safe inside this repo's own build, but areal hazard for external consumers of the installed public
ggml.h+libggml.sothat don't define the same flag.Full rebuild verification after every round: posix + FPGA both clean (0 errors),
llama-cli/llama-server/llama-completionall present and packaged intotsi-ggml-0.4.24.tz.Posix re-validation (2026-08-26, post-remediation)
None of the fixes above touch compute kernels, but re-ran the full model set anyway
since real bugs were found and fixed along the way:
tinyllama-vo-5m-para.ggufMy cat's name is Tim. HeGemma3-270M-F32.ggufMy cat's name is "Cat"Tiny-Llama-v0.3-FP32-1.1B-F32.ggufMy cat's name is Luna.Llama3.2:1B-1.2B-F32.ggufMy cat's name is "Bella"qwen2-0_5b-instruct-q5_k_m.ggufMy cat's name is Muffy. SheQwen2.5-0.5B-Q4_K_M.ggufMy cat's name is Zane. HeGemma4-e2b-5.1B-Q4_K_M.ggufwrong number of tensors), independently confirmed against ggml-org/llama.cpp#27349Gemma4-12b-Q4_K_M.ggufMy cat's name is **"Luna0(matches the already-documented Tsavorite-vs-CPU formatting divergence, not corruption)7/8 models pass cleanly with zero warnings; the 8th (
Gemma4-e2b) fails identically to before this PR's changes, a pre-existing upstream loading bug unrelated to the Tsavorite backend (see the Gemma 4 investigation this PR already contains for detail).Raw logs gzipped and attached to this PR description rather than committed to the
repo tree.
llama-clismoke-tested end to end for the first time (it was neverbuildable under Tsavorite before this fix): clean run,
user_dram_size_gb=16correctly read, generated"I'm, exited cleanly in 6s (previously spun forever on any non-interactive invocation -- see thecli-context.cppfix above).Review this PR's file-by-file diff for the actual code review of the ~92 files that
matter. Once approved here, the same content lands via #162.
Summary by cubic
Review-only branch for JIRA-2258 that diffs against the exact upstream baseline
consolidated-patch.patchis generated from, exposing only the ~93 files this sync actually changes instead of the ~3150-file diff against master. Do not merge this branch; the real merge isjira-2258-llama-cpp-sync.What changed
consolidated-patch.patch, withUPSTREAM_BASE_COMMITpinning its regeneration base.ggml/src/ggml-tsavorite/), build tooling (tsi-pkg-build.sh,tsavorite-model-deployment.yaml, CMake wiring), repro tools underexamples/simple/, and amodel-rerun.pyvalidation harness.GGML_TSAVORITE(they previously never built).add_link_options()call and routesTOOLBOX_DIRoverrides (normalized to an absolute path) through oneTSAVORITE_TOOLBOX_ROOTfor both include and link roots.set -efromtsi-pkg-build.sh; sourcing it could kill the caller's shell.bool* eofout-param; the loop breaks on genuine EOF (getline failure/Ctrl+D/WEOF), and the earlierisatty()heuristic that exited early on embedded blank lines is removed.ggml_backend_cleanup()explicit(void)to fix an upstream-Werror=strict-prototypesCI failure.GGML_PERF-guarded op profiling with a dedicated Tsavorite summary, aGGML_LOG_LEVEL_TSAVORITElog level, and backend profile/cleanup hooks.GGML_TSAVORITECMake guards.user_dram_size_gbdeployment default from 8 to 16.docs/jira-2258/: 4/4 posix models are byte-identical old vs new and Gemma 4 12b loads; raw per-run logs are attached to this PR instead of committed.Written for commit 1b3aaa1. Summary will update on new commits.