The semantic phase of a compiler first translates parse trees into an intermediate representation (IR), which is independent of the underlying computer architecture, and then generates machine code from the IRs. This makes the task of retargeting the compiler to another computer architecture easier to handle.
We will consider Tiger for a case study. For simplicity, all data are one word long (four bytes) in Tiger. For example, strings, arrays, and records, are stored in the heap and they are represented by one pointer (one word) that points to their heap location. We also assume that there is an infinite number of temporary registers (we will see later how to spill-out some temporary registers into the stack frames). The IR trees for Tiger are used for building expressions and statements. They are described in detail in Section 7.1 in the textbook. Here is a brief description of the meaning of the expression IRs:
MEM(BINOP(PLUS,TEMP(fp),CONST(24)))fetches a word from the stack located 24 bytes above the frame pointer.
CALL(NAME(g),ExpList(MEM(NAME(a)),ExpList(CONST(1),NULL)))represents the function call g(a,1).
MOVE(MEM(+(NAME(x),CONST(16))),CONST(1))computes x := 1 (since 4*4bytes = 16 bytes).
In addition, when JUMP and CJUMP IRs are first constructed, the labels are not known in advance but they will be known later when they are defined. So the JUMP and CJUMP labels are first set to NULL and then later, when the labels are defined, the NULL values are changed to real addresses.