Repository navigation
tsbindgen v1: C headers to tslang bindings - #367
Merged
Merged
Conversation
ASDAlexander77
force-pushed
the
tsbindgen-v1
branch
from
September 26, 2026 16:41
b3a03ca to
aed6755
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed C integers map to sN (tslang's iN are signless), and a struct pointer that leads back to its own struct is Opaque: tslang cannot declare a self-referencing type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…paque Found by running tsbindgen over the default library's regex wrappers: their functions take a std::cmatch *, which was emitted as a type name (match_results) nothing declares, so the bindings did not compile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the branch review: - a C type named like a tslang type (typedef int boolean) is looked through, a struct of such a name renamed: tslang ignores such an alias and bound an int result as boolean's one bit - a C name TS reserves (int new(void)) gets a `_` and @Linkname - an __asm__ label is the symbol (glibc's __REDIRECT) - a malformed number in an unexpanded macro skips that macro instead of failing the header - a non-C calling convention (__stdcall on i686) is skipped, not bound as cdecl - an enum declared but never defined is its integer type - the e2e fixture is built at -O2, where a callee relies on its caller extending narrow arguments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gcc -Wpedantic -Werror (Linux CI) rejects &main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ASDAlexander77
force-pushed
the
tsbindgen-v1
branch
from
September 26, 2026 17:37
aed6755 to
08a239a
Compare
ASDAlexander77
marked this pull request as ready for review
September 26, 2026 18:19
This was referenced Sep 26, 2026
ASDAlexander77
added a commit
that referenced
this pull request
Sep 26, 2026
…372) tsbindgen has built alongside tslang since #367, but the release packaging step only ever staged an explicit allowlist of binaries, so it never reached the zip/tarball. It also needs clang's resource directory (stddef.h, stdint.h, ...) next to it, or it fails at runtime with "clang's resource directory not found" - findResourceDir's release-package candidate is exeDir/lib/clang/<major>, so stage 3rdParty/llvm's lib/clang folder at that path in both packages. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 2 of
docs/superpowers/specs/2026-09-25-tsbindgen-linkname-design.md. It addstsbindgen, a tool that reads a C header with clang and writes tslang bindings for it.What it writes
declare function, with@linkname("c_name")whenever the TS name differs from the symbol. That covers--namespace,--strip-prefix, escaped reserved words and__asm__labels.enums of the C integer type;consts.Reference<T>, orOpaquefor handles,void *, function pointers and C++ classes.char *isstring.sNand unsigned touN, by the width the target gives them.// skipped: <name>: <reason>line and a warning, never dropped silently. Examples:The code is in three places:
tslang/lib/TsClangImporter: the binding model, clangHeaderParser,TypeMapperandBindingPrinter.tslang/tsbindgen: the command line.tslang/unittests/TsClangImporter: 53 gtest cases.Where it differs from the spec
The full table is in the spec's new "As built (2026-09-26)" section. Each row was found by running generated bindings through tslang:
.ts, not.d.ts. Aconstin a.d.ts, or in any file pulled in withimport, has no value:LNK2019when linked,Symbols not foundunder the JIT. The bindings are included with/// <reference path>.sN, notiN. tslang'siNare signless, so anint8_t-5 printed251.Opaque. A self-referencing type alias makes tslang exit 127 with no message. That's a compiler bug to file separately./* ... */comment on the parameter. The spec had one trailing comment, which can't say which parameter it describes.ToolInvocationwith our own diagnostics.runToolOnCodeWithArgsexits 0 even when the clang command line has an error.--strip-prefixnever produces an empty, digit-leading or duplicate name;tslang/docs/reference-counting-evaluation.md§9.78 records the open issue: under-mm=rc, a C-ownedchar *returned asstringhas no string header. v1 targetsgc.Tests
unittest-TsClangImporterTests(53 cases):test-bindgen-plainandtest-bindgen-namespace: buildfixture.cinto a real C library at-O2, generate bindings fromfixture.h, and runbindgen_test.tsboth linked and under--emit=jit. The output must matchexpected.txt.narrowrow passesint8_t/uint16_t/boolarguments. It exists to catch a missingsignext/zeroexton tslang'sdeclareparameters. That can only fail on SysV (Linux), where an optimized callee trusts the caller to extend.test-bindgen-cli: pins the exit codes and messages for bad arguments, a missing header and a clang error.Checked against the default library
Bindings generated from DefaultLib's
regex.cppandhttp.cppcompile in tslang. Compared with the hand-writtenlib.native.d.ts, the 22 functions in each have the same names. The only differences are expected:Opaqueversus a named or commentedOpaquehandle;intversuss32;sby hand where the C++ source saysc;: void.No mistakes were found in
lib.native.d.ts. The comparison did find one generator bug:std::cmatch *came out as an undeclaredmatch_results. It's fixed in 6918335 with a unit test.Known gaps (v1)
Nothing is emitted, and no skip line is written, for these:
externglobal variables;enum { FOO = 1 }constants;typedef struct {…} *Handle(the typedef and its users).Smaller:
inlinefunction is emitted as a declaration;Linux CI
Run 36246544195 on
b3a03ca3: 2897/2899 pass.test-bindgen-plainandtest-bindgen-namespacefail on exactly one line, thenarrowrow, both linked and under the JIT. Windows is green.fx_widen_s8(-5)returns 251. On x86-64 SysV, a clang-compiled callee assumes the caller has already sign- or zero-extended an 8- or 16-bit argument to 32 bits. tslang never emitssignext/zeroext; nothing inlib/TypeScriptsets either. So tslang passes the raw 8 bits and the callee reads garbage in the upper bits.u16passed only because the 16-bit constant happened to arrive zero-extended.This is the tslang call-lowering bug from Review Focus 1, not a mapping error. It affects every tslang call into C with an 8- or 16-bit argument on Linux, hand-written bindings included. The mapping stays as it is.
Fixed in #369. This branch with #369 cherry-picked passes on Linux: 2907/2907 (run 36250596356). #367 goes green once it's rebased onto
mainafter #366 and #369 merge.(An earlier run failed to build: gcc
-Wpedanticrejects&main. Fixed in b3a03ca.)🤖 Generated with Claude Code