Ideally, what you want to translate the code into is an "unrolled"
dataflow graph. Unrolled, here, means that all the loops and
procedure calls have been expanded out, leading to an infinite graph.

Optimizations can then be applied on the unrolled graph, even the
generation of target language. Then the graph has to be rolled back
up, and this is where the structures (if any) of the target language
-- the procedure calls, definitions, the loops and jumps -- are
generated. In assembly, you only have procedure calls & definitions,
and jumps. Loops might exist as part of the definition of a single
operator (a block move), but that's it.