Repository navigation
@cpp calls pass records by value and read them back from registers as each C++ ABI does - #578
Merged
Merged
Conversation
… each C++ ABI does A C++ (virtual) method taking a trivially copyable struct by value, or returning one in registers, now works through a @cpp class, and tsbindgen emits such methods instead of skipping them. LowerToLLVM (lowerCppCallArgs, for call and invoke): a tuple argument of a @cpp call is passed from a zeroed copy as the target passes the record (TargetInfo::cppRecordAbi): - MSVC x64: 1, 2, 4 or 8 bytes in a register as an integer of its size, any other by a pointer to the copy; - SysV x86-64: up to 16 bytes of integers and pointers in one or two 64-bit registers when that many of the six remain, else on the stack, as a bigger one is (byval); - AAPCS64: up to 16 bytes as [N x i64] (registers all or none), a bigger one by a pointer to the copy. A tuple the Itanium ABI returns in registers (any trivial record of up to 16 bytes of integers and pointers, not only one or two 8-byte fields) is read back from i64 / {i64, i64} / [2 x i64]. Floating-point records on the Itanium targets (SSE registers, HFAs) are an error, and so is a trivial record of more than 16 bytes returned unmarked (@cppnontrivial). MLIRGen: records by value in non-virtual methods and in methods with a body are errors. tsbindgen: a virtual method's by-value record parameter is its own type, unless it isn't trivially copyable (MSVC would destroy a RefCountPtr in the callee), a union, or (Itanium) has floating-point fields; a record result of more than 16 bytes is @cppnontrivial under the Itanium ABI. Tests: abi_host.cpp's byValue/pair/flags/r12 (records of 3 to 24 bytes), run against MSVC (test-jit-cppvtable-abi) and, on Linux, g++; the IR of each ABI's calls (test-compile-cppvtable-records-*); floating-point errors; tsbindgen's unit tests. Verified against g++ on x86-64 too: the same check compiled with pre-alpha101 fails both by-value cases. 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.
A
@cppclass can now call C++ virtual methods that take a trivially copyable struct by value, or return a small one in registers.tsbindgenbinds such methods instead of skipping them.tslang
LowerToLLVM(lowerCppCallArgs, on both call and invoke): a tuple argument of a@cppcall is copied into a zeroed slot and passed the way the target passes the record.TargetInfo::cppRecordAbiselects the rules:byval)[N x i64], which the backend places all in registers or all on the stackA tuple the Itanium ABI returns in registers is read back from
i64/{ i64, i64 }/[2 x i64]. That now covers any trivial record of up to 16 bytes of integers and pointers, not only one or two 8-byte fields.These are errors rather than wrong calls:
@cppnontrivial);tsbindgen
RefCountPtrin the callee and release a reference the caller never added),@cppnontrivial.docs/cpp-classes.md("Structs passed by value") and the README document this, including the cases left out.Tests
abi_host.cppgainsbyValue(records of 4, 8, 12, 16 and 24 bytes, then anint),pair,flags(threebools) andr12(12 bytes). It runs against MSVC intest-jit-cppvtable-abiand against g++/clang on Linux CI. The callee changes its by-value copies, and the test checks that the caller's tuples are unchanged.test-compile-cppvtable-records-{msvc,x86_64,aarch64}check each ABI's call shape in the IR on any host.itanium_float_param.tsanditanium_record.ts(now floats) cover the errors.TsClangImporterTestsgainRecordsPassedByValueandRecordsReturnedInMemoryOrFloatRegisters.Downstream
native_ts_graphics'
tools/gen_nvrhi_classes.pyhand-wrote 11 NVRHI methods per ABI because tsbindgen skipped them. With this change tsbindgen binds them all. A local build against this tslang passesnvrhi_directandheadlesson D3D12 and Vulkan (-debug) and on Android x86_64 and arm64. That cleanup lands after a release.🤖 Generated with Claude Code