300 likes | 547 Views
CSC 415: Translators and Compilers Spring 2009. Chapter 7 Code Generation. Code Generation. Code Selection A Code Generation Algorithm Constants and Variables Procedures and Functions Case Study: Code Generation in the Triangle Compiler. Code Generation.
E N D
CSC 415: Translators and CompilersSpring 2009 Chapter 7 Code Generation
Code Generation • Code Selection • A Code Generation Algorithm • Constants and Variables • Procedures and Functions • Case Study: Code Generation in the Triangle Compiler
Code Generation • Translation of the source program to object code • Dependent on source language and target machine • Target Machines • Registers, or stack, or both for intermediate results • Instructions with zero, one, two, or three operands, or a mixture • Single addressing mode, or many
Code GenerationMajor Subproblems • Code selection: which sequence of target machine instructions will be the object code for each phrase • Write code templates: a general rule specifying the object code of all phases of a particular form (e.g., all assignment commands, etc.) • But there are usually lots of special cases • Storage allocation: deciding the storage address of each variable in source program • Exact for glob al variables, but only relative for local variables • Register allocation: should be used to hold intermediate results during expression evaluation • Complex expressions -- not enough registers Since code generation for stack machine much simpler than for register machine, will only generate code for stack machine
Code GenerationCode Selection • Deciding which sequence of instructions to generate for each case • Code template: specifies the object code to which a phrase is translated, in terms of the object code to which its sub phrases are translated. • Object code: sequence of instructions to which the source-language phrase will be translated • Code specification: collection of code functions and code templates; must cover the entire source langauge
Abstract Machine TAM • Suitable for executing programs compiled from a block-structured language such as Triangle • All evaluation takes place o a stack • Primitive arithmetic, logical, and other operations are treated uniformly with programmed functions and procedures • Two separate stores • Code Store: 32-bit instruction words (read only) • Data Store: 16-bit data words (read-write)
Abstract Machine TAMCode and Data Stores • Code Store • Fixed while program is running • Code segment: contains the program’s instructions • CB points to base of code segment • CT points to top of code segment • CP points to next instruction to be executed • Initialized to CB (programs first instruction is at base of code segment) • Primitive segment: contains ‘microcode’ for elementary arithmetic , logical, input-output, heap, and general-purpose operations • PB points to base of primitive segment • PT points to top of primitive segment
Abstract Machine TAMCode and Data Stores • Data Store • While program is running segments of data store may vary • Stack grows from low-address end of Data Store • SB points to base of the stack • ST points to top of the stack • Initialized to SB • Heap grows from the high-address endo fo Data Store • HB points to base of heap • HT points to top of heap • Initialized to HB
Code Store CB code segment CP CT unused PB primitive segment PT Abstract Machine TAMCode and Data Stores Data Store SB global segment • Stack and heap can expand and contract • Global segment is always at base of stack • Stack can contain any number of other segments known as frames containing data local to an activation of some routine • LB points to base of topmost frame frame stack LB frame ST unused HT heap segment HB
Code Functions run P Run the program P and then halt, starting and finishing with an empty stack Execute the command C, possibly updating variables, but neither expanding nor contracting the stack Execute the expression E, pushing its result on to the stack top, but having no other effect Push the value of the constant or variable named V on to the stack top Pop a value from t he stack top, and store it in the variable named V Elaborate the declaration D, expanding the stack to make space for any constants and variables declared therein execute C evaluate E fetch V assign V elaborate D
Abstract Machine TAMInstructions Fetch an n-word object from the data address (d+register r), and push it on the stack Push the data address (d+register r) on to the stack Pop a data address from the stack, fetch an n-word object from that address, and push it on to the stack Push the 1-word literal value d on to the stack Pop an n-word object from the stack, and store it at the data address (d+register r) Pop an address from the stack, then pop an n-word object from t he stack and store it at that address Call the routine at code address (d+register r), using the address in register n as the static link Pop a closure (static link and code address) from the stack, then call the routine at that code address Return from the current routine: pop an n-word result from the stack, then pop the topmost frame, then pop d words of arguments, then push the result back on to the stack Push d words (uninitialized) on to the stack Pop an n-word result from the stack, then pop d more words, then push the result back on to the stack Jump to code address (d+register r) Pop a code address from the stack, then jump to that address Pop a 1-word value from the stack, then jump to code address (d+register r) if and only if that value equals n Stop execution of the program LOAD(n) d[r] LOADA d[r] LOADI(n) LOADL d STORE(n) d[r] STOREI(n) CALL(n) d[r] CALLI RETURN(n) d PUSH d POP(n) d JUMP d[r] JUMPI JUMPIF(n) d[r] HALT
While Command • execute [[while E do C]] = JUMP h • g: execute C • h: evaluate E JUMPIF(1) g
30: JUMP 35 // JUMP h g: 31: LOAD i 32: LOADL 2 33: CALL sub 34: STORE i h: 35: LOAD i 36: LOADL 0 37: CALL gt 38: JUMPIF(1) 31 // JUMPIF(1) g While Command • execute [[while i > 0 do i := i – 2]] • execute [[i := I – 2]] • execute [[i > 0]]
While Command public Object visitWhileCommand(WhileCommand ast, Object o) { Frame frame = (Frame) o; int jumpAddr, loopAddr; jumpAddr = nextInstrAddr; // saves the next instruction address (g:) to put in JUMP command emit(Machine.JUMPop, 0, Machine.CBr, 0); // puts the JUMP h instruction in obj file loopAddr = nextInstrAddr; // this is address g: ast.C.visit(this, frame); // this generates code for C patch(jumpAddr, nextInstrAddr); // this establishes address h: that was needed in the JUMP h statement ast.E.visit(this, frame); // this generated code for E emit(Machine.JUMPIFop, Machine.trueRep, Machine.CBr, loopAddr); // this generated code to check expression, if false to address g: return null; }
While Command • execute [[while E do C]] = g: execute C evaluate E JUMPIF(1) g
g: 31: LOAD i 32: LOADL 2 33: CALL sub 34: STORE i 35: LOAD i 36: LOADL 0 37: CALL lt 38: JUMPIF(0) 31 // JUMPIF(0) g Repeat Command • execute [[repeat i := i – 2 until i < 0 do ]] • execute [[i := i – 2]] • execute [[i > 0]]
Repeat Command public Object visitRepeatCommand(RepeatCommand ast, Object o) { Frame frame = (Frame) o; int jumpAddr, loopAddr; // emit(Machine.JUMPop, 0, Machine.CBr, 0); // jumpAddr = nextInstrAddr; loopAddr = nextInstrAddr; ast.C.visit(this, frame); // patch(jumpAddr, nextInstrAddr); ast.E.visit(this, frame); emit(Machine.JUMPIFop, Machine.falseRep, Machine.CBr, loopAddr); return null; }
ST ST ST Result E2 Result E2 V1 V2 V2 Result E1 Extend Mini-TriangleV1 , V2 := E1 , E2 • This is a simultaneous assignment: both E1 and E2 are to be evaluated, and then their values assigned to the variables V1 and V2, respectively evaluate E1 evaluate E2 assign V2 assign V1 Results pushed to top of stack Results pushed to top of stack Top of stack stored in variable V2 Top of stack stored in variable V1 ST ST Result E1 Result E1 Result E1 Result E2
Extend Mini-TriangleC1 , C2 • This is a collateral command: the subcommands C1 and C2 are to be executed in any order chosen by the implementer execute C1 execute C2 Top of stack unchanged Top of stack unchanged
Extend Mini-Triangleif E then C • This is a conditional command: if E evaluates to true, C is executed, otherwise nothing evaluate E JUMPIF (0) g execute C g: Results pushed to top of stack Jump to g if E evaluates to false Top of stack unchanged Jump location
Extend Mini-Trianglerepeat C until E • This is a loop command: E is evaluated at the end of each iteration (after executing C), and the loop terminates if its value is true g: execute C evaluate E JUMPIF (0) g Top of stack unchanged Results pushed to top of stack Jump to g if E evaluates to false
Extend Mini-Trianglerepeat C1 while E do C2 • This is a loop command: E is evaluated in the middle of each iteration (after executing C1 but before executing C2), and the loop terminates if its value is false JUMP h g: execute C2 h: execute C1 evaluate E JUMPIF (1) g Top of stack unchanged Top of stack unchanged Results pushed to top of stack Jump to g if E evaluates to true
Extend Mini-Triangleif E1 then E2 else E3 • This is a conditional expression: if E1 evaluates to true, E2 is evaluated, otherwise E3 is evaluated (E2 and E3 must be of the same type) evaluate E1 JUMPIF (0) g evaluate E2 JUMP h g: evaluate E3 h: Results pushed to top of stack Jump to g if E evaluates to false Results pushed to top of stack Jump location Results pushed to top of stack
Extend Mini-Trianglelet D in E • This is a block expression: the declaration D is elaborated, and the resultant bindings are used in the evaluation of E elaborate D evaluate E POP (n) s Expand stack for variables or constants Results pushed to top of stack Pop an n word from stack, pop s more, then push first n-word back on stack If s>0 where s = amount of storage allocated by D n = size (type of E)
Extend Mini-Trianglebegin C; yield E end • Here the command C is executed (making side effects), and then E is evaluated execute C evaluate E Top of stack unchanged Results pushed to top of stack
Extend Mini-Trianglefor I from E1 to E2 do C • First the expressions E1 and E2 are evaluated, yielding the integer m and n, respectively. Then the subcommand C is executed repeatedly, with I bound to integers m, m+1, …, n in successive iterations. If m < n, C is not executed at all. The scope of I is C, which may fetch I but may not assign to it.
Extend Mini-Trianglefor I from E1 to E2 do C evaluate E2 evaluate E1 JUMP h g: execute C CALL succ h: LOAD –1 [ST] LOAD –3 [ST] CALL le JUMPIF(1) g POP(0) 2 Compute final value Compute initial value of I Top of stack unchanged Increment current value of I Fetch current value of I Fetch final value Test current value <= final value If so, repeat Discard current and final values At g and at h, the current value of I is at the stack top (at address –1 [ST], and the final value is immediately underlying (at address –2 [ST]