Intermediate Code Generation Part II Chapter 6 (1 st  ed Chapter 8) COP5621 Compiler Construction Copyright Robert van Engelen, Florida State University, 2007-2009
Advanced Intermediate Code Generation Techniques Reusing temporary names Addressing array elements Translating logical and relational expressions Translating short-circuit Boolean expressions and flow-of-control statements with backpatching lists Translating procedure calls
Reusing Temporary Names Evaluate  E 1  into  t1   Evaluate  E 2  into  t2 t3 := t1 + t2 E 1   +   E 2 Modify  newtemp () to use a “stack”: Keep a counter  c , initialized to 0 Decrement counter on each use of a  $ i  in a three-address statement newtemp () returns temporary  $ c++  (that is,  c  is post incremented )   If  t1  no longer used, can reuse  t1 instead of using new temp  t3 generate
Reusing Temporary Names (cont’d) x := a * b + c * d - e * f $ 0  := a * b $ 1  := c * d $ 0  :=  $0  +  $1 $ 1  := e * f $ 0  :=  $0  -  $1 x  :=  $0 0 0 ->  0  -> 1 1 ->  1  -> 2 2 ->  0  -> 1 1 ->  1  -> 2 2 ->  0  -> 1 1 ->  0  -> 0 c  ->  c decr  ->  c incr Statement
Addressing Array Elements: One-Dimensional Arrays = base A  + ( i  -  low ) *  w = i  *  w  +  c where  c = base A  - low * w with  low =  10;  w =  4 A : array [10..20] of integer; … := A[i] t1 := c // c =  base A  -  10 * 4 t2 := i * 4 t3 := t1[t2] …  := t3
Addressing Array Elements: Multi-Dimensional Arrays A : array [1..2,1..3] of integer; low 1  =  1,  low 2  =  1,  n 1  =  2 , n 2  =  3 , w =  4 A[1,1] A[1,2] A[1,3] A[2,1] A[2,2] A[2,3] Row-major A[1,1] A[2,1] A[1,2] A[2,2] A[1,3] A[2,3] Column-major base A base A
Addressing Array Elements: Multi-Dimensional Arrays = base A  + (( i 1  -  low 1 ) *  n 2  +  i 2  -  low 2 )  * w =  (( i 1  *  n 2 )  + i 2 ) *  w  +  c where  c = base A  -  (( low 1  * n 2 ) +  low 2 ) *  w with  low 1  =  1;  low 2  =  1;  n 2  =  3;  w =  4 A : array [1..2,1..3] of integer;  (Row-major) … := A[i,j] t1 := i * 3 t1 := t1 + j t2 := c // c =  base A  -  (1 * 3 + 1) * 4 t3 := t1 * 4 t4 := t2[t3] …  := t4
Addressing Array Elements: Grammar S      L   :=   E E      E   +   E   |  (   E  )   |  L L      Elist  ]   |  id Elist      Elist  ,   E   |  id [  E Synthesized attributes: E .place name of temp holding value of  E Elist .array array name Elist .place name of temp holding index value Elist .ndim number of array dimensions L .place lvalue (=name of temp) L .offset index into array (=name of temp) null  indicates non-array simple  id
Addressing Array Elements S      L   :=   E {  if   L .offset =  null   then   emit ( L .place ‘:=’  E .place)   else   emit ( L .place[ L .offset] ‘:=’  E .place) }   E      E 1  +  E 2  {  E .place :=  newtemp ();   emit ( E .place ‘:=’  E 1 .place ‘+’  E 2 .place) }   E      (   E 1   ) {  E .place :=  E 1 .place } E      L {  if   L .offset =  null   then   E .place :=  L .place   else   E .place :=  newtemp ();   emit ( E .place ‘:=’  L .place[ L .offset] }
Addressing Array Elements L      Elist   ] {  L .place :=  newtemp ();   L .offset :=  newtemp ();   emit ( L .place ‘:=’  c ( Elist .array);   emit ( L .offset ‘:=’  Elist .place ‘*’  width ( Elist .array)) }   L      id   {  L .place :=  id .place;   L .offset :=  null  }   Elist      Elist 1   ,  E {  t  :=  newtemp ();  m  :=  Elist 1 .ndim + 1;    emit ( t  ‘:=’  Elist 1 .place ‘*’  limit ( Elist 1 .array,  m ));   emit ( t  ‘:=’  t  ‘+’  E .place);    Elist .array :=  Elist 1 .array;  Elist .place :=  t ;   Elist .ndim :=  m  } Elist      id   [  E {  Elist .array :=  id .place;  Elist .place :=  E .place;   Elist .ndim := 1 }
Translating Logical and Relational Expressions a or b and not c t1 := not c t2 := b and t1 t3 := a or t2 if a < b goto L1   t1 := 0   goto L2 L1: t1 := 1 L2: a < b
Translating Short-Circuit Expressions Using Backpatching E      E   or   M   E   |  E   and   M   E     |  not   E   |  (   E   )   |  id relop id   |  true |  false M       Synthesized attributes: E .truelist backpatch list for jumps on true E .falselist backpatch list for jumps on false M .quad location of current three-address quad
Backpatch Operations with Lists makelist ( i ) creates a new list containing three-address location  i , returns a pointer to the list merge ( p 1 ,  p 2 ) concatenates lists pointed to by  p 1  and  p 2 , returns a pointer to the concatenates list backpatch ( p ,  i ) inserts  i  as the target label for each of the statements in the list pointed to by  p
Backpatching with Lists: Example a < b or c < d and e < f 100: if a < b goto _ 101: goto _ 102: if c < d goto _ 103: goto _ 104: if e < f goto _ 105: goto _ 100: if a < b goto TRUE 101: goto 102 102: if c < d goto 104 103: goto FALSE 104: if e < f goto TRUE 105: goto FALSE backpatch
Backpatching with Lists: Translation Scheme M         {  M .quad :=  nextquad () } E      E 1   or   M   E 2 {  backpatch ( E 1 .falselist,  M .quad);   E .truelist :=  merge ( E 1 .truelist,  E 2 .truelist);   E .falselist :=  E 2 .falselist }   E      E 1   and   M   E 2 {  backpatch ( E 1 .truelist,  M .quad);   E .truelist :=  E 2 .truelist;   E .falselist :=  merge ( E 1 .falselist,  E 2 .falselist); } E      not   E 1  {  E .truelist :=  E 1 .falselist;   E .falselist :=  E 1 .truelist }   E      (   E 1   ) {  E .truelist :=  E 1 .truelist;   E .falselist :=  E 1 .falselist }
Backpatching with Lists: Translation Scheme (cont’d) E      id 1   relop id 2 {  E .truelist :=  makelist ( nextquad ());   E .falselist :=  makelist ( nextquad () + 1);   emit (‘ if ’  id 1 .place  relop .op  id 2 .place ‘ goto _ ’);   emit (‘ goto _ ’) }   E      true {  E .truelist :=  makelist ( nextquad ());   E .falselist := nil;   emit (‘ goto _ ’) } E      false {  E .falselist :=  makelist ( nextquad ());   E .truelist := nil;   emit (‘ goto _ ’) }
Flow-of-Control Statements and Backpatching: Grammar S      if   E   then   S   |  if   E   then   S   else   S     |  while   E  do  S   |  begin  L  end   |  A L      L   ;   S   |  S Synthesized attributes: S .nextlist backpatch list for jumps to the next statement after  S  (or nil) L .nextlist backpatch list for jumps to the next statement after  L  (or nil) S 1   ;  S 2   ;  S 3   ;  S 4   ;  S 5  … backpatch ( S 1 .nextlist, 200) backpatch ( S 2 .nextlist, 300) backpatch ( S 3 .nextlist, 400) backpatch ( S 4 .nextlist, 500) 100: Code for S1 200: Code for S2 300: Code for S3 400: Code for S4 500: Code for S5 Jumps out of S 1
Flow-of-Control Statements and Backpatching S     A {  S .nextlist := nil } S      begin  L  end {  S .nextlist :=  L .nextlist } S      if   E  then  M S 1 {  backpatch ( E .truelist,  M .quad);   S .nextlist :=  merge ( E .falselist,  S 1 .nextlist) } L     L 1   ;   M S {  backpatch ( L 1 .nextlist,  M .quad);   L .nextlist :=  S .nextlist; } L     S {  L .nextlist :=  S .nextlist; } M        {  M .quad :=  nextquad () } A    … Non-compound statements, e.g. assignment, function call
Flow-of-Control Statements and Backpatching (cont’d) S      if   E  then  M 1  S 1   N   else  M 2  S 2 {  backpatch ( E .truelist,  M 1 .quad);   backpatch ( E .falselist,  M 2 .quad);   S .nextlist :=  merge ( S 1 .nextlist,   merge ( N .nextlist,  S 2 .nextlist)) } S     while  M 1  E  do  M 2   S 1 {  backpatch ( S 1 ,nextlist,  M 1 .quad);   backpatch ( E .truelist,  M 2 .quad);   S .nextlist :=  E .falselist;   emit (‘ goto  M 1 .quad’) } N        {  N .nextlist :=  makelist ( nextquad ());   emit (‘ goto _ ’) }
Translating Procedure Calls S      call id (   Elist   ) Elist      Elist   ,   E   |  E call foo(a+1, b, 7) t1 := a + 1 t2 := 7 param t1 param b param t2 call foo 3
Translating Procedure Calls S      call id (   Elist   ) {  for  each item  p  on  queue   do   emit (‘ param ’  p );   emit (‘ call ’  id .place | queue |) } Elist      Elist   ,   E { append  E .place to the end of  queue  } Elist      E { initialize  queue  to contain only  E .place }

Ch8b

  • 1.
    Intermediate Code GenerationPart II Chapter 6 (1 st ed Chapter 8) COP5621 Compiler Construction Copyright Robert van Engelen, Florida State University, 2007-2009
  • 2.
    Advanced Intermediate CodeGeneration Techniques Reusing temporary names Addressing array elements Translating logical and relational expressions Translating short-circuit Boolean expressions and flow-of-control statements with backpatching lists Translating procedure calls
  • 3.
    Reusing Temporary NamesEvaluate E 1 into t1 Evaluate E 2 into t2 t3 := t1 + t2 E 1 + E 2 Modify newtemp () to use a “stack”: Keep a counter c , initialized to 0 Decrement counter on each use of a $ i in a three-address statement newtemp () returns temporary $ c++ (that is, c is post incremented ) If t1 no longer used, can reuse t1 instead of using new temp t3 generate
  • 4.
    Reusing Temporary Names(cont’d) x := a * b + c * d - e * f $ 0 := a * b $ 1 := c * d $ 0 := $0 + $1 $ 1 := e * f $ 0 := $0 - $1 x := $0 0 0 -> 0 -> 1 1 -> 1 -> 2 2 -> 0 -> 1 1 -> 1 -> 2 2 -> 0 -> 1 1 -> 0 -> 0 c -> c decr -> c incr Statement
  • 5.
    Addressing Array Elements:One-Dimensional Arrays = base A + ( i - low ) * w = i * w + c where c = base A - low * w with low = 10; w = 4 A : array [10..20] of integer; … := A[i] t1 := c // c = base A - 10 * 4 t2 := i * 4 t3 := t1[t2] … := t3
  • 6.
    Addressing Array Elements:Multi-Dimensional Arrays A : array [1..2,1..3] of integer; low 1 = 1, low 2 = 1, n 1 = 2 , n 2 = 3 , w = 4 A[1,1] A[1,2] A[1,3] A[2,1] A[2,2] A[2,3] Row-major A[1,1] A[2,1] A[1,2] A[2,2] A[1,3] A[2,3] Column-major base A base A
  • 7.
    Addressing Array Elements:Multi-Dimensional Arrays = base A + (( i 1 - low 1 ) * n 2 + i 2 - low 2 ) * w = (( i 1 * n 2 ) + i 2 ) * w + c where c = base A - (( low 1 * n 2 ) + low 2 ) * w with low 1 = 1; low 2 = 1; n 2 = 3; w = 4 A : array [1..2,1..3] of integer; (Row-major) … := A[i,j] t1 := i * 3 t1 := t1 + j t2 := c // c = base A - (1 * 3 + 1) * 4 t3 := t1 * 4 t4 := t2[t3] … := t4
  • 8.
    Addressing Array Elements:Grammar S  L := E E  E + E | ( E ) | L L  Elist ] | id Elist  Elist , E | id [ E Synthesized attributes: E .place name of temp holding value of E Elist .array array name Elist .place name of temp holding index value Elist .ndim number of array dimensions L .place lvalue (=name of temp) L .offset index into array (=name of temp) null indicates non-array simple id
  • 9.
    Addressing Array ElementsS  L := E { if L .offset = null then emit ( L .place ‘:=’ E .place) else emit ( L .place[ L .offset] ‘:=’ E .place) } E  E 1 + E 2 { E .place := newtemp (); emit ( E .place ‘:=’ E 1 .place ‘+’ E 2 .place) } E  ( E 1 ) { E .place := E 1 .place } E  L { if L .offset = null then E .place := L .place else E .place := newtemp (); emit ( E .place ‘:=’ L .place[ L .offset] }
  • 10.
    Addressing Array ElementsL  Elist ] { L .place := newtemp (); L .offset := newtemp (); emit ( L .place ‘:=’ c ( Elist .array); emit ( L .offset ‘:=’ Elist .place ‘*’ width ( Elist .array)) } L  id { L .place := id .place; L .offset := null } Elist  Elist 1 , E { t := newtemp (); m := Elist 1 .ndim + 1; emit ( t ‘:=’ Elist 1 .place ‘*’ limit ( Elist 1 .array, m )); emit ( t ‘:=’ t ‘+’ E .place); Elist .array := Elist 1 .array; Elist .place := t ; Elist .ndim := m } Elist  id [ E { Elist .array := id .place; Elist .place := E .place; Elist .ndim := 1 }
  • 11.
    Translating Logical andRelational Expressions a or b and not c t1 := not c t2 := b and t1 t3 := a or t2 if a < b goto L1 t1 := 0 goto L2 L1: t1 := 1 L2: a < b
  • 12.
    Translating Short-Circuit ExpressionsUsing Backpatching E  E or M E | E and M E | not E | ( E ) | id relop id | true | false M   Synthesized attributes: E .truelist backpatch list for jumps on true E .falselist backpatch list for jumps on false M .quad location of current three-address quad
  • 13.
    Backpatch Operations withLists makelist ( i ) creates a new list containing three-address location i , returns a pointer to the list merge ( p 1 , p 2 ) concatenates lists pointed to by p 1 and p 2 , returns a pointer to the concatenates list backpatch ( p , i ) inserts i as the target label for each of the statements in the list pointed to by p
  • 14.
    Backpatching with Lists:Example a < b or c < d and e < f 100: if a < b goto _ 101: goto _ 102: if c < d goto _ 103: goto _ 104: if e < f goto _ 105: goto _ 100: if a < b goto TRUE 101: goto 102 102: if c < d goto 104 103: goto FALSE 104: if e < f goto TRUE 105: goto FALSE backpatch
  • 15.
    Backpatching with Lists:Translation Scheme M   { M .quad := nextquad () } E  E 1 or M E 2 { backpatch ( E 1 .falselist, M .quad); E .truelist := merge ( E 1 .truelist, E 2 .truelist); E .falselist := E 2 .falselist } E  E 1 and M E 2 { backpatch ( E 1 .truelist, M .quad); E .truelist := E 2 .truelist; E .falselist := merge ( E 1 .falselist, E 2 .falselist); } E  not E 1 { E .truelist := E 1 .falselist; E .falselist := E 1 .truelist } E  ( E 1 ) { E .truelist := E 1 .truelist; E .falselist := E 1 .falselist }
  • 16.
    Backpatching with Lists:Translation Scheme (cont’d) E  id 1 relop id 2 { E .truelist := makelist ( nextquad ()); E .falselist := makelist ( nextquad () + 1); emit (‘ if ’ id 1 .place relop .op id 2 .place ‘ goto _ ’); emit (‘ goto _ ’) } E  true { E .truelist := makelist ( nextquad ()); E .falselist := nil; emit (‘ goto _ ’) } E  false { E .falselist := makelist ( nextquad ()); E .truelist := nil; emit (‘ goto _ ’) }
  • 17.
    Flow-of-Control Statements andBackpatching: Grammar S  if E then S | if E then S else S | while E do S | begin L end | A L  L ; S | S Synthesized attributes: S .nextlist backpatch list for jumps to the next statement after S (or nil) L .nextlist backpatch list for jumps to the next statement after L (or nil) S 1 ; S 2 ; S 3 ; S 4 ; S 5 … backpatch ( S 1 .nextlist, 200) backpatch ( S 2 .nextlist, 300) backpatch ( S 3 .nextlist, 400) backpatch ( S 4 .nextlist, 500) 100: Code for S1 200: Code for S2 300: Code for S3 400: Code for S4 500: Code for S5 Jumps out of S 1
  • 18.
    Flow-of-Control Statements andBackpatching S  A { S .nextlist := nil } S  begin L end { S .nextlist := L .nextlist } S  if E then M S 1 { backpatch ( E .truelist, M .quad); S .nextlist := merge ( E .falselist, S 1 .nextlist) } L  L 1 ; M S { backpatch ( L 1 .nextlist, M .quad); L .nextlist := S .nextlist; } L  S { L .nextlist := S .nextlist; } M   { M .quad := nextquad () } A  … Non-compound statements, e.g. assignment, function call
  • 19.
    Flow-of-Control Statements andBackpatching (cont’d) S  if E then M 1 S 1 N else M 2 S 2 { backpatch ( E .truelist, M 1 .quad); backpatch ( E .falselist, M 2 .quad); S .nextlist := merge ( S 1 .nextlist, merge ( N .nextlist, S 2 .nextlist)) } S  while M 1 E do M 2 S 1 { backpatch ( S 1 ,nextlist, M 1 .quad); backpatch ( E .truelist, M 2 .quad); S .nextlist := E .falselist; emit (‘ goto M 1 .quad’) } N   { N .nextlist := makelist ( nextquad ()); emit (‘ goto _ ’) }
  • 20.
    Translating Procedure CallsS  call id ( Elist ) Elist  Elist , E | E call foo(a+1, b, 7) t1 := a + 1 t2 := 7 param t1 param b param t2 call foo 3
  • 21.
    Translating Procedure CallsS  call id ( Elist ) { for each item p on queue do emit (‘ param ’ p ); emit (‘ call ’ id .place | queue |) } Elist  Elist , E { append E .place to the end of queue } Elist  E { initialize queue to contain only E .place }