Skip to content

Commit

Permalink
phase_3_c7: functions added
Browse files Browse the repository at this point in the history
  • Loading branch information
mroghani committed Jul 20, 2021
1 parent a1dd9a0 commit c8804b5
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 51 deletions.
4 changes: 2 additions & 2 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ function structure:
name_label:
pre_ (save in stack ra, store local base, allocate space for variables)

kobs sher

post_ (restore registers (s1 ra), deallocate, return)

Expand All @@ -24,4 +23,5 @@ g() {
}
w() {

}
}

29 changes: 29 additions & 0 deletions driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ driver::driver () {
global_offset = 0;
function_offset = 0;
push_scope();

in_loop = 0;
in_switch = 0;
}

std::string driver::get_label () {
Expand Down Expand Up @@ -71,6 +74,32 @@ Var driver::get_variable(std::string id, yy::location & loc) {
throw yy::parser::syntax_error(loc, "undefined identifier " + id);
}

Function driver::get_function(std::string id, yy::location & loc) {
auto it = Functions.find(id);
if (it != Functions.end()) {
return it->second;
}
throw yy::parser::syntax_error(loc, "undefined identifier " + id);
}

void driver::make_func(std::string id, int type) {
curr_function = id;
Functions[curr_function] = Function();
Functions[curr_function].id = id;
Functions[curr_function].type = (Function::Type)(type - 1);

}

void driver::add_args_to_func(std::vector<Var> &vars, yy::location & loc) {
if (vars.size() > 4) {
throw yy::parser::syntax_error(loc, "Too many arguments");
}
Functions[curr_function].number_of_arguments = vars.size();


}


bool driver::has_variable_in_scope(std::string id, int scope) {
// auto it = variables[scope].find(id);
// if (it == variables[scope].end()) {
Expand Down
12 changes: 12 additions & 0 deletions driver.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ public:
void push_scope();
void pop_scope();

int in_loop;
int in_switch;

// ====> FUNCTIONS

std::map<std::string, Function> Functions;

Function get_function(std::string id, yy::location & loc);
void make_func(std::string id, int type);
void add_args_to_func(std::vector<Var> &vars, yy::location & loc);

std::string curr_function;

// ====> VARIABLES
int global_offset;
Expand Down
85 changes: 77 additions & 8 deletions helpers/helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ std::string sw(std::string register_name, std::string destination)
// Loads value of an address (destination) into a register.
std::string lw(int register_number, std::string source)
{
return "lw $" + std::to_string(register_number) + ", " + source + "\n";
return "lw $" + std::to_string(register_number) + ", " + (source[0] == '$' ? "" : "$") + source + "\n";
}
// Loads value of an address (destination) in another address or register.
std::string lw(std::string destination, std::string source)
{
return "lw " + destination + ", " + source + "\n";
return std::string("lw ") + (destination[0] == '$' ? "" : "$") + destination + ", " + (source[0] == '$' ? "" : "$") + source + "\n";
}
// Copies the contents of source (arg #2) to destination (arg #1).
std::string move(std::string destination, std::string source)
Expand Down Expand Up @@ -75,12 +75,12 @@ std::string fp(int offset = 0)
return "$fp";
}
// Returns "?($reg)" or "$reg"
std::string reg_offset(std::string reg, int offset = 0)
std::string reg_offset(std::string reg, int offset)
{
if (offset)
return std::to_string(4 * offset) + "($reg)";
return std::to_string(4 * offset) + "($" + reg + ")";
else
return "$reg";
return "$" + reg;
}
// Adds two registers and stores the result in the destination register.
std::string addregisters(std::string destination, std::string source1, std::string source2)
Expand Down Expand Up @@ -130,15 +130,15 @@ Node helpers::load_mutable(driver &drv, std::string id, yy::location &loc, Node
if (ind == nullptr)
{ // variable
// text << stackmore(1) << lw("t0", reg_offset(base_reg, var.offset)) << sw("t0", sp(0));
text << addimmediate("t0", base_reg, 4 * var.offset)
text << addimmediate("t0", base_reg, -4 * var.offset)
<< stackmore(1)
<< sw("t0", sp(0));
}
else
{
// array
text << ind->code.text // index is on top of stack.
<< addimmediate("t0", base_reg, 4 * var.offset)
<< addimmediate("t0", base_reg, -4 * var.offset)
<< lw("t1", sp(0))
<< addregisters("t0", "t0", "t1")
<< sw("t0", sp(0));
Expand All @@ -149,7 +149,7 @@ Node helpers::load_mutable(driver &drv, std::string id, yy::location &loc, Node
return node;
}

Node load_mutable_value(Node &mu) // DONE
Node helpers::load_mutable_value(Node &mu) // DONE
{
Node node;

Expand All @@ -158,6 +158,10 @@ Node load_mutable_value(Node &mu) // DONE
text << lw("t0", sp(0))
<< lw("t0", "t0") // At first, "t0" holds the address, after this instruction it holds the contents of the address.
<< sw("t0", sp(0));

node.code.text = text.str();

return node;
}

Node helpers::sum_exp(Node &left, int op, Node &right) // DONE
Expand Down Expand Up @@ -341,5 +345,70 @@ Node helpers::merge_nodes(Node &left, Node &right)
{
Node node;
node.code.text = left.code.text + right.code.text;
return node;
}


Node helpers::return_stmt(driver &drv, yy::location &loc, Node * exp) {
Node node;

std::ostringstream text;


if (exp == nullptr) { // if returns nothing
if (drv.Functions[drv.curr_function].type != Function::Type::VOID) {
throw yy::parser::syntax_error(loc, "return type is not compatible.");
}
} else { // if returns int or char
if (drv.Functions[drv.curr_function].type == Function::Type::VOID) {
throw yy::parser::syntax_error(loc, "return type is not compatible.");
}

text << exp->code.text;

text << lw("v0", "sp");

}

text << lw("s0", reg_offset("s0", 1))
<< lw("ra", reg_offset("s0", 2))
<< lw("sp", "s0")
<< stackless(2)
<< "JR $ra\n";

node.code.text = text.str();

return node;
}


Node helpers::create_function(Function func, Node & stmts) {
Node node;

std::ostringstream text;

// Store important registers
text << func.id << ":\n"
<< stackmore(3)
<< sw("ra", sp(2))
<< sw("s0", sp(1))
<< lw("s0", sp(0));

if (func.number_of_arguments > 0)
text << stackmore(func.number_of_arguments);

// Load args
for (int i = 0; i < func.number_of_arguments; i++) {
std::string rname = "a0";
rname[1] = '0' + i;
text << sw(rname, reg_offset("s0", -i));
}


text << stmts.code.text;


node.code.text = text.str();

return node;
}
6 changes: 5 additions & 1 deletion helpers/helpers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ namespace helpers
Node binary_exp(Node &left, std::string op, Node &right);
Node assign(Node &mu, Node &exp);
Node merge_nodes(Node &left, Node &right);

Node create_function(Function func, Node & stmts);

Node return_stmt(driver &drv, yy::location &loc, Node * exp);
};

std::string stackmore(int amount);
Expand All @@ -31,7 +35,7 @@ std::string move(std::string destination, std::string source);
std::string ret();
std::string sp(int offset);
std::string fp(int offset);
std::string reg_offset(std::string reg, int offset = 0);
std::string reg_offset(std::string reg, int offset);

std::string addregisters(std::string destination, std::string source1, std::string source2);
std::string subregisters(std::string destination, std::string source1, std::string source2);
Expand Down
21 changes: 1 addition & 20 deletions inp
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
int s.

int ss.

char fc (char c, int s) <
int x.
int y = 3.
x= y.
>

char cs = 'a'.


int f(int a) <
if (a == 0) <return 0.>
return f(a - 1) + a.
>




int main() <
return 0.
>


Expand Down
19 changes: 14 additions & 5 deletions inp.out
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
ADDI $t2, $sp, 4
MOVE $t3, $t2
ADDI $t2, $sp, 0
LW $t0, ($t2)
SW $t0, ($t3)
main:
addiu $sp, $sp, -12
sw $ra, 8($sp)
sw $s0, 4($sp)
lw $s0, $sp
addiu $sp, $sp, -4
li $t0, 0
sw $t0, $sp
lw $v0, $sp
lw $s0, $4($s0)
lw $ra, $8($s0)
lw $sp, $s0
addiu $sp, $sp, 8
JR $ra
42 changes: 27 additions & 15 deletions parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class driver;
%nterm <Node> immutable mutable exp call unaryExp factor;
%nterm <Node> simpleExp andExp unaryRelExp relExp sumExp mulExp;
%nterm <Node> programm declLists decl funcDecl expStmt;
%nterm <Node> returnStmt;
%nterm <Node> stmt stmtList;

// %nterm <Node> cases;

// grammar
Expand All @@ -118,7 +121,7 @@ declLists: %empty { $$ = Node(); }
;

decl: varDecl "." { $$ = Node(); }
| funcDecl { $$ = Node(); /* TODO */}
| funcDecl { $$ = $1; }
;

varDecl: varType ID { drv.make_variable($2, @2, $1, 1, 0); }
Expand All @@ -131,10 +134,17 @@ varType: INT { $$ = 1; }
| CHAR { $$ = 2; }
;

funcDecl: varType ID { drv.push_scope(); }
"(" params ")" "<" stmtList ">" { /** make function **/ drv.pop_scope(); }
| VOID ID { drv.push_scope(); } "(" params ")" "<" stmtList ">" { drv.pop_scope(); }
| INT MAIN { drv.push_scope(); } "(" <std::vector<Var>>{$$ = std::vector<Var>();} ")" "<" stmtList ">" { drv.pop_scope(); }
funcDecl: varType ID { drv.push_scope(); drv.make_func($2, $1); }
"(" params ")" { drv.add_args_to_func($5, @5); }
"<" stmtList ">" { $$ = helpers::create_function(drv.Functions[$2], $9); drv.pop_scope(); }

| VOID ID { drv.push_scope(); drv.make_func($2, 3); }
"(" params ")" { drv.add_args_to_func($5, @5); }
"<" stmtList ">" { $$ = helpers::create_function(drv.Functions[$2], $9); drv.pop_scope(); }

| INT MAIN { drv.push_scope(); drv.make_func("main", 1); }
"(" <std::vector<Var>>{$$ = std::vector<Var>();} ")"
"<" stmtList ">" { $$ = helpers::create_function(drv.Functions["main"], $8); drv.pop_scope(); }
;

params: paramList { $$ = $1; }
Expand All @@ -148,19 +158,21 @@ paramList: paramList "," paramItem { $1.push_back($3); $$ = $1; }
paramItem: varType ID { $$ = drv.make_variable($2, @2, $1, 1, 0); }
;

stmtList: varDecl "." stmtList
| stmt stmtList
| %empty
stmtList: varDecl "." stmtList { $$ = $3; }
| stmt stmtList { $$ = helpers::merge_nodes($1, $2); }
| %empty { $$ = Node(); }
;

stmt: expStmt
| selectStmt
stmt: expStmt { $$ = $1; }
| returnStmt { $$ = $1; }
;

/* | selectStmt
| iterStmt
| breakStmt
| continueStmt
| returnStmt
;

*/

selectStmt: IF "(" exp ")" "<" stmtList ">"
| SWITCH "(" factor ")" "<" cases ">"
;
Expand Down Expand Up @@ -189,8 +201,8 @@ breakStmt: BREAK "."
continueStmt: CONTINUE "."
;

returnStmt: RETURN "."
| RETURN simpleExp "."
returnStmt: RETURN "." { $$ = helpers::return_stmt(drv, @1, nullptr); }
| RETURN simpleExp "." { $$ = helpers::return_stmt(drv, @1, &$2); }
;


Expand Down
1 change: 1 addition & 0 deletions types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "types/Node.hh"
#include "types/Var.hh"
#include "types/Function.hh"
#include "types/Code.hh"
#include "types/Constant.hh"

Expand Down
21 changes: 21 additions & 0 deletions types/Function.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ifndef Function_HH
# define Function_HH

#include <string>

struct Function
{
std::string id;

int space_needed;
int number_of_arguments;

enum Type
{
INT,
CHAR,
VOID
} type;
};

#endif

0 comments on commit c8804b5

Please sign in to comment.