Final Exam Page 1 of 8 CS 152: Compiler Design Final Exam Peter H. Fröhlich phf@cs.ucr.edu March 14, 2003 Time: 40 Minutes Start here: Fill in the following important information using a permanent pen before you do anything else! Your exam will not be graded if you use a pencil or erasable ink on this page. Name (print): Student ID (print): Login (print): Cheat Sheet: Signature: Instructions: Please read these instructions carefully. Switch off your phones, pagers, and other noisy gadgets! You can not have anything but your ID, a pen, your cheat sheet, and this exam on your desk. You can not talk to anyone during the exam. If you have a question, please raise your hand quietly. You must hand in your cheat sheet with the exam. You must remain seated quietly until all exams have been collected. You can not claim grading errors if you do not use a permanent pen for your answers. And finally: Good luck! :-) Do not open the exam before you are told to do so! You received CS 152: Compiler Design out of 40 points. Winter 2003 Final Exam 1 Warmup For each of the following statements, determine whether it is either true or false. Page 2 of 8 (10 points) (1 point each) 1. In a single-pass compiler, each compilation phase completes before the next compilation phase starts. 2. It is not advisable to use a single intermediate representation for compiling both C++ and VAL (a functional dataflow language). 3. The language produced by L → “y” | “x” L “x” is regular. 4. An LR(k) parser processes tokens from left to right, looks at most k tokens ahead, and performs left-most reductions. 5. The regular expression (“a”|“b”)+ , the EBNF grammar E = {“a”|“b”} , and the BNF grammar B → “a” B | “b” B | generate the same language. 6. In S IMPLE, the declaration CONST y = 0 + y + 1; leads to an error because we can not apply constant folding to its expression. 7. Weak symbols can be used to re-synchronize the parser with the input stream after a syntax error occurred. 8. Good error handling, although driven mostly by heuristics, is indispensable for production quality compilers. 9. The primary concern when developing static analyses that help with code optimization is that they terminate quickly. 10. In terms of instruction selection, implementing a code generator for a RISC architecture is generally easier than implementing one for a CISC architecture. CS 152: Compiler Design Winter 2003 Final Exam Page 3 of 8 2 Hard Choices For each of the following questions, circle one answer out of the choices given. (8 points) (2 points each) 1. Consider the task of recognizing keywords during lexical analysis. Assume a large set of potentially long keywords. Which of the following techniques is most appropriate (“efficient”)? (a) Binary search on a sorted array of keywords. (b) A switch on the first letter followed by cascaded if instructions. (c) A hash table with a perfect hash function. (d) An optimal binary search tree. (e) None of the above. 2. Consider the syntax for declarations in S IMPLE (see also page 8). In both VarDecl and Type we find the fragment {IdentifierList ":" Type ";"}. How can we simplify the grammar, the parser, and the generation of symbol tables (all three at once)? (a) Replace the fragment with {VarDecl} in Type. (b) Split Type into NamedType, ArrayType, and RecordType, then do (a). (c) Move "CONST", "VAR", and "TYPE" up into Declarations, then do (a). (d) Do (b) but not yet (a), then do (c) including (a). (e) None of the above. 3. Consider building a compiler for C and PASCAL which will generate code for x86 and PowerPC platforms, with specific optimizations for about 10 members of each family. What compiler architecture is least suitable for this task? (a) A multi-pass compiler consisting of separate programs communicating through files. (b) A multi-pass compiler using source-level abstract syntax trees and a shared symbol table. (c) A tightly integrated single-pass compiler with a shared symbol table. (d) Since all of these can be made to work, I don’t prefer one or the other. (e) None of the above. 4. Consider a language with parallel assignments such as “x, y := y, x” to swap the values of two variables. Which evaluation strategy is most appropriate for this construct? (a) Evaluate corresponding “pairs” in sequence, i.e. “x := y; y := x”. (b) Evaluate corresponding “pairs” in reverse, i.e. “y := x; x := y”. (c) Evaluate all designators (left side) into addresses first, then follow (a). (d) Evaluate all expressions (right side) into values first, then follow (b). (e) None of the above. CS 152: Compiler Design Winter 2003 Final Exam Page 4 of 8 3 Syntactic Analysis (8 points) Consider logical expressions made up of the operators “and”, “or”, and “not”, as well as identifiers and parenthesis “(” and “)”. Similar to S IMPLE’s arithmetic expressions (see page 8), these operators have different precedences: “not” binds the strongest, followed by “and”, followed by “or”. For example, the expression a or not b and c should be parsed as (a or ((not b) and c)) which is a legal expression itself. Identifiers are defined below, and you should assume that operators are treated as keywords (tokens). 1. Give a context-free grammar for logical expressions that models operator precedence and is suitable for an LL(1) parser. Hint: This just asks for a grammar, it does not ask you to change the S IMPLE grammar. (6 points) identifier = letter { letter } . letter = "a" .. "z" | "A" .. "Z" . 2. If you were to add logical expressions to S IMPLE, what would you change in the concrete syntax (see page 8) besides productions related to Expression? (2 points) CS 152: Compiler Design Winter 2003 Final Exam Page 5 of 8 4 Symbol Tables (4 points) Consider the following S IMPLE program and sketch the symbol table (ST) that should be generated for it by the parser. You do not have to sketch an abstract syntax tree, but you must indicate pointers to it where necessary (just label them “AST”). PROGRAM ST; TYPE A = ARRAY 1 OF INTEGER; TYPE R = RECORD s, t: RECORD x, y: ARRAY 1 OF INTEGER; END; END; END ST. CS 152: Compiler Design Type Scope Cons tant Varia ble Winter 2003 Final Exam Page 6 of 8 5 Abstract Syntax Trees (4 points) Consider the following S IMPLE program and sketch the abstract syntax tree (AST) that should be generated for it by the parser. Include “the usual” AST transformations. You do not have to sketch a symbol table, but you must indicate pointers to it where necessary (just label them “ST”). PROGRAM AST; TYPE A = ARRAY 3 OF RECORD x, y: INTEGER; END; VAR a: A; BEGIN READ a[1].y; END AST. CS 152: Compiler Design Type Node Cons tant Varia ble Winter 2003 Final Exam 6 Code Generation Page 7 of 8 (6 points) Consider the following S IMPLE program and give the V MICS code that should be generated for it. You must include a sketch of storage allocation for data memory, as well as the addresses of all instructions in code memory. You can ignore bounds checking for arrays. You can not be smarter than the compiler would be. Please comment your code to make sure that we can grade it easily; if things are too confusing, we’ll ignore those parts we can’t make sense of. PROGRAM VMICS; CONST s = 16; VAR i: INTEGER; VAR a: ARRAY s OF INTEGER; BEGIN i := 0; REPEAT a[i] := i UNTIL i > s END END VMICS. CS 152: Compiler Design Winter 2003 Final Exam Page 8 of 8 This page is intentionally mostly blank in case you run out of space elsewhere. If you ended up here early, please go over everything again and remain seated quietly! You should probably check that the title page is filled out using a permanent pen. Maybe you want to “rewrite” your answers as well to be able to claim grading errors? If you’re really bored, try this: Who can make a broken program work by breaking it some more? Program = "PROGRAM" identifier ";" Declarations ["BEGIN" Instructions] "END" identifier "." . Declarations = { ConstDecl | TypeDecl | VarDecl } . ConstDecl = "CONST" {identifier "=" Expression ";"} . TypeDecl = "TYPE" {identifier "=" Type ";"} . VarDecl = "VAR" {IdentifierList ":" Type ";"} . Type = identifier | "ARRAY" Expression "OF" Type | "RECORD" {IdentifierList ":" Type ";"} "END" . Expression = ["+"|"-"] Term {("+"|"-") Term} . Term = Factor {("*"|"DIV"|"MOD") Factor} . Factor = number | Designator | "(" Expression ")" . Instructions = Instruction {";" Instruction} . Instruction = Assign | If | Repeat | While | Read | Write . Assign = Designator ":=" Expression . If = "IF" Condition "THEN" Instructions ["ELSE" Instructions] "END" . Repeat = "REPEAT" Instructions "UNTIL" Condition "END" . While = "WHILE" Condition "DO" Instructions "END" . Condition = Expression ("="|"#"|"<"|">"|"<="|">=") Expression . Write = "WRITE" Expression . Read = "READ" Designator . Designator = identifier Selector . Selector = {"[" ExpressionList "]" | "." identifier} . IdentifierList = identifier {"," identifier} . ExpressionList = Expression {"," Expression} . CS 152: Compiler Design Mnenomic Opcode Data Description halt error push pop dup swap out in add sub mul div mod load store $00 $01 $10 $11 $12 $13 $20 $21 $30 $31 $32 $33 $34 $40 $41 value value - jump jneg jeql jpos $50 $51 $52 $53 value value value value stop execution stop execution with error code push value on stack pop value from stack duplicate top of stack swap top two stack values print pop() push( input_value ) r = pop(); l = pop(); push( l+r r = pop(); l = pop(); push( l-r r = pop(); l = pop(); push( l*r r = pop(); l = pop(); push( l/r r = pop(); l = pop(); push( l%r a = pop(); push( memory[a] ) a = pop(); v = pop(); memory[a] := v pc := value if pop() < 0 then pc := value if pop() = 0 then pc := value if pop() > 0 then pc := value ) ) ) ) ) Winter 2003