Skip to content

Commit

Permalink
generate 3 address code
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Oct 11, 2010
1 parent c415a5e commit eae318e
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 57 deletions.
10 changes: 7 additions & 3 deletions TODO
@@ -1,8 +1,12 @@
Project 1 Release:
* test object instantiation & new keyword
* test strings
Project 2 Release:

Bonus:
* add NOT operator
* test for negating non-numeric types
* document enum hax
* test for expressions in a compare (1 < this)
* test for boolean expression in if statement
* pass the test that crashes program
* evaluate constant expressions before semantic checking
* test for invalid/valid array indicies with expressions like 8*8-32
* print statement with trailing comma (meaning no newline)
Expand Down
311 changes: 291 additions & 20 deletions code_generation.cpp
@@ -1,28 +1,98 @@
#include "code_generation.h"
#include "insensitive_map.h"

#include <vector>
#include <cassert>
#include <iostream>

class Instruction {
struct Instruction {
enum Type {
COPY,
OPERATOR,
UNARY,
IMMEDIATE_BOOLEAN,
IMMEDIATE_INT,
};
Type type;

Instruction(Type type) : type(type) {}
};

struct CopyInstruction : public Instruction {
int dest; // register number
int source; // register number
CopyInstruction(int dest, int source) : Instruction(COPY), dest(dest), source(source) {}
};

struct OperatorInstruction : public Instruction {
enum Operator {
EQUAL, NOT_EQUAL, LESS, GREATER, LESS_EQUAL, GREATER_EQUAL,
PLUS, MINUS, OR,
TIMES, DIVIDE, MOD, AND,
};

int dest;
int left;
Operator _operator;
int right;

OperatorInstruction(int dest, int left, Operator _operator, int right) : Instruction(OPERATOR), dest(dest), left(left), _operator(_operator), right(right) {}
};

struct UnaryInstruction : public Instruction {
enum Operator {
NOT,
NEGATE,
};

int dest;
Operator _operator;
int source;

UnaryInstruction(int dest, Operator _operator, int source) : Instruction(UNARY), dest(dest), _operator(_operator), source(source) {}
};

struct ImmediateBoolean : public Instruction {
int dest;
bool constant;

ImmediateBoolean(int dest, bool constant) : Instruction(IMMEDIATE_BOOLEAN), dest(dest), constant(constant) {}
};

struct ImmediateInteger : public Instruction {
int dest;
int constant;

ImmediateInteger(int dest, int constant) : Instruction(IMMEDIATE_INT), dest(dest), constant(constant) {}
};

class CodeGenerator {
private:
std::vector<Instruction *> m_instructions;
int next_register_number;

class CodeGenerator {
public:
CodeGenerator() : m_register_count(0) {}
void generate(FunctionDeclaration * function_declaration);

void pretty_print();

private:
int current_index() { return m_instructions.size(); }
std::vector<Instruction *> m_instructions;
OrderedInsensitiveMap<int> m_variable_numbers;
int m_register_count;

void scan_statement_list(StatementList * statement_list);
void scan_statement(Statement * statement);
int scan_expression(Expression * expression);
private:
int current_index() { return m_instructions.size(); }
int next_available_register() { return m_register_count++; }

void gen_statement_list(StatementList * statement_list);
void gen_statement(Statement * statement);
int gen_expression(Expression * expression);
int gen_additive_expression(AdditiveExpression * additive_expression);
int gen_multiplicitive_expression(MultiplicativeExpression * multiplicative_expression);
int gen_negatable_expression(NegatableExpression * negatable_expression);
int gen_primary_expression(PrimaryExpression * primary_expression);
int gen_variable_access(VariableAccess * variable);

void add_assignment(VariableAccess * variable, int value_register);
void gen_assignment(VariableAccess * variable, int value_register);
};

void generate_code(Program * program) {
Expand All @@ -32,25 +102,114 @@ void generate_code(Program * program) {
FunctionDeclaration * function_declaration = function_list_node->item;
CodeGenerator generator;
generator.generate(function_declaration);

std::cout << "3 Address Code for " << function_declaration->identifier->text << std::endl;
std::cout << "--------------------------" << std::endl;
generator.pretty_print();
std::cout << "--------------------------" << std::endl;
std::cout << std::endl;
}
}
}

void CodeGenerator::pretty_print() {
for (unsigned int i=0; i<m_instructions.size(); ++i) {
Instruction * instruction = m_instructions[i];
switch (instruction->type) {
case Instruction::COPY:
{
CopyInstruction * copy_instruction = (CopyInstruction *) instruction;
std::cout << "$" << copy_instruction->dest << " = $" << copy_instruction->source << std::endl;
break;
}
case Instruction::OPERATOR:
{
OperatorInstruction * operator_instruction = (OperatorInstruction *) instruction;
std::cout << "$" << operator_instruction->dest << " = $" << operator_instruction->left << " ";
switch (operator_instruction->_operator) {
case OperatorInstruction::EQUAL:
std::cout << "=="; break;
case OperatorInstruction::NOT_EQUAL:
std::cout << "!="; break;
case OperatorInstruction::LESS:
std::cout << "<"; break;
case OperatorInstruction::GREATER:
std::cout << ">"; break;
case OperatorInstruction::LESS_EQUAL:
std::cout << "<="; break;
case OperatorInstruction::GREATER_EQUAL:
std::cout << ">="; break;
case OperatorInstruction::PLUS:
std::cout << "+"; break;
case OperatorInstruction::MINUS:
std::cout << "-"; break;
case OperatorInstruction::OR:
std::cout << "||"; break;
case OperatorInstruction::TIMES:
std::cout << "*"; break;
case OperatorInstruction::DIVIDE:
std::cout << "/"; break;
case OperatorInstruction::MOD:
std::cout << "%"; break;
case OperatorInstruction::AND:
std::cout << "&&"; break;
default:
assert(false);
}
std::cout << " $" << operator_instruction->right << std::endl;
break;
}
case Instruction::UNARY:
{
UnaryInstruction * unary_instruction = (UnaryInstruction *) instruction;
std::cout << "$" << unary_instruction->dest << " = ";
if (unary_instruction->_operator == UnaryInstruction::NEGATE)
std::cout << "-";
else if (unary_instruction->_operator == UnaryInstruction::NOT)
std::cout << "!";
else
assert(false);
std::cout << "$" << unary_instruction->source << std::endl;
break;
}
case Instruction::IMMEDIATE_BOOLEAN:
{
ImmediateBoolean * immediate_bool_instruction = (ImmediateBoolean *) instruction;
std::cout << "$" << immediate_bool_instruction->dest << " = " << (immediate_bool_instruction->constant ? "true" : "false") << std::endl;
break;
}
case Instruction::IMMEDIATE_INT:
{
ImmediateInteger * immediate_int_instruction = (ImmediateInteger *) instruction;
std::cout << "$" << immediate_int_instruction->dest << " = " << immediate_int_instruction->constant << std::endl;
break;
}
}
}
}

void CodeGenerator::generate(FunctionDeclaration * function_declaration) {
scan_statement_list(function_declaration->block->statement_list);
for (VariableDeclarationList * variable_list = function_declaration->block->variable_list; variable_list != NULL; variable_list = variable_list->next) {
for (IdentifierList * id_list = variable_list->item->id_list; id_list != NULL; id_list = id_list->next)
m_variable_numbers.put(id_list->item->text, next_available_register());
}

gen_statement_list(function_declaration->block->statement_list);
}

void CodeGenerator::scan_statement_list(StatementList * statement_list) {
for (StatementList * statement_list_node = statement_list; statement_list_node != NULL; statement_list_node = statement_list_node->next)
scan_statement(statement_list_node->item);
void CodeGenerator::gen_statement_list(StatementList * statement_list) {
for (StatementList * statement_list_node = statement_list; statement_list_node != NULL; statement_list_node = statement_list_node->next) {
if (statement_list_node->item != NULL)
gen_statement(statement_list_node->item);
}
}

void CodeGenerator::scan_statement(Statement * statement) {
void CodeGenerator::gen_statement(Statement * statement) {
switch (statement->type) {
case Statement::ASSIGNMENT:
{
int value_register = scan_expression(statement->assignment->expression);
add_assignment(statement->assignment->variable, value_register);
int value_register = gen_expression(statement->assignment->expression);
gen_assignment(statement->assignment->variable, value_register);
break;
}
/*
Expand Down Expand Up @@ -88,15 +247,127 @@ void CodeGenerator::scan_statement(Statement * statement) {
}


int CodeGenerator::scan_expression(Expression * expression) {
return 0;
int CodeGenerator::gen_expression(Expression * expression) {
if (expression->right == NULL) {
// it's just the type of the first additive expression
return gen_additive_expression(expression->left);
} else {
// we're looking at a compare operator
int left = gen_additive_expression(expression->left);
int right = gen_additive_expression(expression->right);
int dest = next_available_register();
OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(expression->_operator->type + OperatorInstruction::EQUAL); // LOL HAX!
m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right));
return dest;
}
}

int CodeGenerator::gen_additive_expression(AdditiveExpression * additive_expression) {
int right = gen_multiplicitive_expression(additive_expression->right);

if (additive_expression->left == NULL) {
// pass the right through
return right;
} else {
int left = gen_additive_expression(additive_expression->left);
int dest = next_available_register();
OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(additive_expression->_operator->type + OperatorInstruction::PLUS);
m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right));
return dest;
}
}

int CodeGenerator::gen_multiplicitive_expression(MultiplicativeExpression * multiplicative_expression) {
int right = gen_negatable_expression(multiplicative_expression->right);

if (multiplicative_expression->left == NULL) {
// pass the right through
return right;
} else {
int left = gen_multiplicitive_expression(multiplicative_expression->left);
int dest = next_available_register();
OperatorInstruction::Operator _operator = (OperatorInstruction::Operator)(multiplicative_expression->_operator->type + OperatorInstruction::TIMES);
m_instructions.push_back(new OperatorInstruction(dest, left, _operator, right));
return dest;
}
}

int CodeGenerator::gen_negatable_expression(NegatableExpression * negatable_expression) {
if (negatable_expression->type == NegatableExpression::PRIMARY) {
return gen_primary_expression(negatable_expression->primary_expression);
} else if (negatable_expression->type == NegatableExpression::SIGN) {
int source = gen_negatable_expression(negatable_expression->next);
int dest = next_available_register();
m_instructions.push_back(new UnaryInstruction(dest, UnaryInstruction::NEGATE, source));
return dest;
} else {
assert(false);
return -1;
}
}

int CodeGenerator::gen_primary_expression(PrimaryExpression * primary_expression) {
switch (primary_expression->type) {
case PrimaryExpression::VARIABLE:
return gen_variable_access(primary_expression->variable);
case PrimaryExpression::INTEGER:
{
int dest = next_available_register();
int constant = primary_expression->literal_integer->value;
m_instructions.push_back(new ImmediateInteger(dest, constant));
return dest;
}
case PrimaryExpression::BOOLEAN:
{
int dest = next_available_register();
bool constant = primary_expression->literal_boolean->value;
m_instructions.push_back(new ImmediateBoolean(dest, constant));
return dest;
}
case PrimaryExpression::PARENS:
return gen_expression(primary_expression->parens_expression);
case PrimaryExpression::NOT:
{
int dest = next_available_register();
int source = gen_primary_expression(primary_expression->not_expression);
m_instructions.push_back(new UnaryInstruction(dest, UnaryInstruction::NOT, source));
return dest;
}
/*
case PrimaryExpression::REAL:
case PrimaryExpression::STRING:
case PrimaryExpression::FUNCTION:
case PrimaryExpression::METHOD:
case PrimaryExpression::OBJECT_INSTANTIATION:
*/

default:
assert(false);
}
}

int CodeGenerator::gen_variable_access(VariableAccess * variable) {
switch (variable->type) {
case VariableAccess::IDENTIFIER:
return m_variable_numbers.get(variable->identifier->text);
/*
case VariableAccess::INDEXED_VARIABLE:
return check_indexed_variable(variable_access->indexed_variable);
case VariableAccess::ATTRIBUTE:
return check_attribute_designator(variable_access->attribute);
case VariableAccess::THIS:
return new TypeDenoter(m_symbol_table->item(m_class_id)->class_declaration->identifier);
*/
default:
assert(false);
}
}

void CodeGenerator::add_assignment(VariableAccess * variable, int value_register) {
void CodeGenerator::gen_assignment(VariableAccess * variable, int value_register) {
switch (variable->type) {
case VariableAccess::IDENTIFIER:
{
m_instructions.push_back(new CopyInstruction(m_variable_numbers.get(variable->identifier->text), value_register));
break;
}
/*
Expand Down
4 changes: 2 additions & 2 deletions insensitive_map.h
Expand Up @@ -16,8 +16,8 @@ class OrderedInsensitiveMap {

int count() { return m_vector.size(); }
bool has_key(std::string x) { return m_map.count(Utils::to_lower(x)) > 0; }
T item(std::string x) { return m_map[Utils::to_lower(x)]; }
T item(int i) { return m_vector[i]; }
T get(std::string x) { return m_map[Utils::to_lower(x)]; }
T get(int i) { return m_vector[i]; }
void put(std::string key, T value);
};

Expand Down

0 comments on commit eae318e

Please sign in to comment.