News for hackers. Stuff that matters.
Re:The Problem with Friendly C by derefr on Wednesday December 23, 2015 @10:57PM (#10787033)
How about being build-system defined? As in, let me specify a "target behavior profile" as a switch to the compiler, which would be shorthand for a bunch of switches that define specific results for specific undefined behaviors: "-foverflow=checked" (add explicit checks) vs. "-foverflow=wrap" (do what most ISAs already do, but even on target ISAs that don't do that) vs. "-foverflow=clip" (do something weird that no target ISA does, like making short 65535 + 1 = 65535.)

I would expect that a single-pass compiler like gcc would look at the toolchain's target ISA, compare it to these switches, and then generate extra shim code to adapt any cases of target-arch-does-X into code-does-Y-on-X, while letting do-X-on-X just translate directly. Basically the same way floating-point code gets compiled: architectures that support it get it, architectures that don't get a shim.

Meanwhile, a two-stage compiler with an intermediate representation, like clang, should generate IR with granular types specifying the chosen behavioral semantics on each operation. The second step in such a toolchain becomes much more formalized: rather than taking code that can contain undefined behavior as input, and then "defining" it during translation in some random heuristic manner, you just take code that already specifies the behavior it wants in full, and then attempt to generate target-arch code that does whatever it says in the most efficient manner possible while not breaking any of the guarantees the IR asks for. In other words, your code-generation stage becomes a static recompiler, like this one[1] for the NES ISA.

And you can always specify a switch at code-gen time that will error out the compilation if you've done something that has caused shims to be inserted. Or even a switch to throw away the behavioral semantics the IR asks for and substitute your own, like happens in most performance-focused emulator software.

[1] http://andrewkelley.me/post/jamulator.html

Re:The Problem with Friendly C by nly on Thursday December 24, 2015 @12:07AM (#10787193)
GCC has an intermediate representation. It's just not exercised as a separate project (like LLVM). It's far from "single pass"
Re:The Problem with Friendly C by derefr on Thursday December 24, 2015 @01:48AM (#10787377)
You're right; to be clear, what I was talking about above was whether the passes are decoupled at an abstract level, not so much whether the implementation uses multiple phases.

You can take LLVM "bitcode" as the product of clang, move it to another system with a different arch, and finish compiling the IR to a native binary on that system. This implies that the first step and second step don't share any state other than the IR itself—meaning that flags passed directly to clang in the first phase can't affect codegen, other than by influencing the generated IR; and that codegen has to treat the IR (and the environment) as its sole inputs.

Whereas with GCC, as far as I know, the RTL IR isn't arch-neutral, and the GENERIC/GIMPLE IRs aren't fully "baked" yet (i.e. they're compiler->compiler step IRs, not post-compilation pre-codegen IRs.) So there's no conceptual guarantee (even if there's an implementation-level one) that the compiler won't use compile-phase state to inform codegen.

In other words: it's guaranteed that you'd be able to implement the switches I'm talking about in clang+LLVM. You might (but won't necessarily) have to do some work to get GCC into the right shape to implement them.

Re:The Problem with Friendly C by cwzwarich on Thursday December 24, 2015 @03:10AM (#10787523)
LLVM IR isn't architecture-neutral. It encodes type layout / alignment, as well as ABI details. You can construct an LLVM target that is itself compilable on multiple architectures (see Portable Native Client), but it requires a nonstandard ABI.
Re:The Problem with Friendly C by cygx on Wednesday December 23, 2015 @11:02PM (#10787059)
As long as the option -foverflow=undefined is kept around, you have my vote. Now, it's just a simple matter of programming ;)
Re:The Problem with Friendly C by derefr on Wednesday December 23, 2015 @11:10PM (#10787078)
I think the equivalent for the current practice would basically be:

1. setting "-foverflow=promote" on the compiler's parsing-and-IR-generating stage, thus generating code that acts like all integers occupy infinitely-sized abstract machine registers, and expects this to get shimmed as checked promotion to pointers-to-structs from a bignum library on most architectures;

and then, seperately,

2. setting an optimization flag like "-Onopromote" for the target-recompilation stage, that throws away all the bignum promotion shims that would have been inserted, and pretends that it's adhering to bignum-promotion semantics anyway (thus creating code that will be optimized the way C code currently is.)

That's quite a bit more complicated, but also a lot more explicit about what's going on: you have to specify (or pick a profile that specifies) the actual semantics you want, and then you have to explicitly opt into assuming those semantics rather than enforcing them. There'd probably be a similar pair of {semantic, assumption} flags for each currently-undefined behavior.