cse443 compilers
play

CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis - PowerPoint PPT Presentation

CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall Phases of a compiler Intermediate Representation (IR): specification and generation Figure 1.6, page 5 of text Intermediate Representations Directed Acyclic


  1. CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall

  2. Phases of a compiler Intermediate Representation (IR): specification and generation Figure 1.6, page 5 of text

  3. Intermediate Representations

  4. Directed Acyclic Graph (DAG) Similar to a syntax tree No repeated nodes: structure sharing

  5. Ex. 6.1 [p 359] a + a * ( b - c ) + ( b - c ) * d + + * a * - d b c a - b c

  6. Ex. 6.1 [p 359] a + a * ( b - c ) + ( b - c ) * d + + * a * - d b c a - b c

  7. Ex. 6.1 [p 359] a + a * ( b - c ) + ( b - c ) * d + + * * d a - b c

  8. Ex. 6.1 [p 359] a + a * ( b - c ) + ( b - c ) * d + + * * d a - b c e r o m e s b n o n i a s s c e r s p g x n e i h f T i d s t e c t e a f c f i e l p e m d o i s c e v a h

  9. SDT Tree or DAG Production Semantic Rule 1 E -> E 1 + T E.node = new Node('+', E.node, T.node) 2 E -> E 1 - T E.node = new Node('-', E.node, T.node) 3 E -> E 1 * T E.node = new Node('*', E.node, T.node) 4 E -> T E.node = T.node 5 T -> ( E ) T.node = E.node 6 T -> id T.node = new Leaf(id, id.entry) 7 T -> num T.node = new Leaf(num, num.val) Figure 6.4 in text (p. 360), corrected according to errata sheet.

  10. SDT Tree or DAG SDT produces a tree if each call to Node creates a new tree node. SDT produces a DAG if for each call to Node there is a check whether this node already exists, and if so it returns a reference to the existing node rather than returning a new node.

  11. Example p 1 = Leaf(id, entry-a) p 2 = Leaf(id, entry-a) = p 1 p 3 = Leaf(id, entry-b) p 4 = Leaf(id, entry-c) p 5 = Node('-',p 3 ,p 4 ) p 6 = Node('*',p 1 ,p 5 ) p 7 = Node('-',p 1 ,p 6 ) p 8 = Leaf(id, entry-b) = p 3 p 9 = Leaf(id, entry-c) = p 4 p 10 = Node('-',p 3 ,p 4 ) = p 5 p 11 = Leaf(id, entry-d) p 12 = Node('*',p 5 ,p 11 ) p 13 = Node('+',p 7 ,p 12 )

  12. Value-number method Algorithm 6.3 [p. 361] Input: label op, node l, node r Output: The value number of a node in the array with signature <op,l,r> Method: Search the array for a node M with signature <op,l,r>. If there is such a node, return the value number of M. If not, create in the array a new node N with signature <op,l,r> and return its value number.

  13. Value-number method Algorithm 6.3 [p. 361] Input: label op, node l, node r Output: The value number of a node in the array with signature <op,l,r> Can use hash table for efficiency. Method: Search the array for a node M with signature <op,l,r>. If there is such a node, return the value number of M. If not, create in the array a new node N with signature <op,l,r> and return its value number.

  14. Revisiting 6.1 see construction steps in figure 6.5 [p. 360] 1 id —> to ST entry for a 2 id —> to ST entry for b 3 id —> to ST entry for c 4 - 2 3 5 * 1 4 6 - 1 5 7 id —> to ST entry for d 8 * 4 7 9 + 6 8

  15. Three-address code The DAG does not say anything about how the computation should be carried out. For example, there could be one instruction to do this computation: x+y*z as in, t 1 = x + y * z

  16. Three-address code In three-address code instructions can have no more than one operator on the right of an assignment. x+y*z must be broken into two instructions: t 1 = y * z t 2 = x + t 1

  17. Three address code representation "Three-address code is a linearized representation of … a DAG in which explicit names correspond to the interior nodes of the graph." [p. 363] t 5 t 1 = b - c + t 2 = a * t 1 t 3 t 4 t 3 = a + t 2 + * t 2 t 4 = t 1 * d * t 1 d t 5 = t 3 + t 4 a - b c

  18. Three address code instructions (see 6.2.1, pages 364-5) 1. x = y op z 2. x = op y (treat i2r and r2i as unary ops) 3. x = y 4. goto L 5. if x goto L / ifFalse x goto L 6. if x relop y goto L 7. function calls: - param x - call p, n - y = call p - return y 8. x = y[i] and x[i] = y x = & y, x = *y, *x = y 9.

  19. Representation options "The description of three-address instructions specifies the components of each type of instruction, but it does not specify the representation of these instructions in a data structure." [p. 366]

  20. Quadruples Instructions have four fields: op, arg1, arg2, result Example: t 3 = a + t 2 is represented as op arg1 arg2 result + a t 2 t 3 Example: t 4 = - c is represented as op arg1 arg2 result minus c t 4

  21. Variables in representation Identifiers would be pointers to symbol table entries. Compiler- introduced temporaries can be added to the symbol table. op arg1 arg2 result + —> entry for a —> entry for t 2 —> entry for t 3

  22. Triples Instructions have three fields: op, arg1, arg2 Example: t 2 = … t 3 = a + t 2 is represented as line op arg1 arg2 5 computation of t 2 6 + a (5)

  23. Indirect triples Because order matters (due to embedded references instead of explicit variables) it is more challenging to rearrange instructions with triples than with quadruples. Indirect triples allow for easier reordering (see page 369).

  24. Static Single Assignment (SSA) an additional constraint on the three address code 1) Each variable is assigned to exactly once. x = r + 1 x 1 = r + 1 y = s * 2 y 1 = s * 2 x = 2 * x + y x 2 = 2 * x 1 + y 1 y = y + 1 y 2 = y 1 + 1

  25. Static Single Assignment (SSA) an additional constraint on the three address code 1) Each variable is assigned to exactly once. 2) Need 𝜚 function to merge split variables: if (e) then { x = a } else { x = b } y = x With SSA: if (e) then { x 1 = a } else { x 2 = b } y = 𝜚 ( x 1 , x 2 )

  26. 𝜚 function implementation In y = 𝜚 (x1,x2) simply let y, x1 and x2 be bound to the same address.

  27. §6.3 Types and Declarations

  28. Type equivalence Name equivalence: two types are equivalent if and only if they have the same name. Structural equivalence: two types are equivalent if and only if they have the same structure. A type is structurally equivalent to itself (i.e. int is both name equivalent and structurally equivalent to int)

  29. Name equivalence int x = 3; int y = 5; int z = x * y; The type of z is int. The type of x * y is int. The names of the types are the same, so the assignment is legal.

  30. Structural equivalence types, names and struct S { int v; double w; }; order of fields struct T { int v; double w; }; all align int main() { Under name equivalence the struct S x; assignment is disallowed. x.v = 1; x.w = 4.5; struct T y; Under structural equivalence x = y; the assignment is permitted. return 0; } What does C do?

  31. C does not allow the assignment bash-3.2$ gcc type.c type.c:9:5: error: assigning to 'struct S' from incompatible type 'struct T' x = y; ^ ~ 1 error generated.

  32. Structural equivalence types and order struct S { int v; double w; }; of fields align, struct T { int a; double b; }; but names differ int main() { struct S x; x.v = 1; x.w = 4.5; struct T y; x = y; Should this be allowed? return 0; }

  33. Consider… struct Rectangular { double x; double y; }; struct Polar { double r; double theta; }; int main() { struct Rectangular p; p.x = 3.14; x.y = 3.14; struct Polar q; q = p; Should this be allowed? return 0; }

  34. Interpretation matters polar interpretation rectangular interpretation

  35. Our language (use name equivalence) primitive types: integer, real, Boolean, character, string user-defined types: record types have names type rec : [ real : x := 0, y := 0 ] array types have names type arr : 2 -> string function types have names type fun : ( real : x ) -> rec

  36. Recursive records A record type must allow a component to be of the same type as the type itself: type Node: [ integer datum:=0 ; Node rest:=null ]

  37. Recursive records A record type must allow a component to be of the same type as the type itself: type Node: [ integer datum:=0 ; Node rest:=null ] Be careful how you process declaration: you need to ensure that the second occurrence of Node does not trigger an undefinied

Recommend


More recommend