UP | HOME

Project 4

Table of Contents

Overview

In this project, you will implement support for pointer variables as well as control-flow constructs.

This project only needs to implement a subset of the simplec language:

  • there is only one level of indirection for pointers, no need for pointers to pointers.
  • there is no need to support type casting.
  • no need to support arrays
  • only need to support and &&, or ||, not !, equality ==, and less than <

It is left as a challenge for bonus points to implement more features of the language, such as multiple levels of pointers, array allocation and indexing, etc.

Setup

There are no additional setup instructions beyond project 3. No precompiled version of project 3 will be provided, since the test cases will not exercise those constructs. The only construct shared between project 3 and project 4 is the assignment statement, which is also needed to support pointers.

Using your compiler

# this builds your compiler
make
# this runs your compiler to compiler a simplec program
cat if.simplec | ./simplec > if.s
# this assembles and links the simplec program into an executable
gcc if.s  # produces a.out.  use -o NAME to give your executable a better name
./a.out
echo $? # prints the return value of the program

Testing

Be sure to unit test as you go. The grading repository will have the tests used for grading.

Use gdb to step through your simplec output program. First, install it with

sudo apt install gdb

Clone and install this useful gdb assistant called peda. Make sure you have already compiled your simplec program as shown in "Using your compiler" above. Then step through the program like so:

gdb a.out
set disassembly-flavor att
# once inside of gdb
b main # set a breakpoint at main
run # start the program.  it will wait at main
si # step through each assembly instruction
# continue stepping through to track the behavior

If you've downloaded and installed peda, you will see the assembly code, registers, and stack displayed after each step.

Examples

Code generation rules

Type cast

For this project, just pass through any value on the stack, i.e., just do codegen_expr(expr->castexpr.expr);.

It is left as a bonus challenge to implement different bitwidths for different types and do the appropriate conversion for the type cast.

Unary reference operator &

this operation gets the address of the variable, rather than its contents. to do so, we need to get the offset and subtract that from the base pointer and save that result in another register.

  • only allow an identexpr to be referenced, i.e., make sure that the expr->unaryexpr.expr->kind is an E_identexpr
  • save the base pointer to another register, e.g., rax
  • like codegen_identexpr, lookup the identifier's offset in scope
  • compute the address by subtracting the offset from the base pointer copy in rax
  • save the result by pushing it onto the stack

Reading from dereferenced pointer with a unary dereference operator

  • generate code for the expression in the derefernce expression expr->unaryexpr.expr
  • retrieve the value by popping it from the stack
  • use memory indirection addressing to mov the contents of the memory address computed in the dereference expression to a register, e.g., mov (%rax), %rbx
  • save the result onto the stack

Assigning to dereferenced pointer in an assignment statement

  • generate code for the deref on the left side of an expression
  • generate code for the right-hand side of the assignment
  • pop the result of the right-hand side
  • pop the result of the left-hand side
  • move the right-hand side's value into the address pointed to by the left-hand size using memory indirect addressing, e.g., mov %rax, (%rbx)

Control-flow constructs and Boolean operators

Relational operators

Operators

  • ==
  • <

These work just like Boolean operators, except using different jump instructions.

See the reference to pick the right one. Note that the code may be easier to write by testing for the opposite case, e.g., test for >= for < to jump when the condition does not hold (just like for if statements).

https://www.felixcloutier.com/x86/jcc

References

Author: Paul Gazzillo

Created: 2020-11-13 Fri 15:17