> Sure it is, that was the official way to differentiate code across Windows form factors for WinRT during Windows 8.x days.

Thanks, I didn't know that. It doesn't really impact my point though, it just means the .Net IR is less portable than I thought. The point here is to have one portable IR for C code, after all, like Java bytecode. (Well, disregarding the other Java platforms such as Java ME, that is.)

> So how come Apple and NVidia are able to massage LLVM bitcode to serve their purposes?

I don't know specifics here but presumably they have significant control over the hardware and aren't aiming for extreme portability. Are they intending to support 32-bit, 64-bit, various endiannesses, exotic platforms that don't use 2's complement and don't represent NULL as bitwise zero, etc? All from the same IR?

Java supports all such platforms by forcing them to behave the Java way. Java's long is defined to be 64-bit and use 2's complement representation, regardless of the workings of the underlying hardware.

C supports full-speed execution on all such platforms as it permits its behaviour to vary depending on the target platform. This is part of why the C spec is so loose about how the compiler/platform may behave. What are the values of MAX_INT and MAX_LONG? The spec doesn't dictate their values, although it does give lower bounds.

You can't have it all, especially with C where even allocating an array of long requires using sizeof(long). You could mandate in your IR that long is 64-bit, but this means you've changed the behaviour of the C program when running on an LLP64 [0] platform, which must now emulate the 64-bit behaviour. There's similar trouble with pointers. If you mandate that pointers are 64-bit, you'll damage performance on 32-bit machines, unless the (native-code) compiler is somehow smart enough to optimise it back down to the native 32-bits.

And this is assuming no preprocessor trouble, which might be acceptable in a controlled environment but isn't acceptable in a universal C bytecode that can do everything C source-code can.

Again I'm not saying you can't define an IR for C for certain purposes, my issue is with a universal IR. It's not the same as defining an IR for a family of related products, as we see with GPUs and mainframes.

Could you define such a limited-portability IR for your new OS that runs on x86-64, RISC-V, and AArch64? Probably. Would it really help? I doubt it. You can already write portable C programs if you know what you're doing and do adequate testing. If you want a language that gives you robust assurances of platform-independence, you shouldn't be using C in the first place. (From our previous discussions I believe we're both of the opinion it's a bit of a pity Ada sees so little general use these days.)

It would presumably be possible to define a coding-standard a bit like MISRA C that prohibited anything platform-specific, for instance by banning general use of int and long and insisting on using the fixed-width types. It would also have the difficult job of prohibiting undefined behaviour. There's the ZZ project which does something vaguely along these lines, but it defines a whole new language that compiles to C. [1]

> Deciding that they don't want to keep backwards compatibility is definitely politics.

At the risk of a boring discussion on semantics, that doesn't sound to me like politics. Declining to be saddled with a commitment to backward compatibility, is a technical decision intended to permit future improvements.

LLVM chose a permissive licence to keep Apple happy, in contrast to GCC. That counts as politics.

[0] https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_m... (I figure you know this already, pjmlp, but it might be useful for someone else)

[1] https://github.com/aep/zz , see also https://news.ycombinator.com/item?id=22245409