Intermediate Code Generation Control-Flow tatements hort-circuit Predicate valuation Back-Patching Copyright 2011, Pedro C. Diniz, all rights reserved. tudents enrolled in the Compilers class at the University of outhern California have explicit permission to make copies of these materials for their personal use.
Intermediate Code Generation IR Parse tree AT Intermediate Code Generation O(n) IR Three-Address Instructions regs Direct Translation Using DT scheme Parse tree to Three-Address Instructions Can be done while parsing in a single pass Needs to be able to deal with yntactic rrors and Recovery Indirect Translation First validate parsing constructing of AT Uses DT scheme to build AT Traverse the AT and generate Three Address Instructions
Control Flow tatements: Code Layout Attributes:.true: the label to which control flows if is true.false: the label to which control flows if is false.next: an inherited attribute with the symbolic label of the code following if then 1.true:.false:.code 1.code to.true to.false if then 1 else 2.true:.code 1.code to.true to.false.false:.next: goto.next 2.code
Code Layout while do 1.begin:.true:.code 1.code to.true to.false goto.begin.false: Difficulty: Need to know where to jump to Introduce a symbolic labels using the newlabel function Use inherited attributes Back-patch it later with the actual value (later )
Grammar and Actions if then 1.true:.true = newlabel().false =.next.false: 1.next =.next.code = append(.code,gen(.true:), 1.code) if then 1 else 2.true = newlabel().false = newlabelv 1.next =.next 2.next =.next.true:.false :.next:.code 1.code.code 1.code goto.next 2.code.code = append(.code,gen(.true:), 1.code, gen(goto.next),gen(.false :), 2.code) to.true to.false to.true to.false while do 1.begin:.code to.true to.false.begin = newlabel().true:.true = newlabel() 1.code.false =.next goto.begin 1.next =.begin.false.code = append(gen(.begin:),.code,gen(.true:), : 1.code, gen(goto.begin)
Control Flow Translation of Boolean xpressions hort-circuit valuation No Need to valuate portions of the expression if the outcome is already determined xamples: 1 or 2 need not evaluate 2 if 1 is known to be true. 1 and 2 need not evaluate 2 if 1 is known to be false. Use Control Flow Jump over code that evaluates boolean terms of the expression Use Inherited.false and.true attributes and link evaluation of
Control Flow for Boolean xpressions id 1 relop id 2.code = append(gen(if id 1.place relop id 2.place goto.true), gen(goto.false)) true.code = gen(goto.true) false.code = gen(goto.false) not 1 ( 1 ) 1 or 2 1.true =.true 1.false = newlabel 2.true =.true 2.false =.false.code = append( 1.code,gen( 1.false:), 2.code) 1.true =.false 1.false =.true.code = 1.code 1.true =.true 1.false =.false.code = 1.code 1 and 2 1.false =.false 1.true = newlabel 2.true =.true 2.false =.false.code = append( 1.code,gen( 1.true:), 2.code)
hort Circuit valuation a < b or c < d and e < f or and a < b c < d e < f
a < b or c < d and e < f hort Circuit valuation id 1 relop id 2.code = append( gen(if id 1.place relop id 2.place goto.true), gen(goto.false)) 1.true = Ltrue 1.false = L1 or.true = Ltrue.false = Lfalse and 1 or 2 1.true =.true 1.false = newlabel 2.true = Ltrue 2.false = Lfalse 2.true =.true 2.false =.false.code = append( 1.code, gen( 1.false:), 2.code) a < b c < d e < f L1: if a < b goto Ltrue goto L1
a < b or c < d and e < f hort Circuit valuation id 1 relop id 2.code = append( gen(if id 1.place relop id 2.place goto.true), gen(goto.false)) 1.true = Ltrue 1.false = L1 or.true = Ltrue.false = Lfalse 1.true = L2 1.false = Lfalse and 1 and 2 1.false =.false 1.true = newlabel 2.true = Ltrue 2.false = Lfalse 2.true =.true 2.false =.false.code = append( 1.code, 2.true = Ltrue 2.false = Lfalse gen( 1.true:), 2.code) a < b c < d e < f if a < b goto Ltrue goto L1 L1: if c < d goto L2 goto Lfalse L2:
a < b or c < d and e < f hort Circuit valuation id 1 relop id 2.code = append( gen(if id 1.place relop id 2.place goto.true), gen(goto.false)) 1.true = Ltrue 1.false = L1 or.true = Ltrue.false = Lfalse 1.true = L2 1.false = Lfalse and 1 and 2 1.false =.false 1.true = newlabel 2.true = Ltrue 2.false = Lfalse 2.true =.true 2.false =.false.code = append( 1.code, 2.true = Ltrue 2.false = Lfalse gen( 1.true:), 2.code) a < b c < d e < f if a < b goto Ltrue goto L1 L1: if c < d goto L2 goto Lfalse L2: if e < f goto Ltrue goto Lfalse
hort Circuit valuation a < b or c < d and e < f or and a < b c < d e < f if a < b goto Ltrue goto L1 L1: if c < d goto L2 goto Lfalse L2: if e < f goto Ltrue goto Lfalse
Combining Boolean and Control Flow tatements while a < b do if c < d then else x = y + z x = y - z while do 1.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin) while do if then then a < b c < d
while a < b do if c < d then else x = y + z CCI 565 - Compiler Design Combining Boolean and Control Flow tatements x = y - z while do 1.next = Lnext.begin = L1.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) while.true = L2 do.false = Lnext.next = L1 if then then a < b c < d
while while a < b do if c < d then else x = y + z x = y - z CCI 565 - Compiler Design Combining Boolean and Control Flow tatements.true = L2 do.false = Lnext while do 1.next = Lnext.begin = L1.next = L1.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) L1: if a < b goto L2 L2: goto Lnext if then then a < b c < d
while while a < b do if c < d then else x = y + z x = y - z CCI 565 - Compiler Design Combining Boolean and Control Flow tatements.true = L2 do.false = Lnext if while do 1.next = Lnext.begin = L1 then.true = L3.false = L4.next = L1 then.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) 1.next = L1 2.next = L1 L1: if a < b goto L2 goto Lnext L2: if c < d goto L3 L3: goto L4 a < b c < d
while while a < b do if c < d then else x = y + z x = y - z a < CCI 565 - Compiler Design Combining Boolean and Control Flow tatements.true = L2 b do.false = Lnext if while do 1 c.next = Lnext.begin = L1 < d then.true = L3.false = L4.next = L1 then.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) 1.next = L1 2.next = L1 L1: if a < b goto L2 goto Lnext L2: if c < d goto L3 goto L4 L3: t1 = x + z L4: x = t1 goto L1
while while a < b do if c < d then else x = y + z x = y - z a < CCI 565 - Compiler Design Combining Boolean and Control Flow tatements.true = L2 b do.false = Lnext if while do 1 c.next = Lnext.begin = L1 < d then.true = L3.false = L4.next = L1 then.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) 1.next = L1 2.next = L1 L1: if a < b goto L2 goto Lnext L2: if c < d goto L3 goto L4 L3: t1 = x + z x = t1 goto L1 L4: t2 = x - z Lnext: x = t2 goto L1
while a < b do if c < d then else x = y + z x = y - z CCI 565 - Compiler Design Combining Boolean and Control Flow tatements while do 1.begin = newlabel.true = newlabel.false =.next 1.next =.begin.code = append(gen(.begin:),.code, gen(.true:), 1.code, gen(goto.begin)) L1: if a < b goto L2 goto Lnext while do if then then L2: if c < d goto L3 goto L4 L3: t1 = x + z a < b x = t1 goto L1 L4: t2 = x - z c < d x = t2 goto L1 Lnext:
Loop Constructs Loops valuate condition before loop (if needed) valuate condition after loop Branch back to the top (if needed) Pre-test Why this structure? Merges test with last block of loop body Pre-test block to hold loop-invariant code Post-test for increment instructions and test Loop head B1 B2 while, for, do, & until all fit this basic model Post-test Next block
Break & kip tatements Many modern programming languages include a break xits from the innermost control-flow statement Out of the innermost loop Out of a case statement Pre-test Translates into a jump Targets statement outside control- flow construct Creates multiple-exit construct skip in loop goes to next iteration Only make sense if loop has > 1 block Break in B1 Loop head B1 B2 Post-test Next block kip in B2
Break and kip tatements Need to Keep Track of nclosing Control-Flow Constructs Harder to have clean DT scheme Keep a tack of control-flow constructs Using.next as in the stack as the target for the break statement For skip statements need to keep track of the label of the code of the post-test block to advance to the next iteration. This is harder since the code has not been generated yet. Back-Patching helps Use a breaklist and a skiplist to be patched later.
Case tatements case or switch tatements emantics 1 valuate the controlling expression 2 Branch to the selected case 3 xecute the code for that case 4 Branch to the statement after the case Parts 1, 3, & 4 are well understood, part 2 is the key trategies Linear search (nested if-then-else constructs) Build a table of case expressions & binary search it Directly compute an address (requires dense case set) urprisingly many compilers do this for all cases!
switch begin case V 1 : 1 Case tatement: Code Layout code to valuate into t goto Ltest L 1 : code for 1 goto Lnext case V 2 : 2 case V n-1 : n-1 default: n end L 2 : code for 2 goto Lnext L n-1 : code for n-1 goto Lnext L n : code for n goto Lnext Ltest: if t = V 1 goto L 1 if t = V 2 goto L 2 Linear earch Lnext: if t = V n-1 goto L n-1 goto L n
DT scheme for Case tatements Issue: Need to ave the Labels and Values for the various cases for the test code at the end Use a Right-Recursive Grammar Use queue to save pairs (value, label) for generation of search code In the end pop values from queue to generate the linear search Use a Left-Recursive Grammar Cleaner; No queue is needed Use of the parsing stack to accumulate the non-terminals and corresponding attribute
Grammar and Actions switch List end.code = append(.code,gen( goto Ltest ),List.code,gen( Ltest: ) while(queue not empty) do { (vi,li) = pop.queue; if (vi = default).code = append(.code,gen( goto Li )); else.code = append(.code,gen( if t = vi goto Li )); Case case Value : Case.code = append(gen( Li: ),.code,gen( goto Lnext ); queue.push((value.val,li)); List Case ; List 1 List.code = append(case.code,list 1.code); List default : List.code = append(gen( Li: ),.code,gen( goto Lnext ); queue.push((default,li)) List ε List.code = append(gen( Li: ),gen( goto Lnext ); queue.push((default,li))
Other tatements Declarations Just save information in ymbol Table For tructures, Unions compute offsets for each field Function Calls Generate code to evaluate each argument in order into temporaries mit the call instruction using the temporary variables tructures, Variants Records and Unions Use the offsets from symbol table for address generation Unstructured Control-Flow Breaks the DT scheme, just use a global table and backpatch it.
Back- Patching ingle Pass olution to Code Generation? No more symbolic labels - symbolic addresses instead mit code directly into an array of instructions Actions associated with Productions xecuted when Bottom-Up Parser Reduces a production Problem Need to know the labels for target branches before actually generating the code for them. olution Leave Branches undefined and patch them later Requires: carrying around a list of the places that need to be patched until the value to be patched with is known.
Boolean xpressions Revisited Use Additional ε-production Just a Marker M Label Value M.addr Attributes:.truelist: code places that need to be filled-in corresponding to the evaluation of as true..falselist: same for false (1) 1 or M 2 (2) 1 and M 2 (3) not 1 (4) ( 1 ) (5) id 1 relop id 2 (6) true (7) false (8) M ε
Boolean xpressions: Code Outline 1 or 2 1 and 2 false 1.code true true 1.code false false 2.code true false 2.code true???
Auxiliary Functions Functions: makelist(i): make a list with the label i merge(p1,p2): creates a new list of labels with lists p1 and p2 backpatch(p,i): fills the locations in p with the address i newaddr() : returns a new symbolic address in sequence and increments the value for the next call Array of Instructions Linearly sequence of instructions Function emit to generate actual instructions in the array ymbolic Addresses
Using the Actions & List Attributes (5) id 1 relop id 2 {.truelist := makelist(newlabel);.falselist := makelist(newlabel); emit( if id 1.place relop id 2.place goto _ ); emit( goto _ ); } 100: if a < b then goto _ 101: goto _ 102:.truelist = {100}.falselist = {101} a < b
More Actions (3) not 1 {.truelist := 1.falselist;.falselist := 1.truelist; } (4) ( 1 ) {.truelist := 1.truelist;.falselist := 1.falselist; } (5) id 1 relop id 2 {.truelist := makelist(nextaddr());.falselist := makelist(nextaddr()); emit( if id 1.place relop.op id 2.place goto _ ); emit( goto _ ); } (6) true {.truelist := makelist(nextaddr()); emit( goto _ ); } (7) false {.falselist := makelist(nextaddr()); emit( goto _ ); }
Actions (1) 1 or M 2 { backpatch( 1.falselist,M.Addr);.truelist := merge( 1.truelist, 2.truelist);.falselist := 2.falselist; } (2) 1 and M 2 { backpatch( 1.truelist,M.Addr);.truelist := 2.truelist;.falselist := merge( 1.falselist, 2.falselist); } (8) M ε { M.Addr := nextaddr; }
Back-Patching xample xecuting Action Generated Code.truelist.falselist M M.addr.truelist =.falselist = a < or.truelist =.falselist = b M ε M.addr = and.truelist =.falselist =.truelist =.falselist = M ε M.addr = e <.truelist =.falselist = f c < d
.truelist.falselist M M.addr CCI 565 - Compiler Design Back-Patching xample xecuting Action {.truelist := makelist(nextquad());.falselist := makelist(nextquad()); emit( if id1.place relop.op id2.place goto _ ); emit( goto _ ); } Generated Code 100: if a < b goto _ 101: goto _.truelist =.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = and.truelist =.falselist =.truelist =.falselist = M ε M.addr = e <.truelist =.falselist = f c < d
.truelist.falselist M M.addr CCI 565 - Compiler Design Back-Patching xample xecuting Action { M.quad = nextquad(); } Generated Code 100: if a < b goto _ 101: goto _.truelist =.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist =.truelist =.falselist = M ε M.addr = e <.truelist =.falselist = f c < d
.truelist.falselist M M.addr CCI 565 - Compiler Design Back-Patching xample xecuting Action {.truelist := makelist(nextquad());.falselist := makelist(nextquad()); emit( if id1.place relop.op id2.place goto _ ); emit( goto _ ); } Generated Code 100: if a < b goto _ 101: goto _ 102: if c < d goto _ 103: goto _.truelist =.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = e <.truelist =.falselist = f c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { M.quad = nextquad(); } 100: if a < b goto _ 101: goto _ 102: if c < d goto _ 103: goto _.truelist =.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = 104 e <.truelist =.falselist = f c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code {.truelist := makelist(nextquad()); 100: if a < b goto _.falselist := makelist(nextquad()); 101: goto _ emit( if id1.place relop.op id2.place goto _ ); 102: if c < d goto _ emit( goto _ ); } 103: goto _ 104: if e < f goto _.truelist = 105: goto _.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { backpatch( 1.truelist,M.quad); 100: if a < b goto _.truelist := 2.truelist; 101: goto _.falselist := merge( 1.falselist, 2.falselist; } 102: if c < d goto _ 103: goto _ 104: if e < f goto _.truelist = 105: goto _.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { backpatch( 1.truelist,M.quad); 100: if a < b goto _.truelist := 2.truelist; 101: goto _.falselist := merge( 1.falselist, 2.falselist; } 102: if c < d goto _ 103: goto _ 104: if e < f goto _.truelist = 105: goto _.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { backpatch( 1.truelist,M.quad); 100: if a < b goto _.truelist := 2.truelist; 101: goto _.falselist := merge( 1.falselist, 2.falselist; } 102: if c < d goto 104 103: goto _ 104: if e < f goto _.truelist = 105: goto _.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist =.falselist = M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { backpatch( 1.truelist,M.quad); 100: if a < b goto _.truelist := 2.truelist; 101: goto _.falselist := merge( 1.falselist, 2.falselist; } 102: if c < d goto 104 103: goto _ 104: if e < f goto _.truelist = 105: goto _.falselist = a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist = {104}.falselist = {103, 105} M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
.truelist.falselist M M.addr Back-Patching xample xecuting Action Generated Code { backpatch( 1.truelist,M.quad); 100: if a < b goto _.truelist := 2.truelist; 101: goto 102.falselist := merge( 1.falselist, 2.falselist; } 102: if c < d goto 104 103: goto _ 104: if e < f goto _.truelist = {100, 104} 105: goto _.falselist = {103, 105} a < or.truelist =.falselist = b {100} {101} M ε M.addr = 102 and.truelist =.falselist = {102} {103}.truelist = {104}.falselist = {103, 105} M ε M.addr = 104 e <.truelist =.falselist = f {104} {105} c < d
Back-Patching xample 100: if a < b goto _ 101: goto 102 102: if c < d goto 104 103: goto _ 104: if e < f goto _ 105: goto _ while M 1 do M 2 1 { backpatch( 1.nextlist, M 1.addr); backpatch(.truelist,m 2.addr);.nextlist :=.falselist; emit( goto M 1.addr ); }.truelist = {100, 104}.falselist = {103, 105}
Back-Patching xample 100: if a < b goto _ 101: goto 102 102: if c < d goto 104 103: goto _ 104: if e < f goto _ 105: goto _ while M 1 do M 2 1 { backpatch( 1.nextlist, M 1.addr); backpatch(.truelist,m 2.addr);.nextlist :=.falselist; emit( goto M 1.addr ); }.truelist = {100, 104}.falselist = {103, 105} 1
Back-Patching xample 100: if a < b goto _ 101: goto 102 102: if c < d goto 104 103: goto _ 104: if e < f goto _ 105: goto _ while M 1 do M 2 1 { backpatch( 1.nextlist, M 1.addr); backpatch(.truelist,m 2.addr);.nextlist :=.falselist; emit( goto M 1.addr ); }.truelist = {100, 104}.falselist = {103, 105} 1
Control Flow Code tructures if then 1 if then 1 else 2 while do 1.code.code.begin:.code.true: 1.code.true: 1.code.true: 1.code.false:....false: goto.next 2.code.false: goto.begin...next:....
Control Flow Constructs: Conditionals Add the nextlist attribute to and N denotes the set of locations in the code to be patched with the address that follows the execution of Can be either due to control flow or fall-through (1) if then M 1 1 N else M 2 2 { backpatch(.truelist, M 1.addr); backpatch(.falselist,m 2.addr);.nextlist := merge( 1.nextlist,merge(N.nextlist, 2.nextlist)); } (2) N ε { N.nextlist := makelist(nextaddr(); emit( goto _ ); } (3) M ε { M.quad := nextaddr; } (4) if then M 1 { backpatch(.truelist, M.addr);.nextlist := merge(.falselist, 1.nextlist); }
Control Flow Constructs: Loops (5) while M 1 do M 2 1 { backpatch( 1.nextlist, M 1.addr); backpatch(.truelist,m 2.addr);.nextlist :=.falselist; emit( goto M 1.addr ); }
equencing: List of tatements Additional ymbols L for list of statements for Assignment statement (6) begin L end {.nextlist = L.nextlist; } (7) A {.nextlist = nil; } (8) L L 1 ; M { backpatch(l 1.nextlist, M.addr); L.nextlist =.nextlist; } (9) L { L.nextlist =.nextlist; }
xtended xample L i = 0; L M 1 while (i < n) do begin if(a <= k) then a = a + 1; A ε while M 1 do M 2 1 ε ( ) ε begin L end id rel id i++; L 1 M 1 1 end ε A if then M 1 1 ( ) ε A id rel id
ummary Intermediate Code Generation Using yntax-directed Translation chemes Conditional Boolean using hort-circuit valuation Control-Flow Back-Patching Allows Code Generation in a ingle Pass