4 ms·
It's interesting to see which things Rust has defined where C refused to, such as fixing a strict evaluation order (mostly post-order on the AST), requiring sig
by eddyb 8y ago
It's interesting to see which things Rust has defined where C refused to, such as fixing a strict evaluation order (mostly post-order on the AST), requiring signed integers to be 2's complement or masking shift amounts (`x << n` being `x << (n % bitwidth)`).
Where does C actually gain anything nowadays? Signed integer UB is mostly useful for optimizing misuses of `int` for unsigned values (https://news.ycombinator.com/item?id=17191295 https://news.ycombinator.com/item?id=17191295), and is evaluation order even relevant anymore? (I don't think clang can pass that information down to LLVM, at all)
The only example I gave which has known drawbacks is the shift one, where modern platforms differ in the behavior, and LLVM will only optimize out the masking of the shift amount on the platforms that have that same behavior in their shift instructions (I think x86, but not ARM).
However, even if you make all of these changes to C, there's still a lot of UB left, in the form of memory accesses, which is much harder to get rid of (see the other comments, some of which mention Rust as well).
- kazinator 8y ago> I don't think clang can pass that information down to LLVM, at all I.e. you mean that the compiler front end has to choose an order without knowing which order will be good for LLVM, and there is no information to say "I don't actually need this specific order; pick another one that is better".
- pcwalton 8y agoI can't think of a case in which changing the evaluation order between sequence points in a way that LLVM can't prove is safe on its own actually improves codegen.
- deleted 8y ago[deleted]
- eddyb 8y agoWasn't the ordering thing in C for stack push order in calling conventions? At least that's one theory I've heard.
- kazinator 8y agoUnspecified evaluation order helps dumb compilers produce better code. Whenever a particular evaluation order is convenient in order fit some canned code generation pattern, like a function call or whatever, that desired evaluation order can just be blindly used, rather than following forced evaluation order (using temporaries to hold the results). Compilers for languages with strict evaluation order can still perturb evaluation order when it is safe to do so: like when expressions do not have side effects, or have effects that don't mutually interfere and are not external. They can thus avoid or eliminate the temporaries. C is still being specified like it's 1982 and compilers have to run in a few kilobytes of RAM, in a single pass, and go straight from source to target machine code.