CD - CH5 - Intermediate Code Generation
CD - CH5 - Intermediate Code Generation
• In this chapter,
• We consider that the error checking is done in another pass,
• Even though in practice the IC generation and the type checking can be done at the
same time.
Why Intermediate Code?
• While generating machine code directly from source code is possible,
it entails two problems:
• With � languages and � target machines, we need to write � front ends,
� × � optimizers, and � × � code generators.
1. �� = �∗�
2. �� = � + ��
3. �� = �∗�
4. �� = �/��
5. �� = �� − ��
Three Address Code
• Quadruples:
• Each instruction in quadruples presentation is divided into four fields: ��������,
����, ����, and ������.
• Triples:
• Each instruction in triples presentation has three fields : ��, ����, and ����.
• Triples represent similarity with DAG and syntax tree.
• Triples face the problem of code immovability while optimization, as the results are
positional and changing the order or position of an expression may cause problems.
• Indirect Triples:
• This representation is an enhancement over triples representation.
• It uses pointers instead of position to store results.
• This enables the optimizers to freely re-position the sub-expression to produce an
optimized code.
Three Address Code
• Implementations of Three Address Code in the above example
� + � ∗ � − �/(� ∗ �) can be:
Instructions in Three Address Code
• As with an assembler statement, the three-address code statement can
have:
• Symbolic labels, as well as Statements for control flow.
• The following are Common three-address code statements:
E ® E1 + E2 �. ����� : = �������();
�. ���� : = ��. ���� || ��. ���� || ��� (�. �����, ‘: = ’, ��. �����, ‘ + ’, ��. �����)
E ® E1 * E2 �. ����� : = �������();
�. ���� : = ��. ���� || ��. ���� || ��� (�. �����, ‘: = ’, ��. �����, ‘ ∗ ’, ��. �����)
E ® - E1 �. ����� : = �������()
�. ���� : = ��. ���� || ��� (�. �����, ‘: = ������ ’, ��. �����)
E ® (E1) �. ����� : = �������()
�. ���� : = ��. ����
E ® id �. ����� : = ��. ������
�. ���� : = ‘’ /∗ ����� ���� ∗/
Note:
● In languages where nested procedures are possible, we must
have several symbol tables, one for each procedure.
Assignment Statements
● Using the symbol table, we will see how it is possible to generate
the three-address code statements corresponding to
assignments.
– Variables are represented by their symbol table entries.
● The function lookup(lexeme) checks
– if there is an entry for this occurrence of the name in the symbol table,
and
– a pointer to the entry is returned; otherwise nil is returned.
● The newtemp() function will generate
– temporary variables and reserve a memory area for the variables by
modifying the offset and
– putting in the symbol table the reserved memories’ addresses.
Assignment Statements
● Example: generation of the three-address code for the
assignment statement and simple expressions
Syntax Rule Semantic Action
S ® id := E p : = lookup (id. name);
S. code : = E. code || If p <> nil then gen (p. lexeme, ‘: = ’, E. place) else Error;
E ® E1 + E2 �. ����� : = �������();
�. ���� : = ��. ���� || ��. ���� || ���(�. �����, ‘: = ’, ��. �����, ‘ + ’, ��. �����)
E ® E1 * E2 �. ����� : = �������();
�. ���� : = ��. ���� || ��. ���� ||��� (�. �����, ‘: = ’, ��. �����, ‘ ∗ ’, ��. �����)
E ® - E1 �. ����� : = �������();
�. ���� : = ��. ���� || ��� (�. �����, ‘: = ������ ’, ��. �����)
E ® (E1) �. ����� : = �������();
�. ���� : = ��. ����;
E ® id � : = ������ (��. ������)
�� � <> ��� ���� �. ����� = �. ������ ���� ����� �. ���� = ’’/∗ ����� ���� ∗/
Addressing Array Elements
● The elements of an array are stored in a block of consecutive
locations.
– If the width of each array element is w, the relative address of the
array is base and the lower bound of the index is low, then the i'th
element of the array is found at the address:
base + (i – low) * w
● For example for an array declared as
Note:
● The function width(arrayname) returns the width of the
array called arrayname by looking in the symbol table.
● The function base(arrayname) returns the base of the array
called arrayname by looking in the symbol table.
Addressing Array Elements
Syntax Rule Semantic Rule
S ® L := E if L.offset = nil then /* L is a simple id */
S.code := L.code || E.code || Gen (L.place, ‘:=’, E.place);
else
S.code := L.code || E.code || Gen (L.place, ‘[’, L.offset, ‘] :=’, E.place);
E ® E1 + E2 E.place := newtemp();
E.code := E1.code || E2.code ||
gen (E.place, ‘:=’, E1.place, ‘+’, E2.place)
E ® E1 * E2 E.place := newtemp();
E.code := E1.code || E2.code ||
gen (E.place, ‘:=’, E1.place, ‘*’, E2.place)
E ® - E1 E.place := newtemp();
E.code := E1.code || gen (E.place, ‘:= uminus ’, E1.place)
E ® (E1) E.place := newtemp();
E.code := E1.code
Addressing Array Elements
Syntax Rule Semantic Rule
If L.offset = nil then /* L is simple */
E ®L Begin
E.place := L.place
E.code := L.code;
End
Else
Begin
E.place := newtemp();
E.code := L.code || gen (E.place, ‘ :=’, L.place, ‘[’ , L.offset,
‘]’)
L ® id [E] L.place :=End
newtemp();
L.offset := newtemp();
L.code := E.code
|| gen (L.place, ‘:=’, base (id.lexeme) – width (id.lexeme) * low(id.lexeme))
|| gen (L.offset, ‘:=’, E.place, ‘*’, width (id.lexeme));
p := lookup (id.lexeme)
L ® id
If p <> nil then L.place = p.lexeme else Error
L.offset := nil; /* for simple identifier */
E.code := ‘’ /* empty code */
Addressing Array Elements