Skip to content

Commit

Permalink
added handling assignment operations, declare variables without initi…
Browse files Browse the repository at this point in the history
…alizer, variable reference store capability
  • Loading branch information
songmeric committed Mar 22, 2024
1 parent a03e528 commit 67c99d2
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 17 deletions.
2 changes: 2 additions & 0 deletions include/ast_binary_op.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class BinaryOp : public Node
};
void EmitRISC(std::ostream &stream, Context &context) const override;
void Print(std::ostream &stream) const override;

bool IsAssignment() const;
};

#endif
6 changes: 6 additions & 0 deletions include/ast_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,19 @@ class Context

ssize_t lastLabel{};

// Self clearing flag that tells variable
// reference that is is a store, not load
bool variableStore{};

// Stashed by ParameterDecl in its emit
std::vector<Variable> parameterDecls;

Variable *DeclareVariable(
std::string const &type,
std::string const &name);

void ReserveVariables(size_t more);

std::string declarationListType;

Variable *FindVariable(std::string const& name);
Expand Down
17 changes: 15 additions & 2 deletions include/ast_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,20 @@ class NodeList : public Node
virtual void Print(std::ostream &stream) const override;
};


enum Operator {
OP_ASSIGN,

// Basics
OP_ADD,
OP_ADDASSIGN,
OP_SUB,
OP_SUBASSIGN,
OP_MUL,
OP_MULASSIGN,
OP_DIV,
OP_DIVASSIGN,
OP_MOD,
OP_MODASSIGN,

// Function call
OP_CALL,
Expand All @@ -73,7 +79,9 @@ enum Operator {

// Shifts
OP_LEFT,
OP_LEFTASSIGN,
OP_RIGHT,
OP_RIGHTASSIGN,

// Comparisons
OP_CMPLT,
Expand All @@ -88,8 +96,11 @@ enum Operator {

// Bitwise
OP_BITAND,
OP_ANDASSIGN,
OP_BITOR,
OP_ORASSIGN,
OP_BITXOR,
OP_XORASSIGN,

// Logical
OP_LOGAND,
Expand All @@ -100,7 +111,9 @@ enum Operator {
OP_DEC,
OP_BITNOT,
OP_LOGNOT,
OP_ADDRESSOF
OP_ADDRESSOF,


};

#endif
80 changes: 73 additions & 7 deletions src/ast_binary_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@

void BinaryOp::EmitRISC(std::ostream &stream, Context &context) const
{
// Handle assignments in a way that reuses the
// code for non-assignment
bool assignment = IsAssignment();

Operator op = oper_;

if (assignment && oper_ != OP_ASSIGN) {
// The enum is set up so the X enum is equal
// to the integer value of X minus one
op = Operator((int)op - 1);
}

char const *insn = nullptr;
switch (oper_) {
switch (op) {
case OP_ASSIGN: insn = "sw"; break;
case OP_ADD: insn = "add"; break;
case OP_SUB: insn = "sub"; break;
case OP_MUL: insn = "mul"; break;
Expand All @@ -33,12 +46,32 @@ void BinaryOp::EmitRISC(std::ostream &stream, Context &context) const
default: assert(!"FIXME: Unhandled operator");
}

stream << "# Evaluating left side for " << insn << "\n";
lhs_->EmitRISC(stream, context);
// left hand side is expected to be in a1
// right hand side is expected to be in a0

if (assignment) {
if (op == OP_ASSIGN) {
// Evaluate value to be assigned
stream << "# Evaluating right side result for " << insn << "\n";
rhs_->EmitRISC(stream, context);

// Tell the VariableReference that it is a store
context.variableStore = true;
lhs_->EmitRISC(stream, context);
return;
}

// Load the variable as left hand side
lhs_->EmitRISC(stream, context);
} else {
stream << "# Evaluating left side for " << insn << "\n";
lhs_->EmitRISC(stream, context);
}

stream << "# Pushing left side result for " << insn << "\n";
stream << "addi sp,sp,-4\n";
stream << "sw a0,0(sp)\n";
stream << "# Eva;iatomg side result for " << insn << "\n";
stream << "# Evaluating right side result for " << insn << "\n";
rhs_->EmitRISC(stream, context);
stream << "# Popping saved left side result for " << insn << "\n";
stream << "lw a1,0(sp)\n";
Expand All @@ -52,7 +85,7 @@ void BinaryOp::EmitRISC(std::ostream &stream, Context &context) const
std::string True = context.NewLabel();
std::string False = context.NewLabel();

stream << insn << " a1,a0" << True << "\n";
stream << insn << " a1,a0," << True << "\n";
stream << "li a0,0\n";
stream << "j " << False << "\n";
stream << True <<":\n";
Expand Down Expand Up @@ -86,13 +119,27 @@ void BinaryOp::EmitRISC(std::ostream &stream, Context &context) const
else{ ////
stream << insn << " a0,a1,a0\n";
}

if (assignment) {
context.variableStore = true;
lhs_->EmitRISC(stream, context);
}
}

void BinaryOp::Print(std::ostream &stream) const
{
bool assignment = IsAssignment();

Operator op = oper_;

if (assignment && op != OP_ASSIGN) {
op = Operator((int)op - 1);
}

lhs_->Print(stream);
char const *optxt = nullptr;
switch (oper_) {
switch (op) {
case OP_ASSIGN: optxt = ""; break;
case OP_ADD: optxt = "+"; break;
case OP_SUB: optxt = "-"; break;
case OP_MUL: optxt = "*"; break;
Expand All @@ -114,6 +161,25 @@ void BinaryOp::Print(std::ostream &stream) const

default: assert(!"FIXME: Unhandled operator");
}
stream << optxt << "\n";
stream << optxt << (assignment ? "=" : "");
rhs_->Print(stream);
}

bool BinaryOp::IsAssignment() const
{
switch (oper_) {
case OP_ASSIGN:
case OP_MULASSIGN:
case OP_DIVASSIGN:
case OP_MODASSIGN:
case OP_ADDASSIGN:
case OP_SUBASSIGN:
case OP_LEFTASSIGN:
case OP_RIGHTASSIGN:
case OP_ANDASSIGN:
case OP_XORASSIGN:
case OP_ORASSIGN:
return true;
}
return false;
}
7 changes: 7 additions & 0 deletions src/ast_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ Variable *Context::DeclareVariable(
return &variable;
}

void Context::ReserveVariables(size_t more)
{
Scope &innermost = scopes.back();
innermost.locals.reserve(
innermost.locals.size() + more);
}

Variable *Context::FindVariable(std::string const &name)
{
for (size_t i = scopes.size(); i > 0; --i)
Expand Down
24 changes: 24 additions & 0 deletions src/ast_function_definition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,36 @@ void FunctionDefinition::EmitRISC(std::ostream &stream, Context &context) const

int parameter_nr = 0;

std::vector<Variable*> parameterInstances;

// Expand the vector capacity so the instances won't move
context.ReserveVariables(context.parameterDecls.size());

// Declare a variable for each parameter
for (auto &var : context.parameterDecls)
{
Variable *parameterVariable = context.DeclareVariable(
var.type, var.name);

parameterInstances.emplace_back(parameterVariable);
}

if (!parameterInstances.empty()) {
Variable *firstParameter = parameterInstances.front();
Variable *lastParameter = parameterInstances.back();
size_t end = lastParameter->offset +
context.SizeOfType(lastParameter->type);
size_t start = firstParameter->offset;
ssize_t alloc = end - start;

stream << "# Allocate space for the parameters\n";
stream << "addi sp,sp," << alloc << "\n";
}

for (auto &var : context.parameterDecls)
{
Variable *parameterVariable =
parameterInstances[parameter_nr];
// Generate code to copy the parameter register
// into the variable (in the stack frame)
stream << "# Store parameter " << parameter_nr <<
Expand Down
17 changes: 13 additions & 4 deletions src/ast_init_declarator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,23 @@ void InitDeclarator::EmitRISC(std::ostream &stream, Context &context) const
std::string name = ss.str();
Variable *v = context.DeclareVariable(context.declarationListType, name);

value_->EmitRISC(stream, context);
if(value_){
stream << "# Evaluating value for initialization of " << v->name << "\n";
value_->EmitRISC(stream, context);
}
stream << "# Allocating space for " << v->name << "\n";
stream << "addi sp,sp,-4\n";
stream << "sw a0," << v->offset << "(s0)\n";
if(value_){
stream << "# Initializing" << v->name << "\n";
stream << "sw a0," << v->offset << "(s0)\n";
}
}

void InitDeclarator::Print(std::ostream &stream) const
{
identifier_->Print(stream);
stream << " = ";
value_->Print(stream);
if(value_) {
stream << " = ";
value_->Print(stream);
}
}
3 changes: 3 additions & 0 deletions src/ast_parameter_decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ void ParameterDecl::EmitRISC(std::ostream &stream, Context &context) const
{
std::ostringstream ss;

// Get the type
declaration_specifiers_->Print(ss);
std::string type = ss.str();
ss.str("");


// Get the name
declarator_->EmitRISC(ss, context);
std::string name = ss.str();
ss.str("");
Expand Down
11 changes: 9 additions & 2 deletions src/ast_variable_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ void VariableReference::EmitRISC(std::ostream &stream, Context &context) const
variable_identifier_->EmitRISC(ss, context);
std::string name = ss.str();
Variable *v = context.FindVariable(name);
stream << "# Load variable \"" << v->name << "\"\n";
stream << "lw a0," << v->offset << "(s0)\n";

if (!context.variableStore) {
stream << "# Load from variable \"" << v->name << "\"\n";
stream << "lw a0," << v->offset << "(s0)\n";
} else {
stream << "# Store to variable \"" << v->name << "\"\n";
stream << "sw a0," << v->offset << "(s0)\n";
context.variableStore = false;
}
}

void VariableReference::Print(std::ostream &stream) const
Expand Down
38 changes: 36 additions & 2 deletions src/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,39 @@ conditional_expression

assignment_expression
: conditional_expression
| unary_expression assignment_operator assignment_expression
| unary_expression '=' assignment_expression {
$$ = new BinaryOp($1, OP_ASSIGN, $3);
}
| unary_expression MUL_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_MULASSIGN, $3);
}
| unary_expression DIV_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_DIVASSIGN, $3);
}
| unary_expression MOD_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_MODASSIGN, $3);
}
| unary_expression ADD_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_ADDASSIGN, $3);
}
| unary_expression SUB_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_SUBASSIGN, $3);
}
| unary_expression LEFT_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_LEFTASSIGN, $3);
}
| unary_expression RIGHT_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_RIGHTASSIGN, $3);
}
| unary_expression AND_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_ANDASSIGN, $3);
}
| unary_expression XOR_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_XORASSIGN, $3);
}
| unary_expression OR_ASSIGN assignment_expression {
$$ = new BinaryOp($1, OP_ORASSIGN, $3);
}
;

assignment_operator
Expand Down Expand Up @@ -307,7 +339,9 @@ init_declarator_list


init_declarator
: declarator
: declarator {
$$ = new InitDeclarator($1, nullptr);
}
| declarator '=' initializer {
$$ = new InitDeclarator($1, $3);
}
Expand Down

0 comments on commit 67c99d2

Please sign in to comment.