3 ms·
... what does this even mean? As a compiler--indeed, optimization--developer, one of the things that continually frustrates me about discussions on UB is that
by jcranmer 2y ago
... what does this even mean?
As a compiler--indeed, optimization--developer, one of the things that continually frustrates me about discussions on UB is that so many suggestions are based on just complete incomprehension of how compilers work. One of the first things compilers do is throw away the original source code; outside of initial front-end codegen, there is no reference to the original AST, and instead everything is based on a pseudo-assembly IR. A concept like an "entire line of code" just doesn't exist in IR; even mapping instructions back to line of codes is a difficult process because frequently they aren't even attributable to a line.
- pjc50 2y ago> even mapping instructions back to line of codes is a difficult process Enough is retained to allow line-step debugging. Godbolt will even do a nice mapping for you between source and object lines. Yes, a lot of it gets thrown away. My point is "this line of code has no effect on the output" is a problem, and the developer should be warned rather than lulled into a false sense of security that their check is doing something. (Code coverage has the same issue of doing line attribution, plus the difficulty of hitting error conditions in practice, but it would also show unexecuted lines of code)
- gpderetta 2y agoYou are vastly underestimating the amount of false positives under inlining and interprocedural optimizations.
- compiler-guy 2y ago> Enough is retained to allow line-step debugging. Only without optimization. Every compiler I have ever used (and I have used a lot of them!) starts having difficulty with step-debugging at the lowest-level of optimization, typically -O1. Some functions work, most don't.
- estebank 2y ago> One of the first things compilers do is throw away the original source code; outside of initial front-end codegen, there is no reference to the original AST That doesn't have to be an immutable fact for all implementations of compilers for all languages. The Rust compiler has multiple IRs (AST, HIR, THIR, MIR & LLVM IR), and for all but the last one (codegen), we keep around, if not a reference to the HIR node that allows us to navigate its context, at least a Span that points at the user's code (sometimes a whole struct or linked list of "facts" we've collected so far, each containing Spans). rustc also throws away information to reduce memory consumption, much to my dismay, but we still perform later checks to re evaluate (sometimes as an approximation) what the reason for a certain "decision" was, so that we can talk to the user in terms they understand, and not in terms of compiler internals. The ideal design would be to have a single implementation of all logic with two modes of operation: the low memory consumption one (what you state as the way compilers work), and a "track everything without discarding metadata until the end" mode, that can provide better human readable output.