Download Presentation
## Chapter 8

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -

**Chapter 8**Intermediate Code Generation**Intermediate languages: Syntax trees, three-address code,**quadruples. • Types of Three – Address Statements: x := y op z where op is a binary operator x := op y where op is a unary operator. x := y goto L where L is the label of a 3 – address statement if x relop y goto L where relop is a relational operator. param x call p, n Used to call procedures annd functions. return y Return the value y from a function. return return from a procedure.**x := y [i]**x[i] := y x := &y Set x to the location of y. x := *y Set x to the contents of the location pointed to by y. *x := y Copy the contents of y to the location pointed to by x. • Generating three-address code in atop-down parser. An expression, E, has two attributes: E.place is the name holding the value of E. E.code is the code to generate E.**Typical Semantic Rules**• The concatenation operator is shown as ||, X || Y means the concatenation of X and Y. A function, newtwmp, returns a new name whenever it is called. The gen function generates a three-address statement. S id := E S.code := E.code || gen (id.place ‘:=‘ E.place) E E1 + E2 E.place := newtemp; E.code := E1.code || E2.code ||gen (E.place ‘:=‘ ‘+’ E2.place) E -E1 E.place := newtemp; E.code := E1.code || gen (E.place ‘:= uminus’ E1.place) E (E1) E.place := E1.place; E.code := E1.code; E id E.place := id.place; E.code := ‘’**While – do statement : S while E do S1**S.begin := newlabel; S.after := newlabel; S.code := gen (S.begin ‘:’) || E.code || gen (‘if’ E.place ‘= false goto’ S.after) || S1.code || gen (‘goto’ S.begin) || gen (S.after ‘:’) • If – then – else statement: S if E then S1 else S2 S.false := newlabel; S.after := newlabel; S.code := E.code || gen (‘if’ E.place ‘= false goto’ S.false) || S1.code || gen (‘goto’ S.after) || gen (S.false ‘:’) || S2.code || gen (S.after ‘:’)**Example : Consider the nontermional statement in the**grammar. After substituting for variable, procedure_statement and compound_statement we have the productions: stmt id assignop expr | id [expr] assignop expr | id | id (expr_list) | begin opt_stmts end | if expr then stmt else stmt | while expr do stmt • We left-factor id out of the first four productions to get: stmt id stmt_part | begin opt_stmts end | if expr then stmt else stmt | while expr do stmt**stmt_part assignop expr**| [expr] assignop expr | (expr_list) | ε • The stmt procedure in a recursive – descent parser handles statements. • Assume that expr is a function that produces code for an expression and returns the location where the expression value will be stored. • To produce 3 – address code the stmt procedure looks like :**procedure stmt;**var L1, L2 : label; Eplace : location_of_expression_value; begin if lookahead = ‘id’ then stmtpart else if lookahead = ‘begin’ then compoundstmt else if lookahead = ‘if’ then begin match(‘if’); L1 := newlabel; L2 = newlabel; Eplace := expr; match(‘then’); gen (‘if’ Eplace = ‘false goto’ L1); stmt; match(‘else’); gen(‘goto’ L2); gen(L1 ‘:’); stmt; gen(L2 ‘:’) end else if lookahead = ‘while’ then begin L1 := newlabel; L2 := newlabel; match (‘while’); gen (L1 ‘:’); Eplace := expr; match (‘do’); gen (‘if’ Eplace ‘= false goto’ L2); stmt; gen (‘goto’ L1); gen (L2 ‘:’) end Else error End;**procedure stmtpart;**var nptr : pointer_to_symbol_table_entry; E1, E2 : location_of_expression_value; n : integer; begin nptr := lookup (id.entry); match(‘id’); if lookahead = ‘assignop’ then begin match (‘assignop’); E1 := expr; gen (nptr .name ‘:=’ E1) end else if lookahead = ‘[’ then begin match(‘[’); E1 := expr; match(‘]’); match (‘assignop’); E2 := expr; gen (nptr .name ‘[’ E1 ‘] :=’ E2) end else if lookahead = ‘(’ then begin match(‘(’); n := 1; E1 := expr; gen(‘param’ E1) end; match(‘(’); gen(‘call’ nptr .name ‘,’ n) end else gen(‘call’ nptr .name ‘, 0’) end;**Declarations: In Pascal a set of declarations begins with a**single var token. • The syntax of declarations can be changed to normal Pascal. • The productions for declarations are: declarations declarations var identifier_list : type; | ε • The productions must be modified to eliminate the left-recursion: declarations var identifier_list : type; declarations | ε • An identifier_list contains one or more id tokens separated by commas. The type of the id tokens is not known until type is reached. We need to know what the type is before processing the id tokens.**declarations var id decl_ext ; declarations | ε**decl_ext , id decl_ext | : type type integer | real | array [num..num] of integer | array [num..num] of real • Assume integers are 4 bytes wide and reals are 8 bytes wide. • A recursive – descent parser calls function typ to process the type nonterminal. • Function typ returns a type_record with two fields: Width to show the number of bytes in the type and TypeExpr to show the type (either integer, real, integer array, or real array). The typ function looks like:**function typ : type_record;**var N1, N2 : integer; begin if lookahead = ‘integer’ then begin match(‘integer’); typ.Width := 4; typ.TypeExpr := ‘integer’ end else if lookahead = ‘real’ then begin match(‘real’); typ.Width := 8; typ.TypeExpr := ‘real’end else if lookahead = ‘array’ then begin match(‘array’); match(‘[’); if lookahead = ‘num’ then N1 := num.value else error; match(‘num’); match(‘..’); if lookahead = ‘num’; then N2 := num.value else error;**match(‘num’); match(‘]’); match(‘of’);**if lookahead = ‘integer’ then begin match(‘integer’); typ.Typeexpr := ‘integer array’; typ. Width := 4 * (N2 – N1 + 1) end else if lookahead = ‘real’ then begin match(‘real’); typ.Typeexpr := ‘real array’; typ.Width := 8 * (N2 – N1 +1) end {if lookahead = ‘real’} end {if lookahead = ‘array’} else error end;