Compilers

Are in general about converting a tree into a flattened structure. For example:

func3(func2(func1()))

Into:

res1 = func1()
res2 = func2(res1)
res3 = func3(res2)

There are two exceptions to this:

  • Branching
  • Looping

Branching

if (exp1) {
    exp2
}
else {
    exp3
}

Flattens to:

res1 = exp1
if !res1 goto else
exp2
goto end
else:
exp3
end:

Logical expressions

These are a form of branching. Consider:

func1() && func2()

Here if the result of func1 is false func2 should never be evaluated. In branching terms:

res1 = func1()
if !res1 goto rest
func2()
rest:

Looping

Obviously there is a movent of the program counter backwards given some condition. Very similar to branching but some state is needed.

While loops

while(exp1) {
    exp2
}

Expands to:

start:
res1 = exp1
if !res1 goto end
exp2
goto start
end:

Inline all functions

But how do you know when to not inline functions?