Presentation is loading. Please wait.

Presentation is loading. Please wait.

Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts.

Similar presentations


Presentation on theme: "Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts."— Presentation transcript:

1 Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts is lecturer’s own symbolic locations and jump targets, like in many assembly languages, will be used  these would need to be resolved to actual machine addresses before the code could be run all operands in arithmetic expressions and comparisons are integers we deal only with arithmetic expressions, boolean expressions, assignment statements, while-loop statements  ignoring e.g. type declarations, if-then-else statements, most array references, function and procedure calls, record and class definitions, etc etc code is generated as a string, by concatenating substrings code is stored as the value of an attribute of a parse tree node run-time speed of generated code is not a concern http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction1

2 Arithmetic expressions: simple code generation The general idea is that semantic actions are associated with every production in the grammar dealing with expressions and subexpressions. These actions systematically set two particular attributes  ‘code’ – a string containing arbitrarily many 3-address-code instructions  ‘loc’ – a symbol naming the location where the value for the (sub)expression will be placed when those instructions are executed New locations can be invented as required. Code construction may involve adding something to the code already generated for sub- sub-expressions. http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction2 E ::= E + T{E.loc=newloc(); E.code=E 1.code || T.code || gen(add, E.loc, E 1.loc,T.loc)}

3 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction3 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num

4 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction4 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

5 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction5 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

6 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction6 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

7 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction7 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

8 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction8 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

9 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction9 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

10 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction10 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { E.loc = newloc(); E.code=E 1.code || T.code || gen(sub, E.loc, E 1.loc,T.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

11 Add actions to a basic grammar http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction11 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { E.loc = newloc(); E.code=E 1.code || T.code || gen(sub, E.loc, E 1.loc,T.loc)} { E.loc = newloc(); E.code=E 1.code || T.code || gen(add, E.loc, E 1.loc,T.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

12 Is ‘code’ a synthesised attribute? That grammar had left-recursive productions, unsuited to top-down parsing, and all attributes were synthesised. If left-recursion is eliminated from a grammar, we have seen previously that for an existing synthesised attribute it may be necessary to introduce two new attributes, one inherited and one synthesised. There is a pattern for doing this: Where there are two original productions A ::= A b | c, a new nonterminal is needed, say A’ three non-left-recursive productions are needed For any existing synthesised attribute q used in the 2 original productions  the original q attribute is used only in the new production for A ::= c A’  an inherited attribute, say qi, passes progressively refined values for q down the right hand side of a parse tree, from A to A’ and from A’ to lower A’  a synthesised attribute, say qs, passes the ultimate value for q back up the tree http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction12

13 Attribute transformations in left-recursion removal http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction13 A ::= A b A ::= c { A.q = f ( A 1.q, b.q)} { A.q = g(c) } A ::= c { A’.qi = g(c) } A’ { A.q = A’.qs } A’ ::= b { A’ 1.qi = f( A’.qi, b.q)} A’ { A’.qs = A’ 1.qs} A’ ::=  { A’.qs = A’.qi} These grammars both generate one c followed by any number of b’s E ::= E + T E ::= E – T E ::= T { …, E.code= f1 (E 1.code, T.code) } { …, E.code = f2(E 1.code, T.code) } { …, E.code = g(T) } E ::= T { ? } E’ { E.code=E’.codes } E’ ::= + T { ? } E’ { E’.codes = E’ 1.codes } E’ ::= - T { ? } E’ { E’codes = E’ 1.codes } E’ ::=  { E’.codes = E’.codei } These grammars both generate one T followed by any number of either “+ T” or “- T” sequences Exercise: What replaces the ?s (in terms of f1, f2 and g)

14 Assignment statements In a programming language assignment statement, the value of an expression on the right-hand side is calculated and stored in a location named on the left-hand side. In general the location may be something simple like an identifier, an array element, a record slot. Calculation of a storage address is perhaps required. The expression on the right-hand side may be arbitrarily complicated. Calculation of a quantity is required. These two kinds of calculation are for so-called lvalue and rvalue respectively. Assn ::= id := Expr Assn ::= id [ Expr ] := Expr http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction14 { Assn.code = Expr.code || gen(load, id.lexval, Expr.loc)} { Assn.addr = newloc(); Assn.code = Expr 2.code || Expr 1.code || gen(add, Assn.addr, symtabaddr(id.lexval), Expr 1.loc) || gen(loadindirect, Assn.addr, Expr 2.loc)} gets the identifier’s address from compiler’s symbol table

15 Boolean Expressions Boolean expression syntax usually includes elements for  logical constants true and false  comparisons of arithmetic quantities – equal, not equal, greater, etc  boolean variables, array elements, functions etc  logical operators and or and not Boolean expressions have two uses  to calculate boolean quantities to be stored in variables, arrays etc  to determine flow of control – in loops, in if-then-else statements Compound boolean expressions can be evaluated in two distinct ways  akin to arithmetic expressions: evaluate subexpressions then combine values  in a “short-circuit” mode: later subexpressions may not always get evaluated http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction15 e.g. (k >= 0) and (k <= 99) and (B[k] /= 0)

16 Jumping code Code generated for boolean expressions almost always includes jumps & labels to affect control flow to use short-circuit evaluation exception possible only if both full evaluation and calculation to produce a value http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction16 Syntax WHILE boolexpr DO statement label one: <code for boolexpr that jumps -- to label two if true -- to label three if false> label two: jump to label one label three: Translation sketch Syntax bool 1 AND bool 2 Translation sketch (short-circuit) <code for bool 1 that jumps -- to label four if true -- to falselabel if false> label four: <code for bool 2 that jumps -- to truelabel if true -- to falselabel if false> inherited attributes in SDD/SDT

17 Semantic actions for sample of boolean productions Bool ::= http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction17 Expr < Expr Bool AND Bool { Bool.code= { Bool 1.falselabeli = Bool.falselabeli Bool 2.falselabeli = Bool.falselabeli Bool 1.truelabeli = newlabel() Bool 2.truelabeli = Bool.truelabeli Bool.code = Expr 1.code || Expr 2.code || gen(jumpifless, Expr 1.loc, Expr 2.loc, Bool.falselabeli) || gen(jumpalways, Bool.truelabeli) } Bool 1.code || gen(label, Bool 1.truelabeli) || Bool 2.code } Labels are not actual instructions, though they are generated as if they were. They are names attached to the next actual instruction in the sequence.

18 Where Boolean expressions are found Grammar productions which have a Bool anywhere on the right-hand-side must provide values for its falselabeli and truelabeli attributes In translating While loops, two labels are needed anyway to handle a return-to-start and escape-to-end situation. A third label is needed if the boolean expression is to be given short-circuit treatment – language designer’s choice In translating If-Then-Else statements, two labels are needed anyway, to handle the jump to the start of the else-code, and to handle the completion of the then-code. Again a third label is needed, labelling the start of the then-code, if the boolean expression is to be given short-circuit treatment. In translating assignments to boolean variables, two labels are needed. http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction18

19 Translating a While Loop http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction19 Stmt ::=while Bool do Stmt { Stmt.label_one= newlabel(); Stmt.label_two=newlabel(); Stmt.label_three=newlabel(); Bool.truelabeli=Stmt.label_two; Bool.falselabel=Stmt.label_three; { } { Stmt.code = gen(label, Stmt.label_one) || Bool.code || gen(label, Stmt.label_two) || Stmt 1.code || gen(jumpalways, Stmt.label_one) || gen(label, Stmt.label_three) }

20 Translating a While Loop http://csiweb.ucd.ie/staff/acater/comp30330.html Compiler Construction20 Stmt 0 ::=while Bool do Stmt 1 { Stmt 0.label_one= newlabel(); Stmt 0.label_two=newlabel(); Stmt 0.label_three=newlabel(); Bool.truelabeli=Stmt 0.label_two; Bool.falselabel=Stmt 0.label_three; { } { Stmt 0.code = gen(label, Stmt 0.label_one) || Bool.code || gen(label, Stmt 0.label_two) || Stmt 1.code || gen(jumpalways, Stmt 0.label_one) || gen(label, Stmt 0.label_three) }


Download ppt "Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts."

Similar presentations


Ads by Google