This is an automated email from the ASF dual-hosted git repository. tqchen pushed a commit to branch orcjit-windows-arm64-855 in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git
commit 0d7f39be7d4ca077f9979ae2bc7579060e764ca3 Author: Tianqi Chen <[email protected]> AuthorDate: Mon Oct 26 03:51:54 2026 +0000 [TEST] Cover ARM64 CRT recovery after object link failure --- addons/tvm_ffi_orcjit/README.md | 2 +- addons/tvm_ffi_orcjit/tests/test_basic.py | 61 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/addons/tvm_ffi_orcjit/README.md b/addons/tvm_ffi_orcjit/README.md index 06c087dc..0a3b491b 100644 --- a/addons/tvm_ffi_orcjit/README.md +++ b/addons/tvm_ffi_orcjit/README.md @@ -198,7 +198,7 @@ Compile: `clang -O2 -c -o example.o example.c` - **DLL Imports** (Windows): A custom `DefinitionGenerator` resolves host process symbols from loaded DLLs. AMD64 uses JITLink pointer and jump stubs; ARM64 uses RuntimeDyld's native import slots and branch stubs. -- **SEH Stripping** (Windows): `ObjectTransformLayer` strips `.pdata`/`.xdata` +- **SEH Stripping** (Windows AMD64): `ObjectTransformLayer` strips `.pdata`/`.xdata` relocations from COFF objects. C++ exception handling on Windows remains unsupported on both architectures. diff --git a/addons/tvm_ffi_orcjit/tests/test_basic.py b/addons/tvm_ffi_orcjit/tests/test_basic.py index b2f82700..52f8ecc2 100644 --- a/addons/tvm_ffi_orcjit/tests/test_basic.py +++ b/addons/tvm_ffi_orcjit/tests/test_basic.py @@ -25,6 +25,8 @@ the module tears the dylib down. from __future__ import annotations import gc +import platform +import shutil import sys import tempfile import threading @@ -487,6 +489,65 @@ def test_ctor_dtor(v: Variant) -> None: assert "<dtors>" not in log [email protected]( + sys.platform != "win32" or platform.machine().lower() not in ("arm64", "aarch64"), + reason="RuntimeDyld COFF lifecycle recovery is specific to Windows ARM64", +) +def test_failed_materialization_does_not_retain_crt_callbacks( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """A failed object cannot leave callbacks in the next module's lifecycle.""" + compiler = shutil.which("clang-cl") + if compiler is None: + pytest.skip("clang-cl is unavailable") + monkeypatch.setenv("CC", compiler) + source = Path(__file__).parent / "sources" / "c" / "test_ctor_dtor.c" + failing_source = tmp_path / "failed_ctor.c" + failing_source.write_text( + source.read_text().replace( + "static void puts_log(const char* msg) {", + "extern void tvm_ffi_test_unresolved_symbol(void);\n" + "static void puts_log(const char* msg) {\n" + " tvm_ffi_test_unresolved_symbol();", + ) + ) + failed_obj = tvm_ffi.cpp.build( + name="failed_ctor", + sources=[str(failing_source)], + output="failed_ctor.o", + extra_cflags=["/GS-"], + build_directory=str(tmp_path / "build"), + ) + log: list[str] = [] + + @tvm_ffi.register_global_func("append_log", override=True) + def append_ctor_log(value: str) -> None: + log.append(value) + + session = ExecutionSession() + failed = None + with pytest.raises(Exception, match="Failed to materialize|Symbols not found"): + failed = session.load_module(failed_obj) + failed.get_function("main") + del failed + gc.collect() + assert log == [] + + mod = load("c/test_ctor_dtor", session=session) + mod.get_function("main")() + del mod + gc.collect() + assert log == [ + "<crt.XCA>", + "<crt.XCB>", + "<crt.XCC>", + "<crt.XCU>", + "<main>", + "<crt.XTA>", + "<crt.XTZ>", + ] + + @pytest.mark.skipif( sys.platform == "linux", reason="ELFNixPlatform completes initialization before load_module returns",
