4 ms·
> What does LLVM have that can not be achieved 1 to 1 in C? Do you want to have signed integer overflow not be undefined behavior? Sorry, you can't do that in
by jcranmer 3y ago
> What does LLVM have that can not be achieved 1 to 1 in C?
Do you want to have signed integer overflow not be undefined behavior? Sorry, you can't do that in C. Do you want to support SIMD vector types? Oops, no support in C. Underaligned memory accesses? Packed structures? Support for handling unwind structures? Coroutines?
> It feels to me like C should be superior to LLVM and allow to do anything that is possible to do with LLVM, but maybe I'm wrong?
Very much the inverse: as LLVM is used to implement a C compiler, LLVM can faithfully reproduce all of the C semantics, but C cannot be used to implement all of the LLVM features. Even if you pretend C doesn't have undefined behavior, and even if you include compiler extensions as part of C, there are still a few LLVM instructions and intrinsics that just don't exist in C (chief among them is invoke, which is used to implement C++ exception handling).
- twic 3y agoSo how does the LLVM C backend work then? https://github.com/JuliaHubOSS/llvm-cbe https://github.com/JuliaHubOSS/llvm-cbe
- jcranmer 3y agoIt just doesn't support some features, and cheats in other areas. (At a quick glance, there's no support for invoke instructions, and the awkward floating-point types makes it go "oh, let's just use long double and hope it's correct for this platform").
- TazeTSchnitzel 3y agoAs a contributor to that project: with great difficulty. There are so many unfixed bugs and horrible workarounds and it will never generate good or even standards-compliant code. C and LLVM IR are both monsters with hundreds of subtle traps for the unwary, but at least C to LLVM IR is a well-trodden path with a friendly gradient. The reverse is an uphill struggle against entropy.
- pizlonator 3y ago> Do you want to have signed integer overflow not be undefined behavior? Sorry, you can't do that in C. Do you want to support SIMD vector types? Oops, no support in C. Underaligned memory accesses? Packed structures? Support for handling unwind structures? Coroutines? You can get those things with most C compilers via compiler flags or other extensions. You can handle unwinding by targeting C++ instead of C, or doing the unwinding in a totally custom way. The last JVM I wrote had a C backend that did unwinding. It worked with any C compiler. You wouldn’t want to use llvm’s unwinding for the unwinding of most higher level languages anyway. Coroutines can be lowered to C. Most coroutines in higher level languages work best when lowered to C-like functions that save/restore state as needed. Heck, JSC’s coroutines just lower to JSC’s internal notion of a regular function. > there are still a few LLVM instructions and intrinsics that just don't exist in C (chief among them is invoke, which is used to implement C++ exception handling). Right so if you’re implementing C++ then you probably want to compile to llvm not C. But if you have exception semantics that are sufficiently not like C++ then you’re better off handling them at a higher level and lowering to something that doesn’t rely on invoke. You can do that in C. More details: C++ exceptions and llvm invoke are optimized very aggressively for the case that no exceptions are thrown. If you compile Java, where some programs use exceptions for control flow, you’ll want an implementation that is less aggressively optimized for not throwing. And then if you do that then C is fine.
- omoikane 3y ago> support SIMD vector types I think these are supported through intrinsics, for example: https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html But I suppose they are not considered standard C.
- SAI_Peregrinus 3y agoThose are part of GNU C, not part of C, as you suppose.
- Someone 3y ago> Do you want to have signed integer overflow not be undefined behavior? Sorry, you can't do that in C. If you write a compiler that targets C, you can have that. ‘Just’ generate code that avoids it. If you want it to wrap around, for example, generate something like this (I’m not 100% sure it’s right)): int sum = (int)((unsigned int) a + (unsigned int) b); instead of int sum = à + b; If you want that to trap on overflow, the code gets more convoluted (see e.g. https://codereview.stackexchange.com/a/37178 https://codereview.stackexchange.com/a/37178 for what’s needed to detect overflow) Packed structures and unaligned data similarly can be supported by generating C code that manipulates char arrays instead of C structs. I wouldn’t count on having any C compiler generate efficient code for it, though. That applies to most of the other features, too. You can have garbage collection, exception handling and coroutines, for example, but if you generate C code implementing it, chances are zero that the C compiler turns that into efficient code.