7 ms·
> You see the problem. My C++ code expected the calling convention that pushed arguments on the stack, that would be very weird on Linux. The x86_64 linux ABI
by jcelerier 5y ago
> You see the problem. My C++ code expected the calling convention that pushed arguments on the stack,
that would be very weird on Linux. The x86_64 linux ABI mandates that the first arguments go on registers afaik (I'm assuming x86_64 here since the post mentions linux distros which are overwhelmingly x64). What compiler would default to a pure stack-based calling convention ? Certainly not GCC or clang, no ?
> and the kernel expected my code to pass arguments in the registers.
so, how is that a problem with C++ and not the compiler defaults ?
> I found the real gold mine of C++ kernel module development knowledge in OSDev.org. They have an entire article on C++ issues. That includes avoiding templates
bullshit it is then. https://www.youtube.com/watch?v=A_saS93Clgk https://www.youtube.com/watch?v=A_saS93Clgk
if templates are good (sometimes better even) on AVR microcontrollers with memory in kilobytes, there's no reason to not use them in a kernel meant to run on large embedded.
Also what's that rant about strings for ? In the end there is zero substance to this article, only very strange rants.
- 10000truths 5y ago> that would be very weird on Linux. The x86_64 linux ABI mandates that the first arguments go on registers afaik (I'm assuming x86_64 here since the post mentions linux distros which are overwhelmingly x64). What compiler would default to a pure stack-based calling convention ? Certainly not GCC or clang, no ? The System V i386 ABI passes parameters through the stack. Perhaps that is what the author is referring to, although I wouldn't be surprised if he mixed it up with the x64 ABI.
- saagarjha 5y agoThe 32-bit Linux kernel uses a register-based ABI internally, rather than System V.
- ivegotnoaccount 5y agoIn case it is talking about the x64 calling convention, there is actually some kind of an odd case where you would get something that looks like an argument was pushed on the stack: When a non-trivially-copyable object is passed by value to a function, you need to ensure that through the lifetime of the copy, it's address will never change because the constructor may have stored address of some of the field (for instance, a pointer to a field). The way this is handled at list in the SystemV x84_64 ABI is that the object is created on the caller's stack, and a pointer to it is stored in a register, so just like if it was passed as a pointer. I have seen several cases where a header would have an "ifdef c++" clause with copy constructors and destructors in them ("It does not add field so it should be OK, right ?"), which make the object non trivially-copyable, leading to clashing calling convention between C and C++ codes. I am curious about if this may be the issue he encountered.
- ivegotnoaccount 5y agoToo late to edit so I'll just write a message here: The hypothesis written above would not explain the author's complains as he mentions he was able to fix it with a compilation flag, whereas I doubt the compiler would change non-trivially-copyable being handled as reference to a copy since it would break correctness.
- inkyoto 5y ago> The System V i386 ABI passes parameters through the stack. No. The C/C++ ABI is quite uniform across architectures. The first 1..N (N is ISA dependant) parameters that can fit into a CPU register are passed via registers. The first input parameter that _can't_ fit into a register (e.g. a structure passed by value) is pushed onto the stack, with every other following parameter being pushed onto the stack as well. N+1… parameters are always passed through the stack.
- cesarb 5y ago> No. The C/C++ ABI is quite uniform across architectures. The first 1..N (N is ISA dependant) parameters that can fit into a CPU register are passed via registers. Here is the "System V i386 ABI" mentioned above: https://refspecs.linuxfoundation.org/elf/abi386-4.pdf https://refspecs.linuxfoundation.org/elf/abi386-4.pdf (from https://refspecs.linuxfoundation.org/ https://refspecs.linuxfoundation.org/). It clearly passes all arguments on the stack, and none on registers ("Function Calling Sequence" starting on page 35). That is the ABI used on 32-bit x86 Linux if you don't specify -mregparm (which the kernel uses); since the author was calling the compiler directly (which was necessary because the kernel makefiles only have rules for building C files, not C++ files), there was a mismatch between the -mregparm used by the kernel and the default ABI used by the C++ compiler, which was fixed by also passing -mregparm to the C++ compiler.
- inkyoto 5y agoYou are not incorrect, and I shall ruminate on why I had thought that the SysV ABI on i386 used %rax ÷ %rex as input function parameters without having to resort to the use -mpregparm. Thanks for the correction.
- deleted 5y ago[deleted]
- chrisseaton 5y ago> The C/C++ ABI is quite uniform across architectures. How can it be? What about an architecture without conventional registers? And for example I work on an implementation of C/C++ that logically uses the heap for its ABI.
- saagarjha 5y agoPerhaps the article is old enough to have been written in the 32-bit era?
- jcranmer 5y agoThe Page Info I see says this: > article:published-time 2016-10-28T11:40:06+00:00 which is well into the era of 64-bit code.
- olliej 5y agoPeople are still complaining about macOS dropping 32bit despite the last 32bit hardware having been dropped a decade ago. Some people (especially game devs) are bizarrely obsessed with 32bit :-/
- pajko 5y agoThe LDD3 mentioned is 32-bit era, and 2.6.x kernel, which had a CONFIG_REGPARM to allow passing parameters in registers (because the default was not to do that).
- varajelle 5y ago> so, how is that a problem with C++ and not [...] I don't think you should see this article as a criticism of C++. Just a rent on how hard it is to use in the Linux kernel which is openly against it.
- kevin_thibedeau 5y agoAVRs don't have enough storage for templated code to explode into an unmanageable problem.
- pjmlp 5y agoSomehow C64 can deal with them. "CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17”" https://www.youtube.com/watch?v=zBkNBP00wJE https://www.youtube.com/watch?v=zBkNBP00wJE "C++20 For The Commodore 64" https://www.youtube.com/watch?v=EIKAqcLxtT0 https://www.youtube.com/watch?v=EIKAqcLxtT0
- tialaramex 5y agoBut a C64 is still only talking about 64kB of RAM. The post you're replying to claims that Template complexity gets unreasonable on a large machine, such as a Linux system. Not sure I agree, but "it's fine on a C64" isn't evidence in your favour unless you've forgotten Linux doesn't even run on a Commodore 64.
- pjmlp 5y agoSo it is fine on a 64KB system, but unmanageable on a platform that gets all the different kinds of boilerplate to run cloud workloads, got it
- tialaramex 5y agoI mean, apparently this is confusing, but yes, obviously. If your Commodore 64 template is dealing with say, foozles that might be 8-byte, 12-byte or 16-byte, the complexity incurred is pretty small, bugs with foozle<16> are likely to be something mere mortals can understand and fix. On a more complicated system like a cloud Linux setup the template may be for foozles that can be in any colorspace and on a remote machine or locally, and now sometimes the bug with foozle<HSV,remove> involves a fifty line error message because the compiler doesn't realise all that happened is you meant to write foozle<HSV,remote> ... It's not even as if the C++ committee isn't aware that templates are a problem. Remember template meta-programming wasn't really intended from the outset, and a big part of the point of Concepts was to at last let you write code that compilers can provide readable errors for when it's wrong.