Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
7ea2762
Add reference-counting-vs-GC evaluation; bump pre-alpha tag to 81
ASDAlexander77 Sep 2, 2026
39bc1da
Reserve a heap block header on the generic allocation path
ASDAlexander77 Sep 2, 2026
5c7998f
Record heap-header result in the RC evaluation
ASDAlexander77 Sep 2, 2026
642b4ab
Disable typed GC due to bitmap generation defects; class instances no…
ASDAlexander77 Sep 2, 2026
523048b
Point runtime type tags into per-type descriptors
ASDAlexander77 Sep 3, 2026
0521ec4
Generate per-type release routines into the descriptor slot
ASDAlexander77 Sep 3, 2026
e16975e
Give static blocks the heap block header, marked immortal
ASDAlexander77 Sep 3, 2026
bb0be42
Implement reference counting memory model and update related components
ASDAlexander77 Sep 3, 2026
d75b42b
Record the memory model in shared libraries, and settle WeakRef<T>
ASDAlexander77 Sep 3, 2026
2899ab3
Implement reference counting logic for `delete` operation and enhance…
ASDAlexander77 Sep 3, 2026
8f734cf
Add ts.Retain and ts.Release, and the retain routines behind them
ASDAlexander77 Sep 3, 2026
a7bcfb4
Implement unwind-safe disposal for `using` scopes and add correspondi…
ASDAlexander77 Sep 3, 2026
64a8733
Make locals own the heap references they hold
ASDAlexander77 Sep 3, 2026
00cbdfb
Delete two of the four `using` unwind guards, which were already stale
ASDAlexander77 Sep 3, 2026
4523209
End the active catch when a throw leaves it
ASDAlexander77 Sep 3, 2026
076278f
Hoist owned storage out of the TryOp
ASDAlexander77 Sep 3, 2026
0bd5678
Fix catchable type size handling to prevent register corruption in JI…
ASDAlexander77 Sep 4, 2026
7e92d08
Fix inliner behavior for throws and add related tests
ASDAlexander77 Sep 4, 2026
d9c5857
Fix ToInvoke splitting at an operation that is already an invoke
ASDAlexander77 Sep 4, 2026
da08f69
Add the ownership verifier, and fix what it found
ASDAlexander77 Sep 4, 2026
7ab09f2
Make fields own what they hold
ASDAlexander77 Sep 4, 2026
2aba8eb
Make elements own what they hold
ASDAlexander77 Sep 4, 2026
0560cd6
Retain what a literal captures
ASDAlexander77 Sep 4, 2026
ebb1dbc
Retain what the array-mutating ops insert
ASDAlexander77 Sep 4, 2026
bc10b48
Make inline records own what their fields hold
ASDAlexander77 Sep 4, 2026
722f32e
Allocate heap blocks unowned, and return +1
ASDAlexander77 Sep 4, 2026
f58d90e
Consume a transferred reference instead of retaining it again
ASDAlexander77 Sep 4, 2026
d183def
Consume the reference pop and shift transfer
ASDAlexander77 Sep 4, 2026
037e758
Implement Owned Return Consumption Pass to manage reference ownership…
ASDAlexander77 Sep 4, 2026
3d0f21d
Flip the allocator under -mm=rc, and fix allocating inside a catch fu…
ASDAlexander77 Sep 4, 2026
1c63522
Fix a try/catch nested inside a catch clause
ASDAlexander77 Sep 4, 2026
c306620
Give back the temporaries nothing received
ASDAlexander77 Sep 4, 2026
d029c81
Make an interface own what it was made from
ASDAlexander77 Sep 4, 2026
c7961c9
Resolve a method call's callee where it is safe to, and only there
ASDAlexander77 Sep 4, 2026
a19eba0
Give a closure its capture box, and make the releases actually run
ASDAlexander77 Sep 4, 2026
1121ee2
Give a captured variable's cell an owner
ASDAlexander77 Sep 4, 2026
d539934
Give back a cell whether or not the frame owns what is in it
ASDAlexander77 Sep 5, 2026
6e03e52
Take a reference when boxing into `any`
ASDAlexander77 Sep 5, 2026
c91d341
Hand back a reference for a string that was just built
ASDAlexander77 Sep 5, 2026
8eaf9da
Read through the `-mm=rc` corpus sweep and analyze non-zero exits; id…
ASDAlexander77 Sep 5, 2026
c05804e
Give a generator's unwritten local a value the retain can survive
ASDAlexander77 Sep 5, 2026
bab21b2
Give a literal array a block header, and an exhausted iterator a value
ASDAlexander77 Sep 5, 2026
0cda86e
Allocate and free a coroutine frame on the same heap
ASDAlexander77 Sep 5, 2026
d9d9064
Run the corpus under every memory model, in both tiers
ASDAlexander77 Sep 5, 2026
4244462
Take a reference to a cell captured through a capture box
ASDAlexander77 Sep 5, 2026
0c77bf7
Refactor reference counting logic for unions and add tests for union …
ASDAlexander77 Sep 5, 2026
69c55f1
Let `delete` claim the reference it gives up
ASDAlexander77 Sep 5, 2026
162d925
Retain what the synthesised constructor-interface method returns
ASDAlexander77 Sep 6, 2026
064e294
Remove the `-nogc` alias
ASDAlexander77 Sep 6, 2026
f9c3735
Clarify generator state object behavior and fix ownership issues in r…
ASDAlexander77 Sep 6, 2026
6fced23
Diagnose 00mixed_type_ops: the allocation goes, the free stays
ASDAlexander77 Sep 6, 2026
2be955b
Say that boxing a value into `any` allocates
ASDAlexander77 Sep 6, 2026
d1f0767
Add tests for global ownership and reference counting behavior
ASDAlexander77 Sep 6, 2026
5adc662
Enhance reference counting evaluation: add tests for generator locals…
ASDAlexander77 Sep 6, 2026
b692e1c
Give the entry point an exit code, and check it
ASDAlexander77 Sep 6, 2026
00548b1
Enhance ownership routine logic to handle capture boxes: add release …
ASDAlexander77 Sep 6, 2026
d7f97a6
Ask a dispatched call about every callee it could have
ASDAlexander77 Sep 6, 2026
414f949
Answer a call through a value with the module
ASDAlexander77 Sep 6, 2026
073e63f
Let discovery see what `new`'s arguments read
ASDAlexander77 Sep 6, 2026
bceb57b
Carry an awaited result in a slot, not in an async value
ASDAlexander77 Sep 6, 2026
6af9c1c
Tell the collector it is multi-threaded before awaiting on a pool
ASDAlexander77 Sep 6, 2026
44e4d68
Retire 5aa: iterating a literal array does not leak
ASDAlexander77 Sep 6, 2026
231fed7
Stand in for GC_enable_threads when a JIT run has no runtime DLL
ASDAlexander77 Sep 6, 2026
1db4d0f
Measure what raytrace holds, and file the crash blocking the next step
ASDAlexander77 Sep 6, 2026
3d8bddf
Release a discarded temporary on the paths that return early
ASDAlexander77 Sep 6, 2026
44e77e7
Say which half of the last fix was measured and which was not
ASDAlexander77 Sep 6, 2026
d9f4a58
Ask a jump whether it leaves the block, not where it is written
ASDAlexander77 Sep 6, 2026
9d9271d
Implement ownership verifier and update related tests and documentation
ASDAlexander77 Sep 7, 2026
3c84333
Implement dispose guard for `using` declarations and add related tests
ASDAlexander77 Sep 7, 2026
299eed6
Add memory model measurement script to report peak working set
ASDAlexander77 Sep 7, 2026
0772284
Add tests for catch variable behavior under JIT and AOT models
ASDAlexander77 Sep 7, 2026
548acb3
Clarify catch clause behavior for JIT image base and update related d…
ASDAlexander77 Sep 7, 2026
20dfb37
Enhance reference counting evaluation and debug info handling
ASDAlexander77 Sep 7, 2026
c3f629e
Refactor arithmetic operator promotion and improve ownership handling…
ASDAlexander77 Sep 7, 2026
c152402
Clarify memory measurement discrepancies and update harness documenta…
ASDAlexander77 Sep 7, 2026
066a236
Add regression test for conditional expression ownership discrepancies
ASDAlexander77 Sep 7, 2026
2411191
Enhance documentation on memory models and add regression test for `s…
ASDAlexander77 Sep 7, 2026
b499548
Enhance documentation and build scripts for shared library handling w…
ASDAlexander77 Sep 7, 2026
84dabdf
Enhance documentation and implementation for memory model handling, i…
ASDAlexander77 Sep 7, 2026
a3d95e7
Enhance documentation for memory model builds, clarifying usage of bu…
ASDAlexander77 Sep 8, 2026
8d707cc
Enhance version reporting to include Git commit hash for development …
ASDAlexander77 Sep 10, 2026
5df219c
Refactor Async Runtime Implementation
ASDAlexander77 Sep 10, 2026
646b2bc
Add debug shared-Boehm build script so debug trees can run the shared…
ASDAlexander77 Sep 10, 2026
b1fdc62
Emit an entry point for a root that only declares and initializes var…
ASDAlexander77 Sep 10, 2026
10cad10
Consume the llvm::Error on every JIT failure path instead of only log…
ASDAlexander77 Sep 10, 2026
5bf47b6
Narrow a switch case in its body, not in the block that tests the dis…
ASDAlexander77 Sep 10, 2026
4b7648c
Add memory model support for TypeScript compiler configuration
ASDAlexander77 Sep 10, 2026
6cb3fd9
Let the program's file say it is the one that needs an entry point
ASDAlexander77 Sep 11, 2026
b9e008b
Refactor VSCode and CMake folder creation to use updated library path…
ASDAlexander77 Sep 11, 2026
91e5328
Add tslang app path hint to CMake and VSCode folder creation
ASDAlexander77 Sep 11, 2026
18c3e29
Add directory creation for types folder and index.d.ts file in CMake …
ASDAlexander77 Sep 11, 2026
c984573
Add error handling for setting current path in createCMakeFolder
ASDAlexander77 Sep 11, 2026
db6b143
Update tsconfig.json include paths to use dynamic project file names
ASDAlexander77 Sep 11, 2026
b1e1884
Remove no-default-lib flag and update import statement for Adder in C…
ASDAlexander77 Sep 11, 2026
b1839b7
Add cmake.parallelJobs setting and include process headers for cross-…
ASDAlexander77 Sep 12, 2026
996c3fe
Enhance exception handling in TryOpLowering for nested cleanup-only t…
ASDAlexander77 Sep 12, 2026
3fcc50e
Implement blockHasTypedCatch to manage cleanup for typed catch clause…
ASDAlexander77 Sep 12, 2026
8068d5e
Add support for shared Boehm garbage collector in Windows tests and d…
ASDAlexander77 Sep 12, 2026
c478f4c
Ship the shared Boehm in the Windows release package
ASDAlexander77 Sep 12, 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
29 changes: 29 additions & 0 deletions .commit-msg-ownership.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Let a cleanup keep its releases when a disposal throws

A scope's cleanup region runs while an exception is already unwinding, and
TryOpLowering marks every call in a scope's body with that scope's landing
pad - which reaches into the cleanup regions of the scopes nested inside it.
The inner cleanup's [Symbol.dispose]() therefore became an invoke unwinding
to the outer cleanup, and the ts.ReleaseSlot written after it was stepped
over: the reference that scope took was never given back. This is what the
ownership verifier had been reporting on the two nested `using` scopes of
00break_continue_scope_exit.ts.

The fix removes the edge rather than adding a release. A function's outermost
cleanup has always used a plain call, because nothing encloses it and there
was no landing pad to mark it with; skipping calls written inside a nested
cleanup region makes every cleanup agree with the one that was already right.
The price is the C++ rule - a disposal that throws while unwinding terminates
instead of continuing outwards - and only in principle, since a throwing
[Symbol.dispose]() fails to JIT today in every model, un-nested included.

Wrapping the cleanup's disposals in a TryOp of their own was tried first and
failed 24 tests: a TryOp inside a TryOp is the construct section 9.11 already
records as broken.

The verifier now runs in ctest as well. Both of its real findings came from a
hand-run sweep that nothing repeated, which is why this pair stayed open;
verify-ownership.cmake is that sweep over every corpus file, in eight shards
of about four seconds. Suite 2,641 -> 2,649, all green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
21 changes: 21 additions & 0 deletions .github/workflows/cmake-test-release-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ jobs:
run: dir
shell: pwsh

# Boehm as a DLL, for the -shared tests only: an executable and a shared library that each
# link gc.lib statically get two collectors (item 5ao). Mirrors
# scripts/build_gc_release_shared_vs.bat; must be installed before tslang is configured,
# since the test CMakeLists checks for it at configure time.
- name: Configure GC (shared)
continue-on-error: false
run: New-Item -ItemType Directory -Force -Path ".\__build\gcdll\msbuild\x64\release" | Out-Null; cd ".\__build\gcdll\msbuild\x64\release"; cmake ../../../../../3rdParty/gc-${{ env.GC_VERSION }} -G "Visual Studio 18 2026" -A x64 -Wno-dev -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/3rdParty/gcdll/x64/release -DBUILD_SHARED_LIBS=ON -Denable_threads=ON -Denable_cplusplus=OFF -Denable_docs=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
shell: pwsh

- name: Build GC (shared)
continue-on-error: false
working-directory: ${{github.workspace}}/__build/gcdll/msbuild/x64/release
run: cmake --build . --config ${{ env.BUILD_TYPE }} -j 8
shell: pwsh

- name: Install GC (shared)
continue-on-error: false
working-directory: ${{github.workspace}}/__build/gcdll/msbuild/x64/release
run: cmake --install . --config ${{ env.BUILD_TYPE }}; dir ${{github.workspace}}/3rdParty/gcdll/x64/release/lib, ${{github.workspace}}/3rdParty/gcdll/x64/release/bin
shell: pwsh

- name: Configure
continue-on-error: false
working-directory: ${{github.workspace}}/__build/tslang/msbuild/x64/release
Expand Down
38 changes: 33 additions & 5 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,28 @@ jobs:
run: cmake --install . --config ${{ env.BUILD_TYPE }}
shell: pwsh

# Boehm as a DLL: an executable and a tslang shared library that each link the static
# gc.lib get two collectors, and one frees what the other still holds (item 5ao). Used by
# the -shared tests, and shipped in the zip's gcdll folder. Mirrors
# scripts/build_gc_release_shared_vs.bat; installed before tslang is configured, since the
# test CMakeLists checks for it at configure time.
- name: Configure GC (shared)
continue-on-error: false
run: New-Item -ItemType Directory -Force -Path ".\__build\gcdll\msbuild\x64\release" | Out-Null; cd ".\__build\gcdll\msbuild\x64\release"; cmake ../../../../../3rdParty/gc-${{ env.GC_VERSION }} -G "Visual Studio 18 2026" -A x64 -Wno-dev -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/3rdParty/gcdll/x64/release -DBUILD_SHARED_LIBS=ON -Denable_threads=ON -Denable_cplusplus=OFF -Denable_docs=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
shell: pwsh

- name: Build GC (shared)
continue-on-error: false
working-directory: ${{github.workspace}}/__build/gcdll/msbuild/x64/release
run: cmake --build . --config ${{ env.BUILD_TYPE }} -j 8
shell: pwsh

- name: Install GC (shared)
continue-on-error: false
working-directory: ${{github.workspace}}/__build/gcdll/msbuild/x64/release
run: cmake --install . --config ${{ env.BUILD_TYPE }}
shell: pwsh

- name: Configure
continue-on-error: false
working-directory: ${{github.workspace}}/__build/tslang/msbuild/x64/release
Expand Down Expand Up @@ -178,10 +200,16 @@ jobs:
- name: Create Zip of Windows Asset
working-directory: ${{github.workspace}}/__build
# Flatten the compiler/runtime binaries into the archive root, and add the
# default library as a whole tree so its per-build subfolders are preserved:
# defaultlib/dll/{debug,release}, defaultlib/lib/{debug,release},
# default library as a whole tree so its per-build, per-memory-model subfolders
# are preserved:
# defaultlib/{dll,lib}/{debug,release}/{gc,rc,none},
# defaultlib/*.d.ts, defaultlib/generics/
run: Get-ChildItem -Path .\tslang\msbuild\x64\release\bin\tslang.exe, .\tslang\msbuild\x64\release\bin\TypeScriptRuntime.dll, .\gc\msbuild\x64\release\${{ env.BUILD_TYPE }}\gc.lib, .\tslang\msbuild\x64\release\lib\TypeScriptAsyncRuntime.lib, ..\3rdParty\llvm\x64\release\lib\LLVMSupport.lib, ..\3rdParty\llvm\x64\release\bin\wasm-ld.exe, ..\TypeScriptCompilerDefaultLib\__build | Compress-Archive -DestinationPath ..\tslang.zip
# plus the shared collector in its own folder, because its import library is also named
# gc.lib: gcdll/gc.lib + gcdll/gc.dll, for programs that load a tslang shared library.
run: |
New-Item -ItemType Directory -Force -Path .\gcdll_stage\gcdll | Out-Null
Copy-Item -Path ..\3rdParty\gcdll\x64\release\lib\gc.lib, ..\3rdParty\gcdll\x64\release\bin\gc.dll -Destination .\gcdll_stage\gcdll -ErrorAction Stop
Get-ChildItem -Path .\tslang\msbuild\x64\release\bin\tslang.exe, .\tslang\msbuild\x64\release\bin\TypeScriptRuntime.dll, .\gc\msbuild\x64\release\${{ env.BUILD_TYPE }}\gc.lib, .\tslang\msbuild\x64\release\lib\TypeScriptAsyncRuntime.lib, ..\3rdParty\llvm\x64\release\lib\LLVMSupport.lib, ..\3rdParty\llvm\x64\release\bin\wasm-ld.exe, ..\TypeScriptCompilerDefaultLib\__build, .\gcdll_stage | Compress-Archive -DestinationPath ..\tslang.zip
shell: pwsh

- name: Archive Zip of Windows Asset
Expand Down Expand Up @@ -375,8 +403,8 @@ jobs:
cp ../3rdParty/llvm/release/bin/wasm-ld ./__stage/
cp ../3rdParty/llvm/release/lib/libLLVMSupport.a ./__stage/
cp ../3rdParty/llvm/release/lib/libLLVMDemangle.a ./__stage/
# Add the default library as a whole tree so its per-build subfolders are
# preserved: defaultlib/dll/{debug,release}, defaultlib/lib/{debug,release},
# Add the default library as a whole tree so its per-build, per-memory-model
# subfolders are preserved: defaultlib/{dll,lib}/{debug,release}/{gc,rc,none},
# defaultlib/*.d.ts, defaultlib/generics/
cp -r ../TypeScriptCompilerDefaultLib/__build/defaultlib ./__stage/
tar -czvhf ../tslang.tar.gz -C ./__stage .
Expand Down
9 changes: 7 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
}
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
// Release builds of the MLIR-heavy TUs peak at ~3 GB RSS per cc1plus.
// Ninja's default (nproc + 2 = 26 here) exhausts RAM and the OOM killer
// takes out cc1plus ("g++: fatal error: Killed signal terminated program
// cc1plus"). 8 matches build_tslang_release.sh.
"cmake.parallelJobs": 8
}
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ on the fly via a built-in JIT — no Node.js or JavaScript runtime required.
- [Debugging JIT code with GDB (Linux)](#debugging-jit-code-with-gdb-linux)
- [As a native executable](#compile-as-binary-executable)
- [As WebAssembly](#compiling-as-wasm)
- [Memory models](#memory-models)
- [Building from source](#build)
- [Community](#chat-room)
- [License](#license)
Expand Down Expand Up @@ -326,7 +327,7 @@ Hello World!
Build

```bat
tslang.exe --emit=exe --nogc -mtriple=wasm32-unknown-unknown hello.ts
tslang.exe --emit=exe -mm=none -mtriple=wasm32-unknown-unknown hello.ts
```

Run ``run.html``
Expand Down Expand Up @@ -474,6 +475,24 @@ Run ``run.html``

</details>

## Memory models

How heap memory is managed is selected with `-mm=`:

| flag | | |
| --- | --- | --- |
| `-mm=gc` | garbage collection (Boehm) | the default |
| `-mm=rc` | reference counting - freed as soon as the last reference goes, no collector, no `libgc` | **does not collect reference cycles** |
| `-mm=none` | nothing is ever freed | short-lived programs |

`-mm=gc` is the default and needs no thought. `-mm=rc` reclaims memory deterministically and
holds close to the working set - a ray tracer that reaches 114 MB under `-mm=none` holds 4.1 MB,
against garbage collection's 5.8 - but **objects that refer to each other in a cycle are never
freed under it**, which is the same trade Swift makes with ARC.

See **[docs/memory-models.md](docs/memory-models.md)** for which shapes leak, which do not, and
what to do about it.

## Build

### Build on Windows
Expand Down
2 changes: 1 addition & 1 deletion docs/VisualStudio/CustomTool/tslang.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<DataSource Persistence="ProjectFile" ItemType="TSLANG" SourceType="Item"/>
</StringProperty.DataSource>
</StringProperty>
<BoolProperty Name="DisableGarbageCollection" Category="TypeScript Compiler Options" DisplayName="Disable Garbage Collection" Description="Disable Garbage Collection. (--nogc)" HelpUrl="https://github.com/ASDAlexander77/TypeScriptCompiler/wiki/tsc" Switch="--nogc"/>
<BoolProperty Name="DisableGarbageCollection" Category="TypeScript Compiler Options" DisplayName="Disable Garbage Collection" Description="Disable Garbage Collection. (-mm=none)" HelpUrl="https://github.com/ASDAlexander77/TypeScriptCompiler/wiki/tsc" Switch="-mm=none"/>
<BoolProperty Name="DisableWarnings" Category="TypeScript Compiler Options" DisplayName="Disable Warnings" Description="Disable Warnings. (--nowarn)" HelpUrl="https://github.com/ASDAlexander77/TypeScriptCompiler/wiki/tsc" Switch="--nowarn"/>
<BoolProperty Name="GenerateDebugInformation" Category="TypeScript Compiler Options" DisplayName="Generate Debug Information" Description="Generates Debug Information. (--di)" HelpUrl="https://github.com/ASDAlexander77/TypeScriptCompiler/wiki/tsc" Switch="--di"/>
<BoolProperty Name="DebugInformationForLLDB" Category="TypeScript Compiler Options" DisplayName="Debug Information For LLDB" Description="Debug Information for LLDB. (--lldb)" HelpUrl="https://github.com/ASDAlexander77/TypeScriptCompiler/wiki/tsc" Switch="--lldb"/>
Expand Down
6 changes: 3 additions & 3 deletions docs/compiler-explorer/lib/compilers/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class TypeScriptCompiler extends BaseCompiler {
async handleInterpreting(key, executeParameters) {
executeParameters.args = [
'--emit=jit',
this.tslangSharedLib ? '--shared-libs=' + this.tslangSharedLib : '-nogc',
this.tslangSharedLib ? '--shared-libs=' + this.tslangSharedLib : '-mm=none',
...executeParameters.args,
];

Expand All @@ -54,7 +54,7 @@ export class TypeScriptCompiler extends BaseCompiler {

if (!this.tslangSharedLib)
{
newOptions.push('-nogc');
newOptions.push('-mm=none');
}

const output = await this.runCompilerRawOutput(this.tslangJit, newOptions, this.filename(inputFilename), execOptions);
Expand All @@ -77,7 +77,7 @@ export class TypeScriptCompiler extends BaseCompiler {

if (!this.tslangSharedLib)
{
newOptions.push('-nogc');
newOptions.push('-mm=none');
}

const execOptions = this.getDefaultExecOptions();
Expand Down
13 changes: 12 additions & 1 deletion docs/how/cmake_bgfx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(TSLANG_ROOT "" CACHE PATH "TypeScriptCompiler __build folder (contains tslang/, llvm/, gc/)")
set(TSLANG_MEMORY_MODEL "gc" CACHE STRING "Memory model of compiled code: gc, rc or none")
set_property(CACHE TSLANG_MEMORY_MODEL PROPERTY STRINGS gc rc none)

include(LocateTSLang)
locate_tslang_compiler()
Expand Down Expand Up @@ -49,6 +51,10 @@ else()
set(CMAKE_TSLANG_FLAGS "--di --opt_level=0")
endif()

# The same variable that picked the default-lib link directory has to reach the compiler as
# well, or the program is compiled for one model and linked against another model's default lib.
set(CMAKE_TSLANG_FLAGS "${CMAKE_TSLANG_FLAGS} -mm=${TSLANG_MEMORY_MODEL}")

if(WIN32)
else()
set(CMAKE_TSLANG_FLAGS "${CMAKE_TSLANG_FLAGS} -relocation-model=pic")
Expand All @@ -66,9 +72,14 @@ target_include_directories(${PROJECT_NAME} PRIVATE native)
set(TSLANG_LINK_LIBS
TypeScriptDefaultLib
TypeScriptAsyncRuntime
gc
LLVMSupport)

# Boehm is only referenced by the gc default lib; the rc and none builds allocate through the
# CRT and must not drag a collector in.
if(TSLANG_MEMORY_MODEL STREQUAL "gc")
list(APPEND TSLANG_LINK_LIBS gc)
endif()

if(WIN32)
list(APPEND TSLANG_LINK_LIBS ntdll)
else()
Expand Down
13 changes: 13 additions & 0 deletions docs/how/cmake_bgfx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ cmake --preset debug
cmake --build --preset debug
```

### Memory model

The default library is compiled separately for each memory model, and a program has to link the
build matching the model it was compiled with. One variable drives both:

```bash
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree; configuring fails if that model has not been
built. Valid values are `gc` (default), `rc` and `none`; only `gc` links Boehm.

## How it works

1. **`main_entry.cpp`** calls TypeScript `Main()`, then C++ `run_loop()`.
Expand Down
15 changes: 14 additions & 1 deletion docs/how/cmake_bgfx/cmake/LocateTSLang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,29 @@ function(setup_tslang_link_paths)
message(FATAL_ERROR "setup_tslang_link_paths: TSLANG_PREFIX is not set")
endif()

# The compiled default lib is split per build mode (debug/release) and then per memory
# model (gc/rc/none): a default lib built for one model allocates the way that model
# allocates, so linking it into a program built for another is the mismatch the compiler
# refuses to paper over. TSLANG_MEMORY_MODEL picks both this directory and the -mm= flag.
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(_defaultlib_config "release")
else()
set(_defaultlib_config "debug")
endif()

set(_defaultlib_dir
"${TSLANG_BIN_DIR}/defaultlib/lib/${_defaultlib_config}/${TSLANG_MEMORY_MODEL}")
if(NOT IS_DIRECTORY "${_defaultlib_dir}")
message(FATAL_ERROR
"No default library built for -mm=${TSLANG_MEMORY_MODEL}: ${_defaultlib_dir} "
"does not exist. Build it (see the default-lib build scripts), or select a model "
"that is built with -DTSLANG_MEMORY_MODEL=<gc|rc|none>.")
endif()

set(_link_dirs
"${TSLANG_BIN_DIR}"
"${TSLANG_PREFIX}/lib"
"${TSLANG_BIN_DIR}/defaultlib/lib/${_defaultlib_config}")
"${_defaultlib_dir}")

if(TSLANG_ROOT)
if(EXISTS "${TSLANG_ROOT}/gc/release")
Expand Down
27 changes: 25 additions & 2 deletions docs/how/cmake_tslang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ enable_language(TSLANG)
# Include folders
include_directories(${CMAKE_TSLANG_DIR}/defaultlib)

# The compiled default lib is split into per-build subfolders (debug/release) and then per
# memory model (gc/rc/none); pick the pair matching this build, so that the CRT, the allocator
# and the default-lib binaries all agree. A library built for one model cannot be linked into
# a program built for another.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(TSLANG_DEFAULTLIB_BUILD "release")
else()
set(TSLANG_DEFAULTLIB_BUILD "debug")
endif()

set(TSLANG_MEMORY_MODEL "gc" CACHE STRING "Memory model of compiled code: gc, rc or none")
set_property(CACHE TSLANG_MEMORY_MODEL PROPERTY STRINGS gc rc none)

# Lib folders
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/defaultlib/lib)
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/defaultlib/lib/${TSLANG_DEFAULTLIB_BUILD}/${TSLANG_MEMORY_MODEL})

# set options
if (CMAKE_BUILD_TYPE STREQUAL "Release")
Expand All @@ -21,6 +34,10 @@ else()
set(CMAKE_TSLANG_FLAGS "--di --opt_level=0") # global
endif()

# The same variable that picked the link directory has to reach the compiler as well, or the
# program is compiled for one model and linked against another model's default lib.
set(CMAKE_TSLANG_FLAGS "${CMAKE_TSLANG_FLAGS} -mm=${TSLANG_MEMORY_MODEL}") # global

if(WIN32)
else()
set(CMAKE_TSLANG_FLAGS "${CMAKE_TSLANG_FLAGS} -relocation-model=pic") # global
Expand All @@ -34,7 +51,13 @@ add_executable(${PROJECT_NAME}
)

# required libs
set(TSLANG_LINK_LIBS "TypeScriptDefaultLib" "TypeScriptAsyncRuntime" "gc" "LLVMSupport")
set(TSLANG_LINK_LIBS "TypeScriptDefaultLib" "TypeScriptAsyncRuntime" "LLVMSupport")

# Boehm is only referenced by the gc default lib; the rc and none builds allocate through the
# CRT and must not drag a collector in.
if (TSLANG_MEMORY_MODEL STREQUAL "gc")
list(APPEND TSLANG_LINK_LIBS "gc")
endif()

# ntdll provides RtlGetLastNtStatus (pulled in by LLVMSupport) on Windows
if(WIN32)
Expand Down
13 changes: 13 additions & 0 deletions docs/how/cmake_tslang/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ set_source_files_properties(mycode.ts PROPERTIES
COMPILE_OPTIONS "--define;TSLANG=1") # per-file
```

## Memory model

The default library is compiled separately for each memory model, and a program has to link
the build matching the model it was compiled with. One variable drives both:

```
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree. Valid values are `gc` (default), `rc` and
`none`; only `gc` links Boehm.

## Minimal alternative

If you don't need a first-class language, either:
Expand Down
2 changes: 1 addition & 1 deletion docs/how/wasm/test/test_wasm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $files | ForEach-Object -Parallel {
$outFileName = $file.BaseName + ".wasm"
$stdOutputFileName = $file.BaseName + ".txt"
$errOutputFileName = $file.BaseName + ".err"
$argumentList = "--emit=exe", "--nogc", "-mtriple=wasm32-unknown-unknown", "-o=$outFileName", $file.FullName
$argumentList = "--emit=exe", "-mm=none", "-mtriple=wasm32-unknown-unknown", "-o=$outFileName", $file.FullName


if (Test-Path -Path $outFileName -PathType Leaf)
Expand Down
2 changes: 1 addition & 1 deletion docs/how/wasm/wasm/tsc_wasm.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set GC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\gc\msbuild\x64\debug\Debug
set LLVM_LIB_PATH=C:\dev\TypeScriptCompiler\__build\llvm\msbuild\x64\debug\Debug\lib
set TSLANG_LIB_PATH=C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\lib
C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\bin\tslang.exe --emit=exe --nogc --di -mtriple=wasm32-unknown-unknown C:\temp\1.ts
C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\bin\tslang.exe --emit=exe -mm=none --di -mtriple=wasm32-unknown-unknown C:\temp\1.ts
copy 1.wasm C:\temp\webassembly3\hello.wasm
2 changes: 1 addition & 1 deletion docs/how/wasm/wasm/tsc_wasm_emscripten.bat
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ set GC_LIB_PATH=C:\dev\TypeScriptCompiler\__build\gc\msbuild\x64\debug\Debug
set LLVM_LIB_PATH=C:\dev\TypeScriptCompiler\__build\llvm\msbuild\x64\debug\Debug\lib
set TSLANG_LIB_PATH=C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\lib
set EMSDK_SYSROOT_PATH=C:\utils\emsdk\upstream\emscripten\cache\sysroot
C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\bin\tslang.exe --emit=exe --nogc -mtriple=wasm32-pc-emscripten C:\temp\1.ts
C:\dev\TypeScriptCompiler\__build\tslang\windows-msbuild-debug\bin\tslang.exe --emit=exe -mm=none -mtriple=wasm32-pc-emscripten C:\temp\1.ts
copy 1.wasm C:\temp\webassembly3\hello.wasm
Loading
Loading