CpS 450 Language Translation Systems

Variables and Expressions

Assignment Statement

Consider the Assignment Statement x := 5

Must be able to generate code to:

  • Evalute an expression
  • Place the result in the memory location assigned to the variable/parameter

Declaration Processing

Your compiler must generate code that will associate each variable declared in a Dream program with a memory location at runtime.

Consider the following Dream variable declaration:

x: int

To allocate a 32-bit word of global memory and give it a label, you emit the following:

.comm x, 4, 4

You can use this approach for int and boolean variables. We’ll deal with strings in the next phase.

Expression Evaluation

Problems to deal with:

  • Expressions can be complicated, containing several levels of subexpressions
  • Need to store intermediate results temporarily
  • Might use registers, but what if we run out?

Solution:

  • Use the run-time stack to store intermediate results
  • The final result of an expression is always left on the top of the stack

Literal Expressions

Integers are easy:

visitIntLitExprInfo(IntLitExprContext node)
  emit("pushl", node.INTEGER().getText())

Booleans: Pick a representation (I suggest 0 for false, 1 for true).

Identifier Expressions

visitIdExpr(IdExprContext node)
  String name = node.ID().getText();
  // Generate code to push the contents of the variable onto the stack
  emit("pushl",name);

Binary Expressions

Must generate code to evaluate both subexpressions. After doing this, the results are left on the stack. All we have to do is pop the two values off, do the computation, and push the result.

visitBinExpr(BinExprContext node)
  visit(node.e1);          // generate code to evaluate first expression
  visit(node.e2);          // generate code to evaluate second expression
  emit("popl", "%ebx");    // get second expression result
  emit("popl", "%eax");    // get first expression result
  switch (node.getOp()) {
    case '+': 
      emit("addl", "%ebx", "%eax");
      break;
    case '-': 
      ...
  }
  emit("pushl", "%eax");   // push result of this expression

Tip: To figure out how to generate assembly to evaluate a particular operator, I suggest compiling a simple program like `examples/codegen/cfun/cdemo.c using gcc with the -S option, and then looking at the generated assembly. Alternatively, you can try the Godbolt Compiler Explorer tool.

Assignment Statements

Now that we know how to process variable declarations, and we can process expressions, doing an assignment statement is easy:

visitAsmtStmt(AsmtStmtContext node) should 1) Visit the expression, generating code to evaluate it, and then 2) generate code to pop off the expression result and store it in the variable’s memory location:

popl %eax
movl %eax, id