Compiler Design
Spring 2018 2.3 Templates (for code generation) 2.4 Template-based code generator
26
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
26
§ 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
§ 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
§ reg_pool: Pool (list) of free registers § Methods
§ get_register() § free_register(Register register)
29
§ Value must be put into reg § Template
// bookkeeping // get a new register reg = reg_pool.getRegister() // code generation emit “movl $0x…, reg” // no more bookkeping return reg;
30
value v 0x…: hexadecimal representation of v
§ 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
§ 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
§ 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
§ Assume name maps to a known location
§ Various addressing modes exist § For now: Simple scheme is sufficient
34
§ 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
37
§ Result must be put into reg § Assume left and right evaluated into a register
§ reg_right § reg_left
§ Reuse one of the registers to hold result
§ Take reg_right
§ Free other register
§ No longer needed: reg_left
38
OP +
right
register reg_right
left
register reg_left
§ 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
§ Value must be put into reg § Left hand side: Destination for a (named) variable
§ We can get the variable name § Use variable name in assembly instruction
§ Right hand side: result in register § No “return value”
40
=
VAR
A
right
register reg_right Memory location of variable A
§ 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
§ 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
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
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
47
48
§ Examples
§ a = 1 § a = b + c § x = b + c + d + e
50
52
56
1
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
§ Use reg_right for the result of an operation § We decided to visit the right subtree first
§ Visit the left subtree first § (Use reg_left for the result of an operation – won’t show that here)
8
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
10
11
12
14
a = b + c + d + e reg_pool = {%eax,%ebx,%ecx,%edx}
16
17
18
19
= x * v + + y z w
20
21
= x * v + + y z w
§ Visit node § Determine which order is best (uses the smallest number of registers) § Record order (right first or left first)
§ Visit node § Look at result from first step to fix evaluation order
24
§ If no difference, favor right first
25
26
§ If no difference, favor right first
27
28
29
30
31
§ Visit node § Determine which order is best (uses the smallest number of registers) § Record order (right first or left first)
§ Visit node § Look at result from first step to fix evaluation order
34
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
// Template 2.3.3 return reg_right; } } }
35
36
37
§ Later recompute (“rematerialize”) § Temporarily store value in memory (“spill”) – usually on stack
§ Recall that this step may change the semantics
41
42
= x + + b c + d e = x + + + b e c d
43
§ Later recompute (“rematerialize”) § Temporarily store value in memory (“spill”) – usually on stack
§ Recall that this step may change the semantics
§ See next slides on code generator improvements
45
46
47
Generated code movl 0x1, %rax movl x, %rbx addl %rbx, %rax + x 1 … Improved code movl x, %rax inc %rax
49
ADD register, memory ADD memory, register
ADD register, register)
50
51
+ x + … … + x + … …
53
+ x + … … %eax movl x, %ebx addl %ebx, %eax + x + … … %eax addl x, %eax %ebx
54
55