Intermediate Representation
COP-5621, Spring 2024
Table of Contents
Review
Questions about the last class?
Questions about project setup
Homework discussion
While3Addr
- Syntax and Semantics
- Closer to machine code
- No structured code, branching
- One arithmetic operation per instruction
- Program counter
- But infinite registers, variable names
Interpreter
show the interpreter and how it lines up with the semantics (or really vice-versa)
- match is the first premise
- maintaining two pieces of state, the memory (E) and the program counter
- assigning or using memory involves looking it up in mem (E)
- op is abstracted away
- non-branch operations just increment the pc
- branch operations set the pc, e.g., goto
- check result of relationship operation for ifgoto
Goal: Translate While to While3Addr
Example translations
- Arithmetic expressions
- Decompose into each operation
- If statements
- Use ifgoto
- Relational operators
- Convert to equivalent < or = expression
- Swap operands as needed
- Boolean operators
- Use ifgoto
w = x * y + z t1 = x * y t2 = t1 + z if b then S1 else S2 # assignment to a constant t1 := 7 x = y x = 3 # while language x := y + 7 # while3addr t1 := 7 x := y + t1 if b then goto 4 S2 S1 if x >= 0 then S1 else S2 not (x >= 0) => x < 0 # legal while3addr code switch to less than negate x switch to less than swap S1 and S2 # not legal while3addr 1: if x > 0 then goto 4 2: S2 3: goto 5 4: S1 5: x > 0 => 0 < x => 0 - x < x - x => -x < 0 neg1 = -1 t1 = -1 * x if t1 < 0 x > 0 x - 1 >= 0 1. get the sign to be < = 2. deal with the right operand t1 < 0 t1 = 0 x < y => x - y < y - y => x - y < 0 => t1 = x - y t1 < 0 x > y => x - x > y - x => 0 > y - x => y - x < 0 => t1 = y - x t1 < 0 if a and b then b = x and y use divide to get mod use mod to get boolean operators if x then if y then b = true else b = false else b = false 0 false non-zero true x y b 1 1 | 1 1 0 | 0 0 1 | 0 0 0 | 0 b = x and y # test whether something is false 1: if x = 0 goto 5 2: if y = 0 goto 5 3: b = 1 4: goto 6 5: b = 0 6:
While loop
Grammar
ANTLR grammar
grammar While; s: ID ':=' a # Assignment | 'skip' # Skip // | s ';' s # Sequence | 'if' b 'then' s 'else' s # If | 'while' b 'do' s # While | 'begin' s (';' s)* 'end' # Compound ; b: 'true' # True | 'false' # False | 'not' b # Not | b op=('and' | 'or') b # BOp | a op=('<' | '<=' | '=' | '>' | '>=') a # ROp | '(' b ')' # BParen ; a: ID # Var | NUM # Num | a op=('+' | '-' | '*' | '/') a # AOp | '(' a ')' # AParen ; TRUE: 'true' ; FALSE: 'false' ; AND: 'and' ; OR: 'or' ; NOT: 'not' ; ID: [a-zA-Z] ([a-zA-Z] | [0-9])* ; NUM: [0-9]+ ; EQ: '=' ; LT: '<' ; LE: '<=' ; GT: '>' ; GE: '>=' ; PLUS: '+' ; MINUS: '-' ; MULT: '*' ; DIV: '/' ; WS: [ \t\n\r]+ -> skip ; SL_COMMENT: '//' .*? '\n' -> skip ;
Disambiguating the grammar
- begin/end
- parentheses
Example parse trees
Nested constructs
Nested arithmetic expressions
temporary variables to save intermediate values
use tree structure to manage temporary variables and orderings
tree traversal equivalent to recursion
Nested control-flow constructs
use the tree/recursion to maintain state for backpatching
wait for nested constructs to get program counters
Formalizing the translation
Syntax-directed translation
Apply translation rules while traversing the parse tree
while x > 0 do x := x - 1
Visitors
- Allows you to add functions to a class without modifying it, e.g., parse tree, without having to modify the class
- E.g., one parse tree datatype, any number of visitors classes
- Helps traverse parse trees (each node one grammar construct)have subtypes)
What the Visitor class does
- While walking the tree, visitor picks function
- e.g., visitAssignment, visitVar, visitConst, etc.
- Calling visit(n) on a node n, the visitor
- gets the node's type,
- constructs the name of the function using it, e.g., visitAssignment,
- then calls the function
Example visitor
- Visitors mirror semantics (rule match grammar constructs)
- Example: Print "saw assignmnt" whenever we see an assignment
- (Diagram)
Example using visit()
- Print assignment and var
- visitAssignment calls visit()
- (Code, Diagram)
Implementing the translation visitor
Compare to translation rules
One visitor function for each construct
All constructs return intermediate code
Expressions also return name of variable holding result
Use current program counter instead of using arithmetic
Save to list of output instructions
Statements vs. expressions
- Intermediate values
- Temporary variables
Premises represent calls to visit
Easy way, expression visitors create new temporary variables each time (numbers, variables, arithmetic, etc.)
Expressions always return var that will contain the value at runtime. Remember we are not interpreting, but considering all possible inputs, so we generate a program with a variable that will hold the value of the expression.
Nested and sequential constructs, gluing together generated code (provide guarantees to parent, e.g., returns new var holding the result)
Helper APIs
Creating While3Addr instructions
visitAssignment
visitVar
Adding instructions to the output
Accessing parse tree terminals
ctx.ID().getText()
ctx.op.type
Accessing parse tree nonterminals
self.visit(ctx.a())
self.visit(ctx.a(1))
Getting new temporary variables
visitTrue
Accessing the current program counter
visitNot
Backpatching
handling if statements handling boolean logic (intuition, no instruction here for that!) handling relationals (mapping to only lt/eq; tip, common generator for all)