Skip to content

Give a catch copy thunk a debug scope of its own - #361

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-catch-thunk-debug-scope
Sep 24, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-catch-thunk-debug-scope

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Fixes the v0.0-pre-alpha85 release build, which failed on all four platforms (run 36038070141).

What broke

With --di, the .eh.copy.box.* copy thunk a class throw needs was built at the throw statement's location, and that location carries the statement's debug scope. When the throw is inside a braced block, the scope is a lexical block of the enclosing function. The thunk then got a subprogram of its own while its instructions still pointed into the other function, and LLVM rejected the module:

!dbg attachment points at wrong subprogram for function
!5857 = distinct !DISubprogram(name: ".eh.copy.box.PEAVError@@", ...)
tslang: error: Failed to emit LLVM IR

DefaultLib's debug build (--di, no --opt) throws RangeError inside blocks (fetch, Array.with), so it stopped emitting:

  • Windows: LNK1181: cannot open input file '.\lib\debug\gc\lib.obj'
  • Linux: cannot find -lTypeScriptDefaultLibCore, then debug/compile 0/155

Every release variant passed. PR CI is Release-only, and although the suite runs with --di, none of its throws sat in a braced block, so nothing caught this before the tag. When the throw is not in a block, the thunk silently took the enclosing function's subprogram. That was wrong too, but the verifier accepted it.

Fix

mlirGenCatchCopyThunk now does what a function declaration does (MLIRGenFunctions.cpp): it opens a debug scope, creates a subprogram for the thunk, and locates the body under it using the statement's plain location.

Tests

  • New 00throw_in_block_debug_info.ts (compile + jit; the runner already passes --di --opt_level=0). It fails on main with the exact CI error and passes with the fix.
  • Windows release suite: 2884/2884.
  • DefaultLib built locally with this compiler: debug/gc build succeeds. Tests: release/compile 155/155, release/jit 155/155, debug/compile 155/155, debug/jit 155/155.

Not in this PR

Compiling a file that throws with --di --opt still fails, with a different error ("inlinable function call in a function with a DISubprogram location must have a debug location"). This existed before this change and doesn't affect the release, since the debug default lib is built without --opt.

After merge, the release needs a new tag: v0.0-pre-alpha85 points at 5671e4c4 and no release object was created from it.

🤖 Generated with Claude Code

With --di, the `.eh.copy.box.*` thunk a class throw needs was built at the
throw statement's location, which carries that statement's debug scope.
Inside a braced block that scope is a lexical block of the enclosing
function, so the thunk ended up with a subprogram of its own while its
instructions still pointed into the other function, and LLVM rejected the
module ("!dbg attachment points at wrong subprogram for function").

The DefaultLib debug build (`--di`, no `--opt`) throws RangeError inside
blocks, so it stopped emitting: the v0.0-pre-alpha85 release failed on all
four platforms. The suite runs with --di too, but none of its throws sat in
a braced block.

The thunk now takes the same steps a function declaration does: a
subprogram for itself, and a body located under it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 40185c7 into main Sep 24, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-catch-thunk-debug-scope branch September 24, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant