Hi,
Artlav wrote:
Some examples of assembler code are fine, but the idea is to document the patterns used.
This sounds really nice in theory; but in practice I doubt compilers use these patterns.
For example; rather than doing this:
for (initial;final;increment){A;}
-Process initial
-Remember current position X
-Process final
-Emit unresolved conditional jump Y
-Process A
-Process increment
-Emit goto X
-Store current position to Y
A compiler is much more likely to convert "for" loops (e.g. by modifying the AST/Abstract Syntax Tree) from the original higher level form:
Code:
for (initial;condition;increment) { A; }
Into a lower level form like:
Code:
initial;
if(!condition) goto endloop;
startloop:
A;
if(condition) goto startloop;
endloop:
And do the same for things like do, do/while, switch, etc, and converting things like array accesses into pointer arithmetic, etc; so that all the "higher level syntactical sugar" disappears and you're left with little more than (maybe) "if, else, goto, function call, function return, operators and literals".
And then do various optimisations (constant folding, dead code elimination, etc) on the "lower level AST".
And then convert "lower level AST" into "intermediate language" (e.g. SSA).
And then do various optimisations on "intermediate language".
And then (in the back-end) convert from "intermediate language" into something that more closely resembles target specific machine code (e.g. instruction selection, register allocation, etc).
And then do various optimisations on that (peephole, etc).
And then emit the resulting code.
Mostly what I'm saying is that there's no "convert from higher level form directly into something you emit", and it's much more like "many separate steps, where each step brings it closer to something you emit".
Cheers,
Brendan