UP | HOME

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

Diagrams

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
    1. gets the node's type,
    2. constructs the name of the function using it, e.g., visitAssignment,
    3. 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)

Author: Paul Gazzillo

Created: 2024-02-08 Thu 10:51