Releases: The-Mettle-Project/Mettle
Release list
Mettle v0.13.0
Second backend target, first-class closures, and a wave of new optimizer and
tooling work.
BREAKING CHANGE
- The
functionkeyword is nowfn. Existing sources usingfunctionwill not
compile; rename tofn. All docs and examples have been updated.
AArch64 backend (new target)
--emit-arm64compiles scalar Mettle to AArch64 ELF that runs under QEMU:
from-scratch instruction encoder, AAPCS64 ABI, and executable emit layer.- Direct
ir_aarch64backend plus a MIR->AArch64 lowering path with vreg
stack allocation and parameter homing. - Supported: pointers, arrays, narrow ints, full scalar floats, string
literals, and write-syscall I/O.
Closures and lambdas
- Anonymous
fn(...)lambda expressions. - Capturing closures with mutations that persist across calls.
- Cross-boundary closures and revived expression-calls.
- Closures and function pointers stored in and called from struct fields.
- A plain function or non-capturing lambda flows anywhere an
Fn(...)closure
type is expected.
Optimizer and IR
- Zero-run PGO (
--pgo): interpretsmain()at compile time to drive
hot-callee inlining and hotness-aware optimizer thresholds. - Tail-recursion elimination and layout factorization passes.
- New prefetch and if-conversion IR passes.
- ML-guided IR optimization pass (
--ml-opt). - Per-pass translation validation with automatic quarantine of unsound passes.
Compile-time testing and diagnostics
@testfunctions withmettle test(interpreted, assert diagnostics, leak
detection) andmettle trace.mettle explaincommand, new warnings, richer diagnostics, and multi-error
recovery.- Codegen annotation and profiling views in the VS Code extension.
Language
- Local
constnow accepts float, string, and aggregate values.
Correctness fixes
- Fixed a gather-sum miscompile.
- Fixed float global variables reading back as 0 in the direct-object backend.
- Fixed two aggregate-by-value truncation bugs.
- Const-pool sinking now dominates all uses (#40).
Other
- New benchmark suite and examples; contributor guide; installer and Linux
build-flag fixes; dead-code cleanup.
What's Changed
- Backend, optimizer, and tooling overhaul: AArch64 target, closures, PGO/TRE, compile-time testing, and ML-guided IR opt by @marquisburg in #44
Full Changelog: v0.12.0...v0.13.0
Mettle v0.12.0
Implemented COFF IMAGE_SCN_LNK_NRELOC_OVFL support in binary_emitter.c (write) and linker/coff_reader.c (read) so sections with >65535 relocations encode the real count in a synthetic first relocation record instead of erroring.
What's Changed
- changes by @marquisburg in #43
Full Changelog: v0.11.0...v0.12.0
Mettle v0.11.0
v0.10.0 shipped the optimizer as a little helper. v0.11.0 does the same for safety: the compiler now catches use-after-free, dangling returns, loop off-by-ones, and null dereferences before the binary exists, explains what went wrong and where, and when it can't catch something statically, the runtime names the faulting address instead of printing an anonymous pointer.
The vectorizer also grew up: runtime scalar broadcasts, integer lanes, and a confirmed miscompile class found and fixed across the entire recognizer suite.
Compiler: memory safety diagnostics
Hard build errors
- Returning the address of a stack local, directly or through an alias
- Constant-size memory ops that exceed the destination array's capacity
- Constant array index out of bounds, including through pointer aliases (
var p = &a[2]; p[6]is a build error naminga[8]) - Loop off-by-one:
j <= 8over an int32[8] fails with the exact comparison to change - Divide-by-zero and over-width shift, with honest hardware explanations (
x << 32on int32 producesx; the hardware masks the count)
Warnings with fixes
- Use-after-free and double-free
- Stack address stored into a global
- Allocation that never escapes and is never freed (suggests
defer free(p)at the allocation site) - Null dereference through an unguarded pointer (any conditional on the pointer ends the claim)
Whole-program ownership inference
The compiler flattens imports into one program for codegen. It now uses the same call graph to compute per-function ownership summaries bottom-up: does this function free its parameter, store it, return a fresh allocation? The analysis re-runs with those summaries to catch UAF and leaks across call boundaries, through helper functions, and through wrapper allocators like make() -> malloc. Zero annotations required. Only definite summaries propagate; the zero-false-positive budget holds.
Runtime: access violation forensics
0x10 is no longer anonymous. With -s, a fault now explains the address:
Attempted to write inaccessible memory at 0x0000000000000010
This address is null plus offset 16: a field or array access through a null pointer
--> tests/debug_crash.mettle:13:14 in main
- Null-plus-offset: prints the field offset
- Stack region: dangling-frame note
- Freed heap: names the block, its size, and that it was already freed
--native-heap is now a UAF detector. Freed page-backed blocks keep their mapping with all access revoked and sit in a quarantine ring. Freed small blocks are poisoned 0xDD. A dangling read or write faults immediately with classification text, at the point of access, not three functions away where the corruption surfaces.
The static analyzer and the runtime fault handler compound: a UAF that escapes compile-time analysis faults instantly at runtime with the block named. Linux signal path covered.
Vectorizer: correctness and generalization
Confirmed miscompile fixed
Loops with a nonzero induction variable start (j = 3; while (j < n)) were silently replayed as 0..n by SIMD recognizers. Confirmed live repro returning 100 instead of 97. Fixed via a shared ir_iv_zero_at_header guard, one implementation, no duplicates. Eight recognizers had the same hole and all received the fix: sum_i32, dot_i32, dot_i8, exp_f32, memcmp byte-loop, clamp_i32, reverse-copy, both SLP MAC matchers, i2f, outer-lane vectorizer, and all pointer-walk matchers.
VLOOP generalized
- Runtime scalar broadcasts: any loop-invariant scalar symbol (param or local) now vectorizes as a broadcast.
out[i] = (a[i]*s1 + b[i])*s2with runtime coefficients vectorizes at 9.8x over scalar. - Integer lanes: new
IR_OP_SIMD_VLOOP_I32opcode covers int32/uint32 unit-stride maps and+-reductions over+ - * & | ^ <<literalDAGs, 8 lanes per iteration. Results are bit-exact against scalar. Int maps 3.9x, int reductions 5.8x.
uint32 wrap semantics
Unsigned sub-64-bit arithmetic now wraps mod 2^width consistently in all four modes (encoder, MIR, fallback backend, return canonicalization). Root cause was binary_emit_mov_reg_reg32 silently no-oping on dst==src, eating every uint32 zero-extension. Fixed with a dedicated binary_emit_movzx_reg_reg32 and three-layer canonicalization.
VS Code extension
- Full Debug Adapter Protocol: F5, conditional breakpoints, live variable editing, crash reporting via named-pipe debug runtime
- Optimization report panel: regression detection, verified fix application, click-to-source
@inline!and@noalloccontracts surface in the panel- Complete language service: go-to-definition, references, rename, outline, completion, signature help, inlay hints, CodeLens, hovers, compiler-backed diagnostics
- All memory diagnostic warnings and errors surface in the VS Code Problems panel with fix suggestions attached
Other
- DCE pass: dead code elimination in IR, improved compile speeds
- IR optimizer speedups: hash value maps, dead copy-propagation pruning,
getenvcaching type_checker.candir_lowering.csplit into focused modules- Bounded self-recursion inlining
- Site-aware inliner with repeated-refusal folding
- Linux build fix: explicit
-pthread -ldlfor glibc < 2.34 - 416/416 tests, 400/400 differential-fuzz seeds clean
What's Changed
- Add source-level debugger and interactive --explain optimization report panel with verified fixes by @marquisburg in #41
- Memory safety diagnostics, access violation forensics, and vectorizer correctness by @marquisburg in #42
Full Changelog: v0.10.0...v0.11.0
Mettle v.0.10.0
Mettle now compiles for the GPU: a native CUDA/PTX backend with kernel and
dispatch syntax. On the CPU, the legacy text-asm backend is gone and nearly every
function now goes through the register-allocating MIR backend. The language gains
function decorators, range-for loops, and @simd vectorization contracts, and the
runtime gets its own native memory allocator.
What's new
- GPU compilation: the compiler emits PTX natively for NVIDIA GPUs. Write
kernelfunctions as peers offunction, launch them with
dispatch K[grid, block](args), and index withthread.x,block.x,
block_dim.x, andgrid_dim.x. A newstd/gpumodule wraps the CUDA Driver
API. The PTX backend is validated by a ptxas round-trip gate in the test suite
and differential execution tests on real hardware. - One backend: the legacy text-asm backend has been removed. The MIR register
allocator now covers ~97% of functions (up from ~72%), including structs passed
and returned by value, calls with more than 4 arguments, address-of, switch
dispatch, and runtime safety checks. Almost no code falls back to
spill-everything codegen anymore. - Function decorators:
@inline,@noinline,@pure(lets the optimizer
hoist pure calls out of loops), and@simd/@simd!contracts that verify a
loop actually vectorized, with diagnostics explaining any bail. - Range-for syntax:
for i in 0..nand inclusivefor i in 0..=n. - Faster integer code: quantized int8 dot products and matmul tiles are
auto-vectorized with AVX2 (vpmaddwd): 11x over scalar and 3.5x faster than
gcc -march=native on the dot kernel. Constant division and modulo are
strength-reduced to magic multiplies, paired div+mod fuse into one division,
and SIMD kernels now inline into register-allocated functions instead of
forcing a fallback. - Native memory subsystem: Mettle's allocator is now written in Mettle
(std/osmem,std/alloc,std/mem). Build with--native-heapto route
new/malloc/freethrough it on Windows and Linux. Double-free and
invalid-free are detected and rejected. - Imports: stronger visibility enforcement and selective dependency
resolution, so only what you import gets compiled in. - Correctness: the differential fuzzer got new program shapes and automatic
pass attribution, and found 4 silent miscompiles, all fixed. Also fixed: three
register-promoted-global bugs exposed by a real GUI program, a uint32
signedness bug at -O, float32 narrowing bugs, a callee-saved register clobber
on Win64, and a missing diagnostic for non-void functions without a return.
Full test suite green throughout.
Full Changelog: v0.9.1...v0.10.0
What's Changed
- Add MIR register allocator, auto-vectorizators, SROA, magic-divide, and modularize SIMD & IR by @marquisburg in #37
- wcs_broadcast_i32_to_ymm emitted legacy movd immediately before a VEX… by @marquisburg in #38
- Native CUDA/PTX backend, full MIR register allocation, and function decorators by @marquisburg in #39
Full Changelog: v0.9.1...v0.10.0
Mettle v0.9.1
v0.9.0
Mettle v0.9.0
Native Linux --build with a self-contained ELF backend, GitHub Actions CI and release packaging, reworked installers, a richer VS Code extension, and compiler fixes from a new differential fuzzer.
What's new
- Linux native
--build: emits ELF objects with SysV AMD64 ABI and a compiler-owned_start, then links withld -staticinto standalone executables. No NASM, libc, or CRT required. See README anddocs/compilation.md. - CI and releases: GitHub Actions for Windows build+test, nightly fuzz, and tagged release packaging (Windows
.zip+ GUI installer, Linux.tar.gz). A Linuxelf-nativejob exercises the ELF backend. - Installers: reworked
install.ps1, newinstall.shfor per-user Linux installs, and an updated Inno Setup wizard with bundled docs and runtime. - VS Code / Cursor extension: hover docs, snippets, syntax updates, import/declaration hovers, and compiler-backed linting.
- Compiler fixes: struct method calls desugared correctly in the type checker (fixes #31). The differential miscompile fuzzer found and fixed three silent optimizer/backend bugs.
- Tooling cleanup: removed obsolete
build_engine_editor.bat. Benchmark reports and release workflow updated.
Full Changelog: v0.8.0...v0.9.0
What's Changed
- Development by @marquisburg in #33
- Add native Linux ELF backend with CI coverage, installer rework, and VS Code extension improvements by @marquisburg in #35
Full Changelog: v0.8.0...v0.9.0
v0.8.0
Mettle v0.8.0
Tracy profiling, source-aware crash tracebacks on Windows, a large compiler correctness pass, and continued IR and codegen optimization work since v0.7.1.
What's new
mettle --build --tracylinks the real Tracy client.std/tracycovers zones, frame marks, plots, and memory tracking. Without--tracy, the same source links a no-op stub so release and profiled builds stay in sync. Seeexamples/tracy_demo/.- Windows
--buildprograms built with-sor debug/trap flags get COFF stack traces with trap context and source snippets. - Fixed sign-extension bugs, codegen miscompiles,
uint32compares,int32call-result corruption on cross-module calls, and scaled pointer arithmetic lowering, with regression tests for the latter. - Multiple IR optimization passes, loop fusion, SIMD lowering (including insertion-sort fusion), and compilation-speed work across the pipeline.
- The compiler itself can be built with Clang on Windows via
CC=clangorbuild.bat clang, including MSVC/UCRT header compatibility fixes. - Mettle strings now flow to
cstringparameters implicitly where safe, socstr()wrappers are no longer required for common C interop and I/O call sites. - IR dumps include an explicit CFG view for basic blocks.
- Makefile source list fixes, unified
-O2and CFLAGS inbuild.bat, Hello World examples, and a README refresh. - Shared utilities, deduplicated cross-file logic, named phases for oversized functions, and consolidated linker utilities and test helpers. Critical fixes in
posix_helpers,ast_destroy_node, and method-declaration parsing. Full test suite passing again.
Full Changelog: v0.7.1...v0.8.0
v0.7.1
Burnt away the GC and async runtimes.
Optimizations can be observed in compilation speed & runtime performance.
v0.7.0
Mettle v0.7.0 - Rebrand & Async Runtime
Note: The project has been rebranded from Meth to Mettle. The compiler binary is now mettle / mettle.exe, source files use the .mettle extension, and the installer is updated accordingly. Update any scripts that invoke the old meth binary or reference .meth files.
Highlights
- Rebrand to Mettle: new name, binary, file extension, icon, and documentation throughout.
- Async/await runtime: bounded worker-pool executor (default) plus an experimental stackless coroutine model on a portable reactor (IOCP - on Windows, poll(2) on POSIX), with executor lifecycle management, token-routed task wakeups, and cooperative cancellation.
- Compilation speed: multiple passes of compile-time optimization across the front end and codegen.
- Runtime performance: codegen improvements for faster generated programs.
Language & Compiler
- Allowed newlines inside unclosed brackets (more forgiving parsing).
- Improved error reporting and diagnostics.
- Concurrency work and improved operand handling.
- Trait bounds / generic constraints, tagged-enum match, and namespaced imports (new test coverage added).
- Better string/cstring interop and std/conv formatting.
Stability
- Massive stability improvements and bug fixes across the compiler.
- Better POSIX support for Linux.
- Web server demo and form parser improvements.