Repository navigation
Codegen picks the target's CRT, not the host's (Android cross-compile) - #506
Merged
Merged
Conversation
A failing assert, number-to-string conversion and a class's comdat were chosen with `#ifdef WIN32`, so a Windows-hosted tslang compiling for Android or Linux emitted MSVC's `_assert`/`sprintf_s` and an `exactmatch` comdat, which ELF cannot hold. They now follow the target triple (compileOptions.isWindows). Android also gets its own assert: Bionic exports `__assert(file, line, msg)` and `__assert2`, not glibc's `__assert_fail`, so `isAndroid` is set from the triple and AssertLogic calls `__assert` there. test-compile-target-crt emits IR for windows-msvc, linux-gnu and linux-android and checks each declares its own CRT's functions and comdat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`import './x'` looked for x.dll or libx.so by the host (WIN_LOADSHAREDLIBS / LINUX_LOADSHAREDLIBS from `#ifdef WIN32`). The path is also the one the program loads at run time, so a Windows-hosted build for Android baked in "./x.dll", and a Linux-hosted build for Windows looked for libx.so. It now follows the target OS, as --emit=dll's output name does (utils.cpp): Windows x.dll, otherwise libx.so. foreign-target-import builds its x64 DLL as libshared.so, the name an x86_64 Linux importer looks for (still a PE image inside), and checks the program loads libshared.so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 5, 2026
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.
Problem
Three codegen choices were made with
#ifdef WIN32, i.e. by the host the compiler was built on, not the target being compiled for. A Windows-hostedtslang -mtriple=aarch64-linux-android…therefore emitted:_assert(msg, file, line)for a failingassert(MSVC CRT only)sprintf_sfor number → string (MSVC CRT only)comdat exactmatchon class globals, which ELF cannot representFix
AssertLogic.h,LowerToLLVM.cpp(ConvertFOpLowering),MLIRGenClasses.cppnow usecompileOptions.isWindows(from the triple) instead of the host macro.__assert(file, line, msg)and__assert2(file, line, func, msg), not glibc's__assert_fail(checked against bioniclibc/include/assert.handlibc.map.txt). Without this, an Android object compiles but fails to link as soon asassertis used. AddedCompileOptions::isAndroid(Triple::isAndroid()), and AssertLogic calls__assertthere, with Bionic's argument order.snprintfandcomdat anyare correct for Bionic/ELF as is.*-windows-msvc_assertsprintf_sexactmatch*-linux-gnu(and other non-MSVC)__assert_failsnprintfany*-linux-android*__assertsnprintfanySide effect:
isWindowsis the MSVC-environment check, so wasm/emscripten built from a Windows host now gets__assert_fail/snprintftoo. Emscripten provides both, so that's a fix as well.Tests
test-compile-target-crt(test/tester/target-crt.cmake): emits LLVM IR forx86_64-pc-windows-msvc,x86_64-unknown-linux-gnuandx86_64-linux-android, and checks that each declares its own CRT's functions and comdat and none of the others'. IR only, so it's registered for every host. It fails against a pre-fix binary (the linux-gnu triple gets_assert).--emit=obj -mtriple=aarch64-linux-android21produces an ELF object. Not linked against a real NDK sysroot (no NDK on the dev machine).Shared-library import naming (2nd commit)
import './x'chosex.dllvslibx.sowithWIN_LOADSHAREDLIBS/LINUX_LOADSHAREDLIBS(host#ifdef WIN32inConfig.h). That path is also what the program passes toLoadLibraryPermanentlyat run time, so a Windows-hosted build for Android baked in./x.dll, and a Linux-hosted build for Windows looked forlibx.so.mlirGen(ImportDeclaration)now follows the target OS (Triple::getOS() == Win32), the same rule--emit=dllalready uses for its output name (utils.cpp). Windows givesx.dll; anything else giveslibx.so. Thelibprefix behaves exactly as before. The two macros are removed.foreign-target-import(x64 DLL imported by an x86_64-Linux program) now writes the DLL aslibshared.so, the name that target looks for (still a PE image inside). The not-PE case writeslibfoo.so, andreadalso checks that the program loadslibshared.so. Against a pre-fix binary,readfails (the import falls back toshared.tsas source).Not testable here: the newly enabled direction, a Linux host compiling for Windows and finding
x.dll. A Windows host can't read an ELF.so's declarations for a foreign target either (only PE is supported, as before).🤖 Generated with Claude Code