Example #1
0
void n_for::code_gen(status& stat, std::ostream& out)
{
	if (init != NULL) // initialising expression
		init->code_gen(stat, out);
	// start of loop: this is a lot like a while loop.
	stat.set_continue_label();
	out << stat.get_continue_label() << ":\n";
	stat.lock_register(out);
	stat.set_assign_expr();
	// check expression
	cond->code_gen(stat, out);
	stat.set_break_label();
	// exit loop if expression equals zero
	out << "\tbeqz\t$t" << stat.get_register() << "," << stat.get_break_label() << "\n";
	out << "\tnop\n";
	stat.unlock_register(out);
	stat.set_assign_expr();
	// loop statement
	left->code_gen(stat, out);
	if (right != NULL) // loop expression (something like i++)
		right->code_gen(stat, out);
	out << "\tb\t" << stat.get_continue_label() << "\n";
	out << "\tnop\n";
	out << stat.get_break_label() << ":\n";
	stat.reset_labels(true);
	return;
}
Example #2
0
void n_ifelse::code_gen(status& stat, std::ostream& out)
{
	stat.lock_register(out);
	stat.set_assign_expr();
	// check expression
	left->code_gen(stat, out);
	// branch over if statement, if the expression equals zero
	std::string else_label = stat.label_gen();
	out << "\tbeqz\t$t" << stat.get_register() << "," << else_label << "\n";
	out << "\tnop\n";
	stat.unlock_register(out);
	stat.set_assign_expr();
	// if statement
	right->code_gen(stat, out);
	if (else_node != NULL)
	{
		std::string end_label = stat.label_gen();
		// branch over else statement, if if branch was executed
		out << "\tb\t" << end_label << "\n";
		out << "\tnop\n";
		out << else_label << ":\n";
		// else statement
		else_node->code_gen(stat, out);
		out << end_label << ":\n";
	}
	else
	{
		out << else_label << ":\n";
	}	

	return;
}
Example #3
0
void n_case::code_gen(status& stat, std::ostream& out)
{
	if (left != NULL) // case:
	{
		stat.lock_register(out);
		stat.set_assign_expr();
		int op2 = stat.get_register();
		left->code_gen(stat, out);
		stat.unlock_register(out);
		stat.set_assign_expr();
		std::string next_case_label = stat.label_gen();
		// if the expressions are not equal, branch over statement
		out << "\tbne\t$t" << stat.get_register() << ",$t" << op2 << "," << next_case_label << "\n";
		out << "\tnop\n";
		// case body label
		if (stat.get_case_label() != "empty")
			out << stat.get_case_label() << ":\n";
		stat.set_case_label();
		if (right != NULL)
			right->code_gen(stat, out); // case body
		// fall through: need to jump to the next case body.
		out << "\tb\t" << stat.get_case_label() << "\n";
		out << "\tnop\n";
		out << next_case_label << ":\n";
	}
	else // default:
	{
		if (right != NULL)
			right->code_gen(stat, out);
	}
	return;	
}
Example #4
0
void n_init_decl::code_gen(status& stat, std::ostream& out)
{
	if (left != NULL)
	{
		stat.set_decl(false); // let the id node know that a variable is being declared
		left->code_gen(stat, out);
		stat.set_decl(false);
	}

	if (right != NULL) // if variable is initialised to value
	{
		if (stat.global_var())
		{
			std::stringstream amount;
			right->print(amount);
			out << "\t" << amount.str() << "\n";
		}
		else
		{
			stat.lock_register(out);
			stat.set_assign_expr();
			// evaluate assign expr
			right->code_gen(stat, out);
			stat.set_assign_var(); // let the id node know that a variable is being set to a value
			left->code_gen(stat, out);
			stat.set_assign_var();
			stat.unlock_register(out);
			stat.set_assign_expr();
		}
	}
	else if (stat.global_var())
		out << "\n";

	return;
}
Example #5
0
void n_jump_stat::code_gen(status& stat, std::ostream& out)
{
	if (type == "continue")
	{
		out << "\tb\t" << stat.get_continue_label() << "\n";
	}
	else if (type == "break")
	{
		out << "\tb\t" << stat.get_break_label() << "\n";
	}
	else if (type == "return")
	{
		if (left != NULL)
		{
			stat.lock_register(out);
			stat.set_assign_expr();
			left->code_gen(stat, out);
			out << "\tmove\t$v0,$t" << stat.get_register() << "\n";
			stat.set_assign_expr();
			stat.unlock_register(out);
			out << "\tb\tr" << stat.get_function_name() << "\n";
			out << "\tnop\n";
		}
	}
	else // goto
	{
		out << "\tj\tl_" << type << "\n";
	}

	return;
}
Example #6
0
void n_ternary::code_gen(status& stat, std::ostream& out)
{
	bool unlock = false;
	if (!stat.get_assign_expr())
	{
		stat.lock_register(out);
		stat.set_assign_expr();
		unlock = true;
	}

	cond->code_gen(stat, out); // the condition
	std::string zero_label = stat.label_gen();
	out << "\tbeqz\t$t" << stat.get_register() << "," << zero_label << "\n";
	out << "\tnop\n";
	left->code_gen(stat, out); // the first expression
	std::string end_label = stat.label_gen();
	out << "\tb\t" << end_label << "\n";
	out << zero_label << ":\n";
	right->code_gen(stat, out); // the second expression
	out << end_label << ":\n";

	if (unlock)
	{
		stat.unlock_register(out);
		stat.set_assign_expr();
	}
	return;
}
Example #7
0
void n_arg_list::code_gen(status& stat, std::ostream& out)
{
	if (left != NULL)
		left->code_gen(stat, out);

	int arg_reg = stat.lock_arg_register(out);
	stat.lock_register(out);
	right->code_gen(stat, out);
	if (arg_reg < 4)
		out << "\tmove\t$a" << arg_reg << ",$t" << stat.get_register() << "\n";
	else
		out << "\tsw\t$t" << stat.get_register() << ",($sp)\n";
	stat.unlock_register(out);
	return;
}
Example #8
0
void n_switch::code_gen(status& stat, std::ostream& out)
{
	stat.lock_register(out);
	stat.set_assign_expr();
	// check expression
	left->code_gen(stat, out);
	stat.set_assign_expr();
	stat.set_break_label();
	// list of cases
	right->code_gen(stat, out);
	stat.unlock_register(out);
	out << stat.get_break_label() << ":\n";
	out << stat.get_case_label() << ":\n";
	stat.reset_labels(false);
	return;
}
Example #9
0
void n_dowhile::code_gen(status& stat, std::ostream& out)
{
	// label signifying the start of the loop
	stat.set_continue_label();
	out << stat.get_continue_label() << ":\n";
	// loop statement
	stat.set_break_label();
	left->code_gen(stat, out);
	stat.lock_register(out);
	stat.set_assign_expr();
	// check expression
	right->code_gen(stat, out);
	// do another loop if expression is non zero
	out << "\tbnez\t$t" << stat.get_register() << "," << stat.get_continue_label() << "\n";
	out << "\tnop\n";
	out << stat.get_break_label() << ":\n";
	stat.unlock_register(out);
	stat.set_assign_expr();
	stat.reset_labels(true);
	return;
}
Example #10
0
void n_while::code_gen(status& stat, std::ostream& out)
{
	// label signifying the start of the loop
	stat.set_continue_label();
	out << stat.get_continue_label() << ":\n";
	stat.lock_register(out);
	stat.set_assign_expr();
	// check expression
	left->code_gen(stat, out);
	stat.set_break_label();
	// exit loop if expression equals zero
	out << "\tbeqz\t$t" << stat.get_register() << "," << stat.get_break_label() << "\n";
	out << "\tnop\n";
	stat.unlock_register(out);
	stat.set_assign_expr();
	// loop statement
	right->code_gen(stat, out);
	// return to top of loop
	out << "\tb\t" << stat.get_continue_label() << "\n";
	out << "\tnop\n";
	out << stat.get_break_label() << ":\n";
	stat.reset_labels(true);
	return;
}
Example #11
0
void n_expression::code_gen(status& stat, std::ostream& out)
{
	// left OP right : result_reg = t0 OP t1
	bool unlock = false;
	if (!stat.get_assign_expr())
	{
		stat.lock_register(out);
		stat.set_assign_expr();
		unlock = true;
	}
	if (opstr == "+")
	{
		if (left != NULL)
		{
			left->code_gen(stat, out);
			stat.lock_register(out);
			right->code_gen(stat, out);
			int op2 = stat.get_register();
			int op2f = stat.get_f_register();
			stat.unlock_register(out);
			if (stat.is_float())
				out << "\tadd.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n";
			else
				out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
		}
		else
		{
			right->code_gen(stat, out);
		}
	}
	else if (opstr == "-")
	{
		if (left != NULL)
		{
			left->code_gen(stat, out);
			stat.lock_register(out);
			right->code_gen(stat, out);
			int op2 = stat.get_register();
			int op2f = stat.get_f_register();
			stat.unlock_register(out);
			if (stat.is_float())
				out << "\tsub.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n";
			else
				out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
		}
		else
		{
			stat.lock_register(out);
			right->code_gen(stat, out);
			int op2 = stat.get_register();
			stat.unlock_register(out);
			out << "\tneg\t$t" << stat.get_register() << ",$t" << op2 << "\n";
		}
	}
	else if (opstr == "*")
	{
		if (left != NULL) // if operation is left MULT right
		{
			left->code_gen(stat, out);
			stat.lock_register(out);
			right->code_gen(stat, out);
			int op2 = stat.get_register();
			int op2f = stat.get_f_register();
			stat.unlock_register(out);
			if (stat.is_float())
				out << "\tmul.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n";
			else
				out << "\tmul\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
		}
		else // if operation is dereferencing
		{
			if (stat.get_assign_var())
				stat.lock_register(out);
			int op2 = stat.get_register();
			stat.set_dereference();
			right->code_gen(stat, out);
			stat.set_dereference();
			if (stat.get_assign_var()) // if variable needs to be saved
				stat.unlock_register(out);
			out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n";
		}
	}
	else if (opstr == "/")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		int op2f = stat.get_f_register();
		stat.unlock_register(out);
		if (stat.is_float())
			out << "\tdiv.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n";
		else
			out << "\tdiv\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "%")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\trem\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "&")
	{
		if (left != NULL) // if operation is left AND right
		{
			left->code_gen(stat, out);
			stat.lock_register(out);
			right->code_gen(stat, out);
			int op2 = stat.get_register();
			stat.unlock_register(out);
			out << "\tand\t$t" << stat.get_register();
			out << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
		}
		else // if operation is referencing
		{
			stat.set_reference();
			right->code_gen(stat, out);
			stat.set_reference();
		}
	}
	else if (opstr == "|")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tor\t$t" << stat.get_register();
		out << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "^")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\txor\t$t" << stat.get_register();
		out << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "<<")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tsllv\t$t" << stat.get_register();
		out << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}	
	else if (opstr == ">>")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tsrav\t$t" << stat.get_register();
		out << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "==")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tseq\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "!=")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tsne\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "<")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tslt\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == ">")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tslt\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n";
	}
	else if (opstr == "<=")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tsge\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n";
	}
	else if (opstr == ">=")
	{
		left->code_gen(stat, out);
		stat.lock_register(out);
		right->code_gen(stat, out);
		int op2 = stat.get_register();
		stat.unlock_register(out);
		out << "\tsge\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n";
	}
	else if (opstr == "++")
	{
		if (left != NULL) // postfix
		{
			left->code_gen(stat, out);
			int op1 = stat.get_register();
			stat.lock_register(out);
			out << "\tadd\t$t" << stat.get_register() << ",$t" << op1 << ",1\n";
			stat.set_assign_var();
			left->code_gen(stat, out);
			stat.set_assign_var();
			stat.unlock_register(out);
		}
		else if (right != NULL) // prefix
		{
			right->code_gen(stat, out);
			out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n";
			stat.set_assign_var();
			right->code_gen(stat, out);
			stat.set_assign_var();
		}
	}
	else if (opstr == "--")
	{
		if (left != NULL) // postfix
		{
			left->code_gen(stat, out);
			int op1 = stat.get_register();
			stat.lock_register(out);
			out << "\tsub\t$t" << stat.get_register() << ",$t" << op1 << ",1\n";
			stat.set_assign_var();
			left->code_gen(stat, out);
			stat.set_assign_var();
			stat.unlock_register(out);
		}
		else if (right != NULL) // prefix
		{
			right->code_gen(stat, out);
			out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n";
			stat.set_assign_var();
			right->code_gen(stat, out);
			stat.set_assign_var();
		}
	}
	else if (opstr == "[]")
	{
		if (stat.get_assign_var())
			stat.lock_register(out);
		// get offset of first element
		stat.lock_register(out);
		int op2 = stat.get_register();
		stat.set_reference();
		left->code_gen(stat, out);
		stat.set_reference();
		stat.unlock_register(out);
		// evaluate operation
		right->code_gen(stat, out);
		// shift the operation to get number of bytes for array offset
		out << "\tsll\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",2\n";
		// subtract array offset from first element offset
		out << "\tsubu\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n";
		// store or load the variable
		op2 = stat.get_register();
		if (stat.get_assign_var())
			stat.unlock_register(out);
		out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n";
	}
	else if (opstr == "!")
	{
		left->code_gen(stat, out);
		out << "\tseq\t$" << stat.get_register() << ",$zero,$t" << stat.get_register();
	}
	else if (opstr == "~")
	{
		left->code_gen(stat, out);
		out << "\tnot\t$" << stat.get_register() << ",$t" << stat.get_register() << "\n";
	}
	else if (opstr == "=")
	{
		right->code_gen(stat, out);
		stat.set_assign_var();
		left->code_gen(stat, out);
		stat.set_assign_var();
	}

	if (unlock)
	{
		stat.unlock_register(out);
		stat.set_assign_expr();
	}
	return;
}