Further stages of compilation may or may not be referred to as "code generation", depending on whether they involve a significant change in the representation of the program.
Tasks which are typically part of a sophisticated compiler's "code generation" phase include: Instruction selection is typically carried out by doing a recursive postorder traversal on the abstract syntax tree, matching particular tree configurations against templates; for example, the tree W := ADD(X,MUL(Y,Z)) might be transformed into a linear sequence of instructions by recursively generating the sequences for t1 := X and t2 := MUL(Y,Z), and then emitting the instruction ADD W, t1, t2.
This second phase does not require a tree traversal; it can be done linearly, and typically involves a simple replacement of intermediate-language operations with their corresponding opcodes.
However, if the compiler is actually a language translator (for example, one that converts Java to C++), then the second code-generation phase may involve building a tree from the linear intermediate code.
When code generation occurs at runtime, as in just-in-time compilation (JIT), it is important that the entire process be efficient with respect to space and time.