Unnecessary hubris. I assure you the original ABI authors were plenty smart and just faced a different set of problems.
> Our forebears are either not interested in a world without the mounting, crushing debt or just prefer not to tackle that mess right now
The article mentions the organizational/social part of this problem, but then goes on to drop this turd.
I can also assure you that our forebears were neither malicious or lazy; but faced the same problem this proposal does.
I don’t like seeing such disrespect for the folks who laid out the groundwork for us.
You're taking the idea of respect too far.
The Assembly like abilities have been growing as language extensions in specific compilers, not as part of ISO C.
Going back to K&R C, inline Assembly or intrisics were not even available, all of that required using the Assembler directly.
ABIs are defined by CPU and operating system vendors. Those ABIs usually happen to be quite 'C friendly', but that's not a requirement (for instance the AmigaOS ABI was primarily meant to be used from handwritten assembly code, and Amiga C compilers had to adapt to those ABI rules or they wouldn't be able to call into the operating system DLLs).
Personal pet theory: C is portable as in "you can retarget the compiler to any machine" moreso than "your code will run on any machine".
Because in hardware, programmers, aside from researchers, are often paid much less and work in worse conditions compared to their software counterparts. At a software company, code is the product itself. But in manufacturing, software is treated as a cost attached to machines worth billions of dollars. While equipment and sensors keep getting updated and more expensive, the people connecting everything are seen as a cost cutting target. So hardware programmers generally have good job security, but their salaries aren't high. In that situation, asking them to learn something new instead of sticking with the old ways usually gets resistance, because they're not being properly compensated for that learning
And on top of that... these things are battle tested, often running machinery that isn't just worth millions of dollars but runs goods worth orders of magnitude more. Stuff breaking because some new shiny thing has been introduced... no one bats too much an eye when Reddit's UI is missing a widget here and there because someone pushed vibecoded garbage to prod again, but a car manufacturing line? A chemical plant that needs to operate 24/7 so that nothing solidifies in pipes, wrecking the entire facility to the point you need to fully dismantle it?
When this kind of consequences are in the air, everyone is much much more conservative, because no one wants to be left holding that bag.
It's not just legacy code. Some of it is literally certified, that is, it has gone through a certification process. That is a slow and expensive thing to redo; nobody wants to do it for a change that doesn't add real user value.
> at least we’ll finally have the chance to have that discussion [about breaking ABI] with our communities, rather than just being outright denied the opportunity before Day 0.
[0]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2901.htm
[1]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3913.htm
Conceptually intmax_t is a generic type of the form intmax_t<T>. Since C does not have generics, the T is chosen by the compiler during compile time.
But this means that the first time you compile any shared library with an intmax_t parameter or return value in one of its functions, you have permanently baked in the type parameter T to whatever the compiler chose it to be at that moment in time.
You cannot retroactively change intmax_t even if you change the symbols, because intmax_t runs into the same problem any generics system does, you cannot retroactively add instantiations for future types that were not explicitly compiled into the dynamic library.
Even if C gets generics and intmax_t would become obsolete either way, because you don't need intmax_t<T>, you can just have T.
intmax_t is only interesting for choosing the T and even then it is only interesting inside function implementations and never in their signatures.
So my conclusion is that intmax_t was a failed attempt at trying to be "clever" with the idea of introducing generics without introducing generics. This is an idea that is so doomed that anyone trying to rescue it, didn't really understand the problem with intmax_t.
- 2023-06-10, 64 points, 16 comments: (https://news.ycombinator.com/item?id=36249253)
- 2022-03-13, 175 points, 129 comments: (https://news.ycombinator.com/item?id=30660528)
One may say, that shared libraries can save some space for both disk storage and RAM. But such savings aren't that huge and in some cases are even negative - if a library is linked-in, it's possible to discard unused functionality and even inline many library functions.
If you statically link a cryptography stack, you suddenly need a lot more information about what certificate/cipher systems are available on the host via IPC. If you statically link media codecs, you suddenly need a lot more information about hardware acceleration from the host via IPC. If you statically link libraries to manipulate binary data in some shared format, you need extra code to runtime-determine things like endianness. If you're asking hardware to do chunky numerical math, suddenly you need to prepare data with specific widths/sizes and you need to determine that from somewhere.
Windows did good work here with COM, but the average windows app is both more self-contained and targets fewer configurations than a Linux app, so many of those issues don't come up as often as they do on Linux. Linux has a long way to go here, both because there's nothing as capable/ubiquitous as COM there, and because so much Linux software is small and therefore necessarily not self-contained (not talking about the UNIX philosophy and shell tools here--talking more about runtime intermediate layers like VAAPI or compat shims or protocols with multiple implementations).
In the end, OS/CPU combinations define ABIs, compiler toolchains (no matter what language) can't do much more then follow (if they want to be able to talk to the operating system at least). E.g. if one day operating systems implement stable Rust-friendly ABIs, then C compilers will have to adapt to those conventions instead.
See https://faultlore.com/blah/c-isnt-a-language/ for more detailed analysis.
I think defining a constant function pointer should work. As long the compiler doesn't store this pointer in the result executable and optimizes-out all calls via it into calls to the source function.
When Rust chose an unstable ABI it did so for a good reason. I personally think the only place where a stable ABI would be warranted is inside the panic machinery and this is mostly because it is kind of annoying to write perfect no panic Rust just to get rid of the 300KiB overhead but even here I'd take my time, possibly decades, before making the decision to have a stable ABI.
The wrong decision is to choose to support a stable ABI and lock in design mistakes early on.
I'm already hinting at the solution so I'll be taking my leave for now.
In my opinion, that's the correct thing to do anyhow, even for bigger systems
[0]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3913.htm
Does it follow the lua spec?
How are tables implemented?
How fast is it compared to normal Lua, luajit interpreter, and luajit jit?
C doesn't need saving, it will continue to survive on its own and even flourish in niches for decades to come. So will "Java"Script. Worse is Better, respectfully, or at least Old and Simple is Tough as F, living long and prosper. See, C doesn't need you but we need C, apparently for the foreseeable future.
Rust is the new black and it will supplant C/C++ and almost everything else short of virtual machine languages like Java/C#.