CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall
Announcements Weekly team meetings with me: - Doodle poll link in Piazza Wednesday (4/ 4) will be a workshop Wednesday - Post questions you'd like addressed in Piazza by Sunday (4/1) evening
Phases of a compiler Intermediate Representation (IR): specification and generation Figure 1.6, page 5 of text
Intermediate Representations
Sizes of types Q: Since the number of type string: 1 -> character dimensions is part of the type, do we need to store it at runtime? 8 bytes + length of string * size A: No. of character (= 1 byte) # of dimensions size of dimension (0) (1) (2) (3) (4) 1 (integer) 0 0 0 1 0 0 0 5 V A X E S https:/ / en.wikipedia.org/wiki/VAX
Sizes of types type string: 1 -> character 4 bytes + length of string * size of character (= 1 byte) size of dimension (0) (1) (2) (3) (4) 1 (integer) 0 0 0 5 V A X E S https:/ / en.wikipedia.org/wiki/VAX
Sizes of types 0 size of 0 first 0 dimension 2 0 size of 0 second What is the size of a multi- 0 dimension dimensional array of type T? 3 a(0,0) sizes of dimensions (S i ): X*4 bytes a(0,1) first row data: ( ∏ i ∈ X S i ) * sizeOf(T) a(0,2) a(1,0) a(1,1) second row a(1,2)
Figure 6.16, p 375 t = array(2,array(3,int)) T w = 24 t = array(2,array(3,int)) B C T = int w = 24 w = 4 t = array(3,int) int C w = 12 [2] t = int C w = 4 [3] For the purposes of type checking the number of dimensions is relevant, but the size of each 𝜁 dimension is not. Q: if a and b are compatible array types, what are the semantics of a := b ?
Figure 6.16, p 375 What if type info comes after 9+array(2,arr(3,character)) dimensions? w = 9 + 6 * 1 = 15 T C w = 2 * 3 B w = 6 character C w = 3 w = 1 [2] C [3] 𝜁
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 }
Recommend
More recommend