Implementation notes A bit of optimization. ---------------------------------------------------------------------- 0. Concept Usual program behave differently based on one or more conventional inputs, such as reading from file or system clock. Using program language as an input is less conventional, although I did that a few times as well. The one thing that I haven't done is having one program, interpreted as a single language, but behave differently based on how the code is compiled. So far as I can tell, none of the previous IOCCC winners have done it either. Naturally when IOCCC came around, this is exactly the thing that I should do. The goal is to exploit a subtle difference in compiled program behavior that should not have existed in the first place. Turns out that it is indeed possible to detect differences in compiler optimizations, and do so in a fairly deterministic way. ---------------------------------------------------------------------- 1. Optimization detector Detecting optimization is a paradox: if program behavior differs in a detectable, it's probably a compiler bug. But if program behavior does not change at all, there is no point in selecting optimization levels. The most sane way is to look for signs intentionally made visible by the compiler, such as predefined macros describing compile time options. But this is no fun since they will be clearly visible to human readers as well. It's also not very portable. The next thought would be to exploit compiler optimization bugs, which are not as visible but often are well documented. But the reason why they are well documented is because they are bugs, and usually get fixed after a while. They are also not very portable. We won't look for human visible features and we can't look for bugs. Instead, we look for features that are common to lots of compilers. One such feature is dead code elimination, where code that do nothing are simply replaced with nothing. Then, by creating a suitable dead code candidate and detecting that its function size is equivalent to nothing, we can declare that optimization is enabled. To determine function sizes, we compare function addresses: W: dead code X: nothing Y: next function If optimization is enabled, X-W == Y-X. This is not guaranteed to work either, since we can't really predict where the linker is going to place the final functions. But empirically it works very well across many different architectures. Good enough for me. ---------------------------------------------------------------------- 2. Optimization game Detecting dead code elimination basically gives me a single bit of input, so two different outputs are possible. This might be twice as much as what was expected, but still quite boring. To have more interesting outputs, we need to have some sort of loop, which can only be done by compiling the output repeatedly. Coincidentally, the anime that was broadcasting around the time of IOCCC was the second season of Sword Art Online, specifically the GGO arc. So I devised this game where Sinon takes that single bit of input to decide which weapon to fire, and must carefully alternate between the weapons based on timing. Having gained a time requirement, I decided to use __TIME__ as a secondary input. Although it turns out that time is really all I needed, I still claim optimization level as a primary feature, since __TIME__ has been used in IOCCC before, but compiler optimization hasn't. Not coincidentally, this is yet another anime inspired program, and therefore yet another anime inspired IOCCC entry. It has became such a regular occurrence that at least one other IOCCC winner predicted it: https://twitter.com/mametter/status/512220958313029632 I take pride in having a story associated with each piece of code, programming is a lot more fun this way. ---------------------------------------------------------------------- 3. Implementation Having decided what gimmick to employ and what to do with it, the rest is just writing a program around it. Some features here: - ASCII art display of game progress: each enemy is assigned a unique index using linear congruential generator, and is either rendered or not based on whether that index is greater than current score. This allows the enemies to disappear from random places as game progresses. This is rendered as trailing comments to obscure any code that came before it, assuming a 80x25 terminal. - Run-length encoded ending screen: I figured there must be sort of goal at the end for any game to be worth playing at all, so there are separate ending screens for good and bad endings. The good ending is another ASCII art, run-length encoded to save space. - Game state propagated across compilations: this is done using some preprocessor magic to quote+inline the game execution code, plus an array for propagating various counters. Given that I didn't have to account for output code layout because they will be obscured by game progress output (I gave up trying to fit the intermediate states in a 80x25 terminal), this is mostly a trivial exercise. - ASCII art layout: final source code is formatted like Sinon, of course. Basically I have a lot of fluff wrapped around a single bit of unusual input. ---------------------------------------------------------------------- 4. Other features I had like ~200 bytes to spare before reaching IOCCC size limits, a real luxury. So I embedded a Perl script that would generate a Bash script that would automatically play the game to completion. It was very convenient to be able to test in various places from a single source file. I still have a few more bytes to spare, so I embedded CRC32 of the code into the output file itself, just like last year. Also like last year, I recorded the entire editing session, starting from empty file. I am not sure how many people care about these things, but why not. ---------------------------------------------------------------------- 5. Finally... Sinon was a winning entry for IOCCC 2014. Apparently the judges really like that one bit of optimization. My coworkers also seemed to like that one bit of optimization. I am glad that one bit was well received.