CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall http:/ /www.cse.buffalo.edu/faculty/alphonce/SP17 /CSE443/index.php https:/ /piazza.com/class/iybn4ndqa1s3ei
shift/reduce conflict with easy fix pblock and dblock similarities seem to result in difficulties (grammar conflicts) Have all teams run into this? A simple fix seems to be: change the delimiters used in dblock from '(' and ')' to '[' and ']', as in: dblock is: '[' declaration-list ']'
Phases of a compiler Intermediate Representation (IR): specification and generation Figure 1.6, page 5 of text
Three address code instructions (see 6.2.1, pages 364-5) 1. x = y op z 2. x = op y (treat i2r and r2i as unary ops) 3. x = y 4. goto L 5. if x goto L / ifFalse x goto L 6. if x relop y goto L 7. function calls: Need operators for - param x various types: let's use - call p, n - y = call p <t>op, as in - return y i+ or r* or b< 8. x = y[i] and x[i] = y x = & y, x = *y, *x = y 9.
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock definition —> type identifier ':' dblock { st.put(identifier.lexeme, TYPE, dblock.type, dblock.width } dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } declaration-list —> declaration ';' declaration-list declaration-list —> declaration declaration —> identifier ':' { id-list.type = identifier; } <— however you store types identifier-list (maybe pointer into st?) identifier-list —> identifier ( sBinOp constant ) ',' { st.put(identifier.lexeme, VAR, identifier-list.type, offset); Just Just offset = offset + identifier-list.type.width; } suggestions, suggestions, identifier-list not to be taken not to be taken identifier-list —> identifier ( sBinOp constant ) literally literally { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock definition —> type identifier ':' dblock We can { st.put(identifier.lexeme, TYPE, dblock.type, dblock.width } specialize due to the structure of our dblock —> '(' grammar: see next slide! { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } declaration-list —> declaration ';' declaration-list declaration-list —> declaration declaration —> identifier ':' { id-list.type = identifier; } <— however you store types identifier-list (maybe pointer into st?) identifier-list —> identifier ( sBinOp constant ) ',' { st.put(identifier.lexeme, VAR, identifier-list.type, offset); Just Just offset = offset + identifier-list.type.width; } suggestions, suggestions, identifier-list not to be taken not to be taken identifier-list —> identifier ( sBinOp constant ) literally literally { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x integer: x integer: x { ( integer : x , y ) push offset = 8 onto stack offset = 16 offset = 24 integer: y integer: y integer: y offset = 8 { ( real : x , z ) … … } Boolean: y character: z pop offset = 8 from stack real: x push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … real: z } pop offset = 8 from stack }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x { ( integer : x , y ) AT RUNTIME push offset = 8 onto stack offset = 16 offset = 24 integer: y offset = 8 { ( real : x , z ) … … } pop offset = 8 from stack push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … } pop offset = 8 from stack }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x integer: x { ( integer : x , y ) AT RUNTIME push offset = 8 onto stack offset = 16 offset = 24 integer: y integer: y offset = 8 { ( real : x , z ) … … } pop offset = 8 from stack real: x push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … real: z } pop offset = 8 from stack }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x { ( integer : x , y ) AT RUNTIME push offset = 8 onto stack offset = 16 offset = 24 integer: y offset = 8 { ( real : x , z ) … … } pop offset = 8 from stack push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … } pop offset = 8 from stack }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x integer: x { ( integer : x , y ) AT RUNTIME push offset = 8 onto stack offset = 16 offset = 24 integer: y integer: y offset = 8 { ( real : x , z ) … … } Boolean: y character: z pop offset = 8 from stack push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … } pop offset = 8 from stack }
dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock —> '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; } declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=Env.pop(); offset=Stack.pop(); } offset = 0 offset = 4 offset = 8 integer: x { ( integer : x , y ) AT RUNTIME push offset = 8 onto stack offset = 16 offset = 24 integer: y offset = 8 { ( real : x , z ) … … } pop offset = 8 from stack push offset = 8 onto stack offset = 10 offset = 8 offset = 9 { ( Boolean : y ; character : z ) … … } pop offset = 8 from stack }
Dealing with alignment Boolean: a integer: x { [ Boolean : a ; integer : x ; character c; real : y ] character: c { [ character : d ; integer : r , s ] … } real: y { [ Boolean : f , g ; real : t ; character h ] … } } Blocks are not aligned.
Dealing with alignment Boolean: a { [ Boolean : a ; integer : x ; character c; real : y ] integer: x { [ character : d ; integer : r , s ] … } character: c { [ Boolean : f , g ; real : t ; character h ] … } } real: y Blocks are not aligned, but memory wasted to padding
Dealing with alignment integer: x { [ Boolean : a ; integer : x ; character c; real : y ] { [ character : d ; integer : r , s ] … } real: y { [ Boolean : f , g ; real : t ; character h ] … } Boolean: a character: c } Blocks are aligned, no padding needed here.
Dealing with alignment integer: x { [ Boolean : a ; integer : x ; character c; real : y ] { [ character : d ; integer : r , s ] … } real: y { [ Boolean : f , g ; real : t ; character h ] … } Boolean: a character: c } Blocks are aligned, integer: r padding needed before embedded scope block. integer: s character: d
Recommend
More recommend