Date: Mon, 2 Jun 2025 09:14:13 +0000
> > If you want to communicate with code that already exists you need to be able to talk its language.
> No, if you want to interact with a given ABI you must respect that ABI. On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS. Again, the ABI of the platform defines the ABI you must use if you want to interact with the OS. Similarly, if you don’t match the C++ ABI you will break when you interact with the OS.
I'm not talking about "language" as in "programming language" but a more generic "conventions how 2 things communicate", where you put the bits and the bytes.
> On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS.
Let's talk specifics here, which modules are we talking about?
ntdll.dll?
KERNEL32.DLL?
ucrtbase.dll?
Which ones are a fundamental part of the OS and which ones have any "C++ interfaces" at all?
Be more specific, when you say Windows doesn't follow this ABI, do you mean ntdll.dll doesn't follow this ABI for this specific method?
-----Original Message-----
From: Oliver Hunt <oliver_at_apple.com>
Sent: Monday, June 2, 2025 8:47 AM
To: Tiago Freire <tmiguelf_at_[hidden]>
Cc: std-proposals_at_lists.isocpp.org
Subject: Re: [std-proposals] Standard support for different ABI's for class vtables
> On Jun 1, 2025, at 11:09 PM, Tiago Freire <tmiguelf_at_hotmail.com> wrote:
>
> I think there's a problem with actually understanding the problem.
>
> And ABI is not an "operating system" thing. IT ISN'T!
> There's nothing right now that would stop a compiler from generating code with a different ABI and have it work, no matter which OS you are talking about.\\
You can have any compiler, for any language, that is free to use whatever abi it wants to interact with itself.
But the original complaint was about msvc doing something different from other compilers, because msvc generates code that interacts *correctly* with the C++ interfaces provided by the OS. Very simply: dynamic_cast is provided by the platform. If you generate code that does not conform to the platform ABI, then dynamic_cast will not work. If you try to provide your own definition of dynamic_cast then you will break platform code. If you throw exceptions and want them to be handled correctly, then the type_info generated by your compiler must match the type_info expected by OS code, and similarly your generated exception handlers must be able to recognize the platform provided types.
If you do not care about interacting with the OS, then it does not many what calling convention you use. It does not matter how you implement polymorphism. It does not even matter what your compiler uses for “standard” calls.
The moment you want to interact with the OS, you do not get to choose your own adventure through the ABI, you must respect the platform ABI.
*If* msvc were to add darwin or linux targets, we would not accept complaints from MSVC engineers about stdlibc++ or libc++ using a different ABI from what they emit or expect, and the same thing applies in reverse.
>
> It's only important that your ABI be a certain way when you are interacting with other modules that you haven't written/compiled yourself and that already existed as utilities for that OS.
Correct - if you are wanting, as the original post author did - to interact with the OS, your ABI is defined by the OS. If you aren’t, then the OS ABI does not matter, but that’s because an ABI you aren’t interacting with by definition is irrelevant.
> If you want to communicate with code that already exists you need to be able to talk its language.
No, if you want to interact with a given ABI you must respect that ABI. On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS. Again, the ABI of the platform defines the ABI you must use if you want to interact with the OS. Similarly, if you don’t match the C++ ABI you will break when you interact with the OS.
> But if you are not, you don't have too, and there's nothing that stops the OS from providing libraries that "speak different languages". You don't want to do that for ease of maintainability, but you can do it.
Yes, but that’s not relevant here. The question is solely about C++. Windows and darwin at least provide system libraries with C++ interfaces, and the ABI presented by those interfaces is the ABI that all C++ on those platforms is expected to use. Hence, that is the platform C++ ABI.
> It's like the line ending thing "CRNL" or "NL", also not an OS thing, at least not anymore, it's a choice of editor problem now, and even so not even that.
Yes, but if the platform says you use one of them, that’s what you have to use, even if you don’t want to, or disagree with the choice, anything else is arguing with reality.
> And we have already ways to "manipulate" the ABI in a way, in the form of annotations for calling conventions (not portable as they might be), could be extended to classes as a way to implement such a feature if you really wanted to. But the question is, why would you want it too?
Yes you can, and if you do so, you do so in the knowledge that those manipulations are not abi compatible with the rest of the code on the platform.
A “fastcall” (or whatever the old x86 “use more registers to call” annotation was) function cannot be passed by pointer to a API saying “I expect the platform ABI"
>
> Again, the standard doesn't know what a dll is, external code is not a thing that it is prepared to tackle at this point (unless there is a comprehensive work group).
Correct, which is why the original post complaining about the reality of the windows abi not matching their personal preference is incorrect. The standard does not define the ABI for polymorphism in C++, the OS does. Because if you want C++ TU a to interact correctly with TU b, and TU c, then a, b, and c must agree on that ABI, and if one of a, b, or c, is the OS, that is the ABI definition that wins.
This applies to C++ polymorphism just as much as it applies to C function calls. Again `void(*)(long double)` has one ABI on win64, and a different one on darwin, and maybe linux (I’m really not sure), a compiler that generates calls, or callees, expecting a calling convention that does not match other platforms on the same hardware, is wrong. Because the OS is what defines the standard API for the system. If you are not interacting with any other code then that’s entirely moot, that’s what (in principle) allows the compiler or LTO, etc to change calling conventions for functions that do not escape.
—Oliver
> No, if you want to interact with a given ABI you must respect that ABI. On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS. Again, the ABI of the platform defines the ABI you must use if you want to interact with the OS. Similarly, if you don’t match the C++ ABI you will break when you interact with the OS.
I'm not talking about "language" as in "programming language" but a more generic "conventions how 2 things communicate", where you put the bits and the bytes.
> On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS.
Let's talk specifics here, which modules are we talking about?
ntdll.dll?
KERNEL32.DLL?
ucrtbase.dll?
Which ones are a fundamental part of the OS and which ones have any "C++ interfaces" at all?
Be more specific, when you say Windows doesn't follow this ABI, do you mean ntdll.dll doesn't follow this ABI for this specific method?
-----Original Message-----
From: Oliver Hunt <oliver_at_apple.com>
Sent: Monday, June 2, 2025 8:47 AM
To: Tiago Freire <tmiguelf_at_[hidden]>
Cc: std-proposals_at_lists.isocpp.org
Subject: Re: [std-proposals] Standard support for different ABI's for class vtables
> On Jun 1, 2025, at 11:09 PM, Tiago Freire <tmiguelf_at_hotmail.com> wrote:
>
> I think there's a problem with actually understanding the problem.
>
> And ABI is not an "operating system" thing. IT ISN'T!
> There's nothing right now that would stop a compiler from generating code with a different ABI and have it work, no matter which OS you are talking about.\\
You can have any compiler, for any language, that is free to use whatever abi it wants to interact with itself.
But the original complaint was about msvc doing something different from other compilers, because msvc generates code that interacts *correctly* with the C++ interfaces provided by the OS. Very simply: dynamic_cast is provided by the platform. If you generate code that does not conform to the platform ABI, then dynamic_cast will not work. If you try to provide your own definition of dynamic_cast then you will break platform code. If you throw exceptions and want them to be handled correctly, then the type_info generated by your compiler must match the type_info expected by OS code, and similarly your generated exception handlers must be able to recognize the platform provided types.
If you do not care about interacting with the OS, then it does not many what calling convention you use. It does not matter how you implement polymorphism. It does not even matter what your compiler uses for “standard” calls.
The moment you want to interact with the OS, you do not get to choose your own adventure through the ABI, you must respect the platform ABI.
*If* msvc were to add darwin or linux targets, we would not accept complaints from MSVC engineers about stdlibc++ or libc++ using a different ABI from what they emit or expect, and the same thing applies in reverse.
>
> It's only important that your ABI be a certain way when you are interacting with other modules that you haven't written/compiled yourself and that already existed as utilities for that OS.
Correct - if you are wanting, as the original post author did - to interact with the OS, your ABI is defined by the OS. If you aren’t, then the OS ABI does not matter, but that’s because an ABI you aren’t interacting with by definition is irrelevant.
> If you want to communicate with code that already exists you need to be able to talk its language.
No, if you want to interact with a given ABI you must respect that ABI. On windows, the C++ ABI - as presented by C++ APIs present in the OS - is definitionally defined by the OS. Again, the ABI of the platform defines the ABI you must use if you want to interact with the OS. Similarly, if you don’t match the C++ ABI you will break when you interact with the OS.
> But if you are not, you don't have too, and there's nothing that stops the OS from providing libraries that "speak different languages". You don't want to do that for ease of maintainability, but you can do it.
Yes, but that’s not relevant here. The question is solely about C++. Windows and darwin at least provide system libraries with C++ interfaces, and the ABI presented by those interfaces is the ABI that all C++ on those platforms is expected to use. Hence, that is the platform C++ ABI.
> It's like the line ending thing "CRNL" or "NL", also not an OS thing, at least not anymore, it's a choice of editor problem now, and even so not even that.
Yes, but if the platform says you use one of them, that’s what you have to use, even if you don’t want to, or disagree with the choice, anything else is arguing with reality.
> And we have already ways to "manipulate" the ABI in a way, in the form of annotations for calling conventions (not portable as they might be), could be extended to classes as a way to implement such a feature if you really wanted to. But the question is, why would you want it too?
Yes you can, and if you do so, you do so in the knowledge that those manipulations are not abi compatible with the rest of the code on the platform.
A “fastcall” (or whatever the old x86 “use more registers to call” annotation was) function cannot be passed by pointer to a API saying “I expect the platform ABI"
>
> Again, the standard doesn't know what a dll is, external code is not a thing that it is prepared to tackle at this point (unless there is a comprehensive work group).
Correct, which is why the original post complaining about the reality of the windows abi not matching their personal preference is incorrect. The standard does not define the ABI for polymorphism in C++, the OS does. Because if you want C++ TU a to interact correctly with TU b, and TU c, then a, b, and c must agree on that ABI, and if one of a, b, or c, is the OS, that is the ABI definition that wins.
This applies to C++ polymorphism just as much as it applies to C function calls. Again `void(*)(long double)` has one ABI on win64, and a different one on darwin, and maybe linux (I’m really not sure), a compiler that generates calls, or callees, expecting a calling convention that does not match other platforms on the same hardware, is wrong. Because the OS is what defines the standard API for the system. If you are not interacting with any other code then that’s entirely moot, that’s what (in principle) allows the compiler or LTO, etc to change calling conventions for functions that do not escape.
—Oliver
Received on 2025-06-02 09:14:16