compiler design
play

Compiler Design Spring 2018 2.3 Templates (for code generation) - PowerPoint PPT Presentation

Compiler Design Spring 2018 2.3 Templates (for code generation) 2.4 Template-based code generator Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 26 2.3 Templates Templates decide how code generator behaves


  1. Compiler Design Spring 2018 2.3 Templates (for code generation) 2.4 Template-based code generator Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 26

  2. 2.3 Templates § Templates decide how code generator behaves § “Quality” of code § Decide how each kind of IR node is handled § Simple (for now) § Minimal solution (for now) § Next: Produce a catalogue of templates 27

  3. Ground rules § Set of rules to guide template design § Reflect machine properties and/or desire to keep CG simple § You could define your own rules § Rules for now: 1. All templates leave result in a register Exception: ASSIGN nodes have no return value § 2. All operands must be in a register Lots of memory traffic for 32-bit x86 § Other options: § (1) At least one operand must be in a register (2) At most one operand can be in memory 28

  4. Data structures § reg_pool : Pool (list) of free registers § Methods § get_register() § free_register(Register register) 29

  5. 2.3.1 CONST § Value must be put into reg § Template // bookkeeping // get a new register reg = reg_pool.getRegister() // code generation emit “movl $0x…, reg” value // no more bookkeping v return reg; 0x…: hexadecimal representation of v 30

  6. Potential problems § No register in reg_pool § Not today § Value ’v’ does not fit into movl instruction § v requires more than 32 bits § v exceeds limit of immediate in instruction § Options § Delegate problem to assembler § Can break v into pieces, shift/assembly in register § Allocate entry in .data segment, load from memory § Require that IR contains only constants that fit into movl § Front-end must deal with problem § Homework #1: Assume only values that fit 31

  7. 2.3.2 VAR § Recall: § VAR node on the left hand side of ASSIGN: delivers an address § VAR node on the right hand side of ASSIGN (anywhere in tree): delivers a value § Value is kept in a memory location (known to the compiler) § Later: Other storage classes 32

  8. VAR (at RHS) § Value must be put into register § Similar to CONST node § Template // bookkeeping // get a new register reg = reg_pool.getRegister() // code generation emit “movl name, reg” // name identifies location // no more bookkeping return reg; 33

  9. Comment § Assume name maps to a known location § Various addressing modes exist § For now: Simple scheme is sufficient 34

  10. VAR (at LHS) § Must deliver an address § For now: Enough to deliver a name § Template: Let parent use the name § Assume we have a method that returns the name for a VAR node § Only user so far: ASSIGN 35

  11. 37

  12. OPERATOR § Result must be put into reg § Assume left and right evaluated into a register § reg_right OP + § reg_left register register reg_left reg_right § Reuse one of the registers to hold result § Take reg_right left right § Free other register § No longer needed: reg_left 38

  13. OPERATOR § Template // bookkeeping // code generation emit “OP[Operator].txt reg_left, reg_right” // bookkeeping // free reg_left reg_pool.free_register(reg_left) // no more bookkeping return reg_right; § Could ask for a new register § Benefit: Keeps around values for longer § Not really an option with 32-bit x86 (limited # of registers) 39

  14. 2.3.4 ASSIGN § Value must be put into reg § Left hand side: Destination for a (named) variable § We can get the variable name = § Use variable name in Memory register assembly instruction location of reg_right variable A § Right hand side: result in register VAR right A § No “return value” 40

  15. 2.3.4 ASSIGN § Template // preparation // code generation emit “movl reg_right, name” // bookkeeping // free reg_right reg_pool.free_register(reg_right) // no more bookkeping return null; 41

  16. 2.4 Putting the CG together § Code for children must be generated before code for parents can be generated § codegen(Node n) { … } § Start with codegen(Root) § codegen(Node n) § Leafnode? Generate code § Not leafnode? Visit children § In which order? § Code for node n 43

  17. Skeleton Register codegen(Node n) { Register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: } } 45

  18. Right child first Register codegen(Node n) { Register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_right = codegen(N.right_child); reg_left = codegen(N.left_child); // Template 2.3.3 return reg_right; } } } 46

  19. 47

  20. 48

  21. How does it work? § Examples § a = 1 § a = b + c § x = b + c + d + e 50

  22. 52

  23. 56

  24. Compiler Design Spring 2018 2.5 Dynamic programming code generation Thomas R. Gross Computer Science Department ETH Zurich, Switzerland 1

  25. Motivation: Recall “right child first” Register codegen(Node n) { register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_right = codegen(N.right_child); reg_left = codegen(N.left_child); // Template 2.3.3 return reg_right; } } } 2

  26. Discussion We decided to § § Use reg_right for the result of an operation § We decided to visit the right subtree first We could have decided to § § Visit the left subtree first § (Use reg_left for the result of an operation – won’t show that here) 8

  27. Left child first Register codegen(Node n) { register reg_right, reg_left; case (typeOf n) { ASSIGN: { reg_right = codegen(N.right_child); // Template 2.3.4 } VAR : // Template 2.3.2 CONST: //Template 2.3.1 OP: { reg_left = codegen(N.left_child); reg_right = codegen(N.right_child); // Template 2.3.3 return reg_right; } } } 9

  28. How does it work (left-first) § Example § a = b + c + d + e 10

  29. 11

  30. 12

  31. a = b + c + d + e reg_pool = {%eax,%ebx,%ecx,%edx} 14

  32. Discussion § Using a smaller number of registers is better than using a larger number of registers § Right child first: 2 registers (%eax, %ebx) § Left child first: 4 registers (%eax, %ebx, %ecx, %edx) § Should we forget about “left child first”? 16

  33. No evaluation order is the best Find an assignment statement (with only + as operand and four operands on the right hand side) such that for this statement the “visit left child first” strategy delivers a better result (smaller number of registers is needed) than the “visit right child first” strategy. You can jump right to the tree if you wish. 17

  34. No evaluation order is the best § Example § x = (((z + w) + y) + v) 18

  35. No evaluation order is the best Left child first = x * + v + y z w 19

  36. 20

  37. No evaluation order is the best Right child first = x * v + + y z w 21

  38. No evaluation order is the best § No strategy is best for all possible trees § Decide for each node how children should be evaluated § Idea: 2-step approach Step 1: Determine strategy § Visit node § Determine which order is best (uses the smallest number of registers) § Record order (right first or left first) Step 2: Generate code § Visit node § Look at result from first step to fix evaluation order 24

  39. Dynamic programming code generation § Step 1 must determine both the number of registers needed and the evaluation order § need : number of registers § right_first : boolean (true/false) § If no difference, favor right first § We must make some assumptions 25

  40. Simplifications (in machine model) § Assumptions § All registers are equal § All operations deliver result into a register § All operands/results require a single register § No optimizations (reuse of operands) § Real machines do not always meet these assumptions § Some offer new opportunities § Example: Take one operand from memory (later) 26

  41. 2.5 Dynamic programming code generation § Step 1 must determine both the number of registers needed and the evaluation order § need : number of registers § right_first : boolean (true/false) § If no difference, favor right first § Four kinds of nodes to consider § VAR: need = 1 § CONST: need = 1 § ASSIGN: need determined by right child § OPERATOR: see next slide 27

  42. 28

  43. Key idea § To get smallest number of registers: § Evaluate larger subtree (expression) first § Keep result in register § Recall assumptions § All registers created equally 29

  44. OPERATOR node § Case 1: right_child.need > left_child.need § right_first = § need = § Case 2: right_child.need < left_child.need § right_first = § need = § Case 3: right_child.need == left_child.need § right_first = § need = 30

  45. OPERATOR node § Case 1: right_child.need > left_child.need § right_first = true § need = right_child.need § Case 2: right_child.need < left_child.need § right_first = false § need = left_child.need § Case 3: right_child.need == left_child.need § right_first = true § need = right_child.need + 1 31

Recommend


More recommend