Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
747868a
the portable-tier plan: dasLLAMA without the JIT crowns in three stag…
borisbat Sep 4, 2026
19bc49a
the four rulings owed from the is_nan arc: tests-cpp/REVIEW.das gains…
borisbat Sep 4, 2026
3d71cb2
stage 0 of the portable tier: the kernel gates the portable path need…
borisbat Sep 4, 2026
efa727c
test_q8q8_family: the s16 plane's group3 form is bit-exact against th…
borisbat Sep 4, 2026
305ed7d
stage 1, wave 1: f16_cvt moves to daslib (37 requires follow; the JIT…
borisbat Sep 4, 2026
72f5201
stage 1, wave 2: the six tune annotations become daslib shells (dasli…
borisbat Sep 5, 2026
f5bdfe5
stage 1, wave 3: aarch64_neon and x64_avx move to daslib beside f16_c…
borisbat Sep 5, 2026
c0dd2c2
run.das --no-tune runs its children with the image rail off: the refe…
borisbat Sep 5, 2026
64d24b0
math_gen's [init] guards its one framework call (tune_suppress_mint) …
borisbat Sep 5, 2026
8a906b5
the aarch64 SDOT and SMMLA tables gate on DotProd and i8mm, not the a…
borisbat Sep 5, 2026
9b7be37
stage 2 of the portable tier: dasllama_aot, the daslang host with the…
borisbat Sep 5, 2026
d4bfb51
typeinfo module_exists(X): the compiling program's own library, so a …
borisbat Sep 5, 2026
76d92d9
the llvm witness module: "no LLVM" is the build configuration's word,…
borisbat Sep 5, 2026
7b414ba
the plan's stage 3 drops the Vulkan-guard item: the tier already hang…
borisbat Sep 5, 2026
3bc34cf
no tuning under a cross target, by construction: get_target_triple / …
borisbat Sep 5, 2026
49c948d
stage 3: dasLLAMA runs on WASM64 - the dasllama_aot target builds in …
borisbat Sep 5, 2026
e0b3e57
the web build's embedded source trees exclude build residue: _aot_gen…
borisbat Sep 5, 2026
822577f
the plan's stage 3 carries the artifact breakdown after the embed exc…
borisbat Sep 5, 2026
362d5f0
examples/dasLLAMA/speak.das: speak a line locally through the TTS fac…
borisbat Sep 5, 2026
f523c76
the tune sidecar's module-cache pin moves out of the shared manifest …
borisbat Sep 5, 2026
5e69cc1
the node driver sets the engine's knobs in preRun - emscripten builds…
borisbat Sep 5, 2026
4c435a8
the storyteller: stories15M writes a children's story on screen two t…
borisbat Sep 5, 2026
c71e829
the storyteller in the browser: its own web shell fetches the four mo…
borisbat Sep 5, 2026
8ad4747
a TTS image serves without its gguf: the family's driver data (Kitten…
borisbat Sep 5, 2026
90896ef
the release rail forwards an app's own release_emcc_arg lines (only m…
borisbat Sep 5, 2026
c6dc5e6
the int8 dot on wasm: the JIT's signed idot family lowers to i32x4.re…
borisbat Sep 5, 2026
7bd180f
the American-only phoneme pack tts_g2p_en_us.bin (10.3 MB against the…
borisbat Sep 5, 2026
d3b787e
the TTS set's Hugging Face pin moves to the commit that carries tts_g…
borisbat Sep 5, 2026
6051be3
the layout stamp follows the rebase onto the Q8 token table: version …
borisbat Sep 5, 2026
3b84f84
the runner census after the rebase: test_chat sits in the stocked lis…
borisbat Sep 5, 2026
ea564c5
dasllama.io gets an examples page: the storyteller card opens the was…
borisbat Sep 5, 2026
07a4164
news on both sites: dasLLAMA runs in the browser - the storyteller co…
borisbat Sep 5, 2026
fb294df
the dasLLVM descriptor census admits the witness module registration:…
borisbat Sep 5, 2026
df4c579
the comment harvest and the formatter pass over the arc: four rules a…
borisbat Sep 5, 2026
8ca7b8f
the review-round fix batch: the framework is optional everywhere a po…
borisbat Sep 5, 2026
5dae7d7
the gate residue of the fix batch: the two rules the folder gates par…
borisbat Sep 5, 2026
e1bc2b1
the exe-rail residue: the llvm descriptor registers the llvm/daslib p…
borisbat Sep 5, 2026
e78657d
the exe lint rail retires: an exe carries the host's module paths wit…
borisbat Sep 5, 2026
1ccf6cc
get_target_architecture_name's reference text lists what the function…
borisbat Sep 5, 2026
588aa9c
the two remaining daslib-side doors to llvm/ spell the witness guard:…
borisbat Sep 5, 2026
ba6f3f2
the descriptor path gate is withdrawn and the JIT emitter pin re-stam…
borisbat Sep 5, 2026
01ca6a2
the daspkg name guard is an allowlist: letters, digits, underscore, d…
borisbat Sep 6, 2026
b1baf4b
the preview server decides the /examples/ sandbox by containment, not…
borisbat Sep 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ lane's platform, in its PR body or commit message; a green run of that lane on t
commit is that evidence.** A check that fails for a non-defect turns a green branch red for
everyone.

**A step in `pages.yml` that names the deployed games spells the list as a `for g in <ids>; do`
loop, never inline.** `examples/games/REVIEW.das` (repo root) reads the deployed list from
those loops; an inline list beside a surviving loop is one nothing cross-checks.
**A step in `pages.yml` that names more than one id under `examples/games/` spells them as a
`for g in <ids>; do` loop, never inline.** `examples/games/REVIEW.das` (repo root) reads the
deployed list from those loops; an inline list beside a surviving loop is one nothing
cross-checks. An example outside `examples/games/` (a graphics showcase, a dasLLAMA app) is not
on that list and is named on its own.
4 changes: 2 additions & 2 deletions .github/workflows/extended_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ jobs:
ci/nano_arm_build.sh "$BIN/daslang"

- name: "Build standalone executables"
# core: the formatter and lint steps below run the das-fmt / das-lint exes this builds
# core: the formatter step below runs the das-fmt exe this builds; das-lint is built so the
# shipped lint.exe is proven to compile (the bundle smoke test runs it on daslib)
if: matrix.role != 'modules'
run: |
set -eux
Expand Down Expand Up @@ -403,7 +404,6 @@ jobs:
# outside the PR, and >=16 files parallelize into per-file ledgers - both produce
# false stales. The nightly whole-tree -j 1 pass owns staleness.
$BIN/daslang ./utils/lint/main.das -- "${CHANGED[@]}" --quiet --disable LINT019
$BIN/das-lint.exe "${CHANGED[@]}" --quiet --disable LINT019

- name: "Run ast-verify on changed .das files"
if: matrix.role != 'modules'
Expand Down
42 changes: 41 additions & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ jobs:
# The workflow file itself is a build input (it carries the configure flags
# for web/build64 below), so hash it too — a change to the build steps must
# miss a stale cache rather than skip the rebuild and reuse old archives.
key: wasm-${{ runner.os }}-${{ hashFiles('.github/workflows/pages.yml', 'CMakeLists.txt', 'web/CMakeLists.txt', 'web/stage_playground_imgui_samples.cmake', 'src/**', 'include/**', 'modules/**', 'daslib/**', 'utils/daslang/**', 'utils/daspkg/**', 'examples/games/**', 'examples/graphics/**', 'examples/pathTracer/**', 'web/examples/ui/samples/**', 'tutorials/**', 'dastest/**') }}
key: wasm-${{ runner.os }}-${{ hashFiles('.github/workflows/pages.yml', 'CMakeLists.txt', 'web/CMakeLists.txt', 'web/stage_playground_imgui_samples.cmake', 'src/**', 'include/**', 'modules/**', 'daslib/**', 'utils/daslang/**', 'utils/daspkg/**', 'examples/games/**', 'examples/graphics/**', 'examples/pathTracer/**', 'examples/dasLLAMA/storyteller/**', 'web/examples/ui/samples/**', 'tutorials/**', 'dastest/**') }}

# Host daslang — one games-capable build (dasLLVM for cross-compile + dasGlfw
# + dasOpenGL shared modules for the games) that serves BOTH das2rst and the
Expand Down Expand Up @@ -316,6 +316,18 @@ jobs:
echo "WARNING: physarum_lab wasm build failed — its examples card will be skipped this deploy."
fi

# 7. dasllama.io/examples storyteller — dasLLAMA itself compiled to wasm64 (the story
# model + KittenTTS, both served as prepared .dlim images the dasllama.io stage step
# downloads from the rolling `dasllama-web` release). Its .das_package turns the GPU
# modules off, so the host needs no Metal/Vulkan. Non-fatal like the games; the
# dasllama.io stage step stages the card's page only when all three outputs exist.
if ./bin/daslang utils/daspkg/main.das -- \
release wasm --root examples/dasLLAMA/storyteller --out "$REPO/web/output64/examples"; then
echo "storyteller wasm build OK"
else
echo "WARNING: storyteller wasm build failed — the dasllama.io storyteller page will be a placeholder this deploy."
fi

- name: "Compile-gate the curated playground samples"
# The per-sample wasm64 builds used to live here and doubled as the proof
# that every curated sample still compiles. They now build on demand
Expand Down Expand Up @@ -555,6 +567,8 @@ jobs:
fi

- name: "Stage dasllama.io for deployment"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # gh release download of the browser examples' model sets
run: |
set -eux
mkdir -p _site_dasllama/files
Expand All @@ -566,7 +580,33 @@ jobs:
python3 site-dasllama/test_metadata.py

cp site-dasllama/index.html _site_dasllama/
cp site-dasllama/examples.html _site_dasllama/
cp site-dasllama/stories.html _site_dasllama/

# The browser examples: the wasm64 build from step 7 above plus its model set from the
# rolling `dasllama-web` release (prepared .dlim images + the phoneme packs, ~70 MB -
# build artifacts like the tutorial MP4s, never in git; re-minted and re-uploaded with
# --clobber on every IMAGE_VERSION bump). Served same-origin, so the page needs no CORS;
# the Caddy vhost adds the isolation headers under /examples/ (caddy.snippet). A missing
# build or set stages a placeholder page, so the card never 404s.
mkdir -p _site_dasllama/examples/storyteller
if [ -f web/output64/examples/storyteller/storyteller.html ] \
&& [ -f web/output64/examples/storyteller/storyteller.js ] \
&& [ -f web/output64/examples/storyteller/storyteller.wasm ] \
&& gh release download dasllama-web --repo GaijinEntertainment/daScript \
--dir _site_dasllama/examples/storyteller/models --clobber \
&& test -s _site_dasllama/examples/storyteller/models/stories15M.dlim \
&& test -s _site_dasllama/examples/storyteller/models/kitten-nano.dlim \
&& test -s _site_dasllama/examples/storyteller/models/tts_g2p_en_us.bin \
&& test -s _site_dasllama/examples/storyteller/models/tts_postag.bin; then
cp web/output64/examples/storyteller/storyteller.html _site_dasllama/examples/storyteller/
cp web/output64/examples/storyteller/storyteller.js _site_dasllama/examples/storyteller/
cp web/output64/examples/storyteller/storyteller.wasm _site_dasllama/examples/storyteller/
else
echo "WARNING: storyteller build or model set incomplete — staging a placeholder so the card doesn't 404."
rm -rf _site_dasllama/examples/storyteller/models
printf '%s' '<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Storyteller — building</title><style>html,body{margin:0;height:100%}body{background:#12101a;color:#d6cfbf;font-family:ui-monospace,Menlo,Consolas,monospace;display:flex;align-items:center;justify-content:center;text-align:center;padding:24px}p{max-width:30rem;line-height:1.6}</style></head><body><p>This example is being rebuilt and will be available shortly.</p></body></html>' > _site_dasllama/examples/storyteller/storyteller.html
fi
mkdir -p _site_dasllama/stories
cp -R site-dasllama/stories/. _site_dasllama/stories/
cp site-dasllama/ladder.html _site_dasllama/
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,7 @@ if (NOT ${DAS_TESTS_DISABLED})
# AOT examples are enabled — gate the inclusion accordingly.
if(NOT ${DAS_AOT_EXAMPLES_DISABLED})
include(examples/pathTracer/CMakeLists.txt)
include(examples/dasLLAMA/CMakeLists.txt)
endif()
if(NOT ${DAS_AOT_EXAMPLES_DISABLED} AND NOT (WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4))
include(tests/aot/CMakeLists.txt)
Expand Down
22 changes: 22 additions & 0 deletions daslib/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,25 @@ Three companions carry a concern each; a section number is unique across all fou

- **`_table_index_and_init` exists for infer's `default_init_containers` rewrite of
non-store `tab[key]`** - it has no daslib call site and is not dead.

## 37. tune {#tune-shells-module-exists}

- **Every tune annotation - `[tune]`, `[tuned]`, `[tune_perm]`, `[tune_scope]`, `[tune_policy]`,
`[llvm_code]` - registers HERE and nowhere else, as a shell that forwards to the framework in
`llvm/daslib/llvm_tune` when that module is visible and answers "unchanged" when it is not.** A
module's macro state is per module, so a shell and the `[tune_scope]` bank it reads have to
share one macro context; `tune_status` and `log_tune_status` are shells of the same kind.
- **The shells decide with `typeinfo module_exists(llvm_tune)`, a pair with the trait's C++ half
in `src/ast/ast_infer_type.cpp` (`module_exists`): visible from the compiling module, which is
what the `require ?llvm llvm/daslib/llvm_tune public` line above them decided.** Nothing fails
when the two sides drift - `tests/language/optional_require.das` pins the trait's visibility
half on fixtures, and `tests/daslib/test_tune_shells.das` is tier-agnostic by design - so the pair
is recorded here: a trait that answered off the process registry instead would take the
framework arm inside a tool's nested compile, where the framework is not mounted.
- **The `llvm/daslib/*` files resolve in every build that carries `modules/dasLLVM/`; only the
witness decides what `?llvm` and `module_exists(llvm_tune)` answer.** The framework's das files
compile without their C++ module, so a direct `require llvm/daslib/llvm_tune` in a build without
dasLLVM compiles with the shells inert and no `<name>_variants()` registry - a program that
reads one is framework-only and says so with that direct require. `daslib/just_in_time` keeps
its direct require for the opposite reason: a static host that never registered the witness
still runs the JIT through the LLVM library, and the guard would switch it off.
14 changes: 14 additions & 0 deletions daslib/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,17 @@ a value.
marker annotation to the instance it finishes, and returns unchanged when it sees that marker.**
A chain of template ancestors delivers one copy of the annotation per level, so a macro without
the marker runs a second time over a structure it already rewrote.

**A diff that adds or renames a public intrinsic in `aarch64_neon.das`, `x64_avx.das` or
`f16_cvt.das` changes its row in the lookup table of `modules/dasLLVM/daslib/llvm_jit_intrin.das`
(repo root) that is gated on the CPU feature the instruction needs, in the same change.** The JIT
recognizes these calls by function name alone, so a missing row runs the portable fallback on
every target with every test green, and a row in a table gated on a weaker feature emits an
instruction the generic machine cannot select - the `tests/jit_tests` twins compare hardware
against a reference body and catch a wrong emitter, never a missing or misplaced one.

**A function in `aarch64_neon.das`, `x64_avx.das` or `f16_cvt.das` that is the wider- or
newer-tier variant of the same math another function in that file computes calls that function -
never a hand-written scalar loop.** A box whose CPU lacks the tier then runs the recognized
narrower path instead of scalar code. A tier function with no same-math sibling (`smmla`'s 2x8
by 8x2 shape) keeps its own fallback body.
27 changes: 14 additions & 13 deletions modules/dasLLVM/daslib/aarch64_neon.das → daslib/aarch64_neon.das
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ module aarch64_neon shared public
//
// Every function here computes the correct result on ANY target via its daslang body — so the
// interpreter, AOT, and non-ARM JIT builds all just run that body. On an aarch64 JIT target the
// LLVM JIT recognizes the call BY NAME (see g_aarch64_intrin_lookup in llvm_jit_intrin.das, gated
// on g_target_is_aarch64) and emits the hardware NEON instruction in place of the call. There is
// LLVM JIT recognizes the call BY NAME (the g_aarch64_*_intrin_lookup tables in llvm_jit_intrin.das,
// gated on the target arch and on the instruction's feature: TBL is baseline, SDOT needs DotProd,
// SMMLA needs i8mm) and emits the hardware NEON instruction in place of the call. There is
// nothing to annotate and nothing to require from the llvm module — the recognition is purely
// name-based at JIT codegen time, so the fallback runs verbatim everywhere the intrinsic isn't
// emitted. Callers therefore get the fast path for free on arm64 and stay correct elsewhere.
// emitted: a foreign arch, or a generic-CPU aarch64 exe whose baseline machine lacks the feature.
// Callers therefore get the fast path for free on arm64 and stay correct elsewhere.

//! Signed dot-product (`SDOT` / `@llvm.aarch64.neon.sdot`): load 16 int8 from each of `w` and `x`
//! (16-wide unaligned loads), multiply elementwise, and accumulate consecutive groups of 4 products
Expand Down Expand Up @@ -43,17 +45,16 @@ def sdot4_w(acc : int4; w : int4; x : int8 const?) : int4 {
var s3 = 0
unsafe {
for (e in range(4)) {
s0 += sxb(w.x, e) * int(x[e])
s1 += sxb(w.y, e) * int(x[4 + e])
s2 += sxb(w.z, e) * int(x[8 + e])
s3 += sxb(w.w, e) * int(x[12 + e])
s0 += sign_extend_byte(w.x, e) * int(x[e])
s1 += sign_extend_byte(w.y, e) * int(x[4 + e])
s2 += sign_extend_byte(w.z, e) * int(x[8 + e])
s3 += sign_extend_byte(w.w, e) * int(x[12 + e])
}
}
return acc + int4(s0, s1, s2, s3)
}

// sign-extend byte e (0..3, little-endian) of a packed int lane
def private sxb(lane : int; e : int) : int => (((lane >> (e * 8)) & 0xff) ^ 0x80) - 0x80
def private sign_extend_byte(lane : int; e : int) : int => (((lane >> (e * 8)) & 0xff) ^ 0x80) - 0x80

//! Byte table lookup of LOW nibbles (`TBL` / `vqtbl1q_s8(table, nib & 0x0f)`): each of 16 `nib`
//! bytes has its low nibble (masked to 0..15, never out of table) looked up in `table`; the 16
Expand Down Expand Up @@ -123,10 +124,10 @@ def sdot4_laneq_w(acc : int4; w : int4; x : int8 const?; lane : int) : int4 {
let x1 = int(x[b + 1])
let x2 = int(x[b + 2])
let x3 = int(x[b + 3])
r.x += sxb(w.x, 0) * x0 + sxb(w.x, 1) * x1 + sxb(w.x, 2) * x2 + sxb(w.x, 3) * x3
r.y += sxb(w.y, 0) * x0 + sxb(w.y, 1) * x1 + sxb(w.y, 2) * x2 + sxb(w.y, 3) * x3
r.z += sxb(w.z, 0) * x0 + sxb(w.z, 1) * x1 + sxb(w.z, 2) * x2 + sxb(w.z, 3) * x3
r.w += sxb(w.w, 0) * x0 + sxb(w.w, 1) * x1 + sxb(w.w, 2) * x2 + sxb(w.w, 3) * x3
r.x += sign_extend_byte(w.x, 0) * x0 + sign_extend_byte(w.x, 1) * x1 + sign_extend_byte(w.x, 2) * x2 + sign_extend_byte(w.x, 3) * x3
r.y += sign_extend_byte(w.y, 0) * x0 + sign_extend_byte(w.y, 1) * x1 + sign_extend_byte(w.y, 2) * x2 + sign_extend_byte(w.y, 3) * x3
r.z += sign_extend_byte(w.z, 0) * x0 + sign_extend_byte(w.z, 1) * x1 + sign_extend_byte(w.z, 2) * x2 + sign_extend_byte(w.z, 3) * x3
r.w += sign_extend_byte(w.w, 0) * x0 + sign_extend_byte(w.w, 1) * x1 + sign_extend_byte(w.w, 2) * x2 + sign_extend_byte(w.w, 3) * x3
}
return r
}
Expand Down
8 changes: 8 additions & 0 deletions daslib/daspkg.das
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct ReleaseSpec {
emcc_args : array<string> //!< extra emcc flags this module contributes to a `daspkg release wasm` link (e.g. "-sUSE_GLFW=3"); gathered from every referenced module
embed_paths : array<string> //!< "src@dst" embed pairs this module needs in the wasm MEMFS (e.g. a HUD font); gathered from every referenced module
web_shell : string //!< optional emcc `--shell-file` HTML for `release wasm`; empty = daslang's minimal canvas shell
wasm_disabled_modules : array<string> //!< host module folders (`dasvulkan`) kept unloaded on the `release wasm` cross-compile, so a guarded `require ?name` resolves as absent there
wasm_build_command : string //!< shell command that builds this EXTERNAL module's wasm archives (run with cwd = module dir); empty = in-tree module built by `daspkg build --wasm`
wasm_archives : array<string> //!< archives required by wasm link; build outputs are module-relative, SDK archives may be named from the staged wasm lib dir
requires_jit : bool //!< app is JIT-only (per-box [tune]/[llvm_code] kernels); a baked -exe would run broken, so `daspkg release` refuses it
Expand Down Expand Up @@ -212,6 +213,13 @@ def release_embed_file(src, dst : string) {
_release_spec.embed_paths |> push("{src}@{dst}")
}

//! Keep a host module (folder name, case-insensitive) out of the `release wasm` cross-compile:
//! it runs on the host, where a module with no wasm build still satisfies a guarded `require ?name`.
//! dashv is disabled by the rail; an app reaching vulkan, das_metal or das_accelerate names those.
def release_wasm_disable_module(name : string) {
_release_spec.wasm_disabled_modules |> push(name)
}

//! Choose the emcc `--shell-file` HTML wrapper for `release wasm`. Empty (the
//! default) ships daslang's minimal canvas-only shell. A site can point this at
//! its own shell (e.g. the forge canvas frame) for in-page embedding.
Expand Down
4 changes: 2 additions & 2 deletions modules/dasLLVM/daslib/f16_cvt.das → daslib/f16_cvt.das
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def f16_to_f32(h : uint) : float {
}
let sign = (h & 0x8000u) << 16u
var bits : uint
if (exp == 0x1Fu) { // inf / nan
if (exp == 0x1Fu) {
bits = sign | 0x7F800000u | (mant << 13u)
} else { // normal: rebias exponent 15 -> 127 (+112), widen mantissa 10 -> 23 bits
bits = sign | ((exp + 112u) << 23u) | (mant << 13u)
Expand All @@ -39,7 +39,7 @@ def f32_to_f16(f : float) : uint {
let bits = unsafe(reinterpret<uint>(f))
let sign = (bits >> 16u) & 0x8000u
let absb = bits & 0x7FFFFFFFu
if (absb > 0x7F800000u) { // nan -> quiet nan
if (absb > 0x7F800000u) {
return sign | 0x7E00u
}
if (absb >= 0x47800000u) { // inf, or >= 65536 (overflows past f16 max)
Expand Down
Loading
Loading