Nice to see Haskell make an appearance in an article about Lua and C/C++:
> For example, at LLVM IR level, it is trivial to make a function use GHC calling convention (a convention with no callee-saved registers)
This refers to the following section of [1]
“cc 10” - GHC convention
This calling convention has been implemented specifically for use by the Glasgow Haskell Compiler (GHC). It passes everything in registers, going to extremes to achieve this by disabling callee save registers. This calling convention should not be used lightly but only for specific situations such as an alternative to the register pinning performance technique often used when implementing functional programming languages. At the moment only X86 supports this convention and it has the following limitations:
On X86-32 only supports up to 4 bit type parameters. No floating-point types are supported.
On X86-64 only supports up to 10 bit type parameters and 6 floating-point parameters.
This calling convention supports tail call optimization but requires both the caller and callee are using it.
I didn't realise LLVM supported such a wide variety of calling conventions.
It would be cool if they supported OpenVMS/x86-64 calling convention–even not on OpenVMS. Why? Well, OpenVMS calling convention has this cool little feature which nobody else seems to have – the parameter count to a function is passed in a register. What this means–people always ask "how can a C variadic function know how many parameters it was passed?" And the usual answer is – you need to add an argument to explicitly pass an argument count (the computation of which can be automated using preprocessor voodoo), or you need to pass some kind of printf-style format argument, or a sentinel value (terminal NULL), or whatever. "Why can't we just have a va_count() which tells us how many arguments we were passed?" "Not possible, per the calling convention, the caller doesn't tell us."
However, for OpenVMS, there actually is such a thing as va_count() – it pulls it from that extra register (the "Argument Information Register"–which also encodes some info on their types, so you can know whether each parameter is passed in an integer register or a floating point one.) Anyway, if LLVM/Clang/etc supported OpenVMS calling convention on other platforms, they could enjoy va_count() too, you'd just have to declare that as the calling convention for your function.
It only uses %al and leaves the upper 56 bits of %rax undefined. OpenVMS adds an arg count in %ah and then uses the rest of the register to hold bitmasks showing whether each register-passed argument was integer or float, and also (optionally) a pointer (stored as offset from call address) to a data structure containing type info for the stack arguments.
Optimising variadic functions seems fairly low value but given they're usually a different calling convention anyway passing an extra integer is probably harmless.
From what I understand, VSI's C compiler for OpenVMS/x86-64 actually gives you a choice of two different variadic calling conventions - something very close to standard SysV ABI x86-64 (which doesn't pass parameter count and type info), and the OpenVMS extension which adds that. So, while I doubt one extra "mov rax, CONSTANT" is going to be noticed (variadic function calls are rarely found on performance-critical code paths), if a function doesn't need va_count(), it can turn that off.
From what I understand, their x86 C and C++ compilers are a patched version of clang/LLVM – they've said they planned to upstream their changes, I don't think it has happened yet, but I hope it does. (Their other compilers – COBOL, Fortran, Pascal, BASIC, BLISS, MACRO – are also using LLVM as backend on x86-64, but with their legacy frontends.)
Haskell and Pandoc has too much dependency bloat. Just installing Pandoc on Arch requires like 200MB in dependencies, and over hundred haskell specific dependencies.
Well, firstly, I’d note that Haskell on Arch (including Pandoc) is broken, mostly due to the fact that Arch likes to dynamically link everything and Haskell doesn’t (see also https://www.reddit.com/r/haskell/comments/yuwcei). But yes, Haskell packages do often tend to have quite a lot of dependencies. To some extent this is because the base library is very much ‘batteries-excluded’, so dependencies are necessary for things like file management and byte strings and so on, but I do see quite a few dependencies which could be split up (e.g. ‘servant-server’, a big dependency used to create a webserver in exactly one module of pandoc).
> For example, at LLVM IR level, it is trivial to make a function use GHC calling convention (a convention with no callee-saved registers)
This refers to the following section of [1]
“cc 10” - GHC convention This calling convention has been implemented specifically for use by the Glasgow Haskell Compiler (GHC). It passes everything in registers, going to extremes to achieve this by disabling callee save registers. This calling convention should not be used lightly but only for specific situations such as an alternative to the register pinning performance technique often used when implementing functional programming languages. At the moment only X86 supports this convention and it has the following limitations:
On X86-32 only supports up to 4 bit type parameters. No floating-point types are supported. On X86-64 only supports up to 10 bit type parameters and 6 floating-point parameters. This calling convention supports tail call optimization but requires both the caller and callee are using it.
[1] https://llvm.org/docs/LangRef.html#calling-conventions