Repository navigation
Catch a class thrown from another module (Linux box thunk, -shared instanceof, thunk linkage) - #351
Merged
Conversation
…stanceof, thunk linkage An untyped or `any` catch of a class that only another module throws did not work on either platform: - Linux: the catch-all binding recognised only the classes its own module throws (ts.thrown_classes), so any other class was boxed as a plain object and `<Cls>e` threw "Can't cast from any type". The thrower now supplies the box, as the Windows copy thunk does: a class's __pointer_type_info gets a fifth field, the address of a `.eh.copy.box.P<n><name>` thunk (class -> any), which the binding calls when the type_info is a __pointer_type_info. This replaces the ts.thrown_classes list. - -shared: `x instanceof C` and `<C>anyValue` of a class imported from a shared library expected its rtti value to be a ref, and failed when the property access had already read through it - so the instanceOf call was dropped: `instanceof` did not compile and the cast always threw. - Windows, static link: a typed catch and the throw each emitted the class's `.eh.copy.box` thunk as an external symbol - duplicate symbol. Thunks are now internal (linkonce_odr crashed catches under the Win64 JIT). Also fixes `if (x instanceof N.C)` for a namespaced class, which crashed the compiler: the narrowing built a type reference from the property access instead of a qualified name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ASDAlexander77
added a commit
that referenced
this pull request
Sep 23, 2026
…#352) MLIRCodeLogicHelper::conditionalValue returned failure with its IfOp still in the IR - an empty or none-typed region - and the insertion point still inside it. Whenever the caller carried on, the failure turned into bad IR further on: "'ts.If' op expects a non-empty block" in place of the branch's own error (seen as `x instanceof C` of a -shared class before #351). It now erases the IfOp and puts the insertion point back before returning. Co-authored-by: Claude Opus 5.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.
Summary
An untyped or
anycatch of a class that only another module throws failed on both platforms. Fixing it exposed three more bugs on the same path.ts.thrown_classeslist). Any other class was boxed as a plain object, so<Cls>ethrew "Can't cast from any type"._ZTIP<n><name>(a__pointer_type_info) gets a fifth field that libstdc++ never reads: the address of an.eh.copy.box.P<n><name>thunk (class → any). It is built by the existingmlirGenCatchCopyThunk.__pointer_type_info, it calls that thunk. Anything else, such as a foreign C++ exception, is still boxed as a plain object.ts.thrown_classesandrecordThrownClass.-shared:instanceofand<C>anyValueof an imported class.mlirGenInstanceOfOpaqueexpected the rtti of a dynamically imported class to be a ref. The property access already reads through it, so the check failed and the.instanceOfcall was dropped:x instanceof Cdid not compile, and<C>ealways threw..eh.copy.box.*symbol. A typed catch and the throw each emitted the thunk as an external function. Thunks now have internal linkage.linkonce_odr+ comdat (thespecializationpath) fixed the link but made JIT catches crash with an access violation.if (x instanceof N.C)crashed the compiler for any namespaced class, even in a single module. The narrowing built a type reference from the property access instead of a qualified name.Notes
MLIRCodeLogicHelper::conditionalValuereturns failure but leaves its half-builtts.Ifin the IR. That is how the droppedinstanceOfcall became "'ts.If' op expects a non-empty block", or an unbox that always throws, with no error message.Tests
import_throw_class.ts/export_throw_class.ts. Registered likeclass-extends: static,-shared,-jit -shared, plus the rc/none variants. They cover a typed catch,<C>ein an untyped catch,<C>ein ananycatch, andinstanceofnarrowing.00instanceof_namespace_narrowing.ts.🤖 Generated with Claude Code