Exemplo n.º 1
0
void gen_ASSIGNMENT_STATEMENT ( node_t *root, int scopedepth )
{
	 tracePrint ( "Starting ASSIGNMENT_STATEMENT\n");

	//Generating the code for the expression part of the assignment. The result is
	//placed on the top of the stack
	root->children[1]->generate(root->children[1], scopedepth);

    // Left hand side may be a class field, which should be handled in this assignment
	if(root->children[0]->expression_type.index == CLASS_FIELD_E){
        root->children[0]->children[0]->generate(root->children[0]->children[0], scopedepth);
        instruction_add(POP, r2, NULL, 0, 0);
        char stack_offset[10];
        sprintf(stack_offset, "#%d", root->children[0]->entry->stack_offset);
        instruction_add(MOVE, r1, STRDUP(stack_offset), 0, 0);
        instruction_add3(ADD, r0, r1, r2);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(STORE, r1, r0, 0, 0);
	}
	// or a variable, handled in previous assignment
	else{
        instruction_add(POP, r0, NULL, 0, 0);

        instruction_add(STORE, r0, fp, 0, root->children[0]->entry->stack_offset);
	}

	tracePrint ( "End ASSIGNMENT_STATEMENT\n");
}
Exemplo n.º 2
0
void gen_EXPRESSION ( node_t *root, int scopedepth )
{
    /*
     * Expressions:
     * Handle any nested expressions first, then deal with the
     * top of the stack according to the kind of expression
     * (single variables/integers handled in separate switch/cases)
     */
    tracePrint ( "Starting EXPRESSION of type %s\n", (char*) root->expression_type.text);

    switch(root->expression_type.index){

        case FUNC_CALL_E:
            ge(root,scopedepth);
            break;

        /* Add cases for other expressions here */
        case ADD_E: case SUB_E: case MUL_E: case DIV_E: case LEQUAL_E: case GEQUAL_E:
        case NEQUAL_E: case EQUAL_E: case LESS_E: case GREATER_E: case AND_E: case OR_E:
            ;
            node_t *left_child = root->children[0];
            node_t *right_child = root->children[1];
            right_child->generate(right_child, scopedepth);
            left_child->generate(left_child, scopedepth);

            instruction_add(POP, r1, NULL, 0, 0);
            instruction_add(POP, r2, NULL, 0, 0);
            switch(root->expression_type.index) {
                case ADD_E:
                case OR_E:
                    instruction_add3(ADD, r0, r1, r2);
                    break;
                case SUB_E:
                    instruction_add3(SUB, r0, r1, r2);
                    break;
                case MUL_E:
                case AND_E:
                    instruction_add3(MUL, r0, r1, r2);
                    break;
                case DIV_E:
                    instruction_add3(DIV, r0, r1, r2);
                    break;
                case EQUAL_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVEQ, r0, "#1", 0, 0);
                    break;
                case GEQUAL_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVGE, r0, "#1", 0, 0);
                    break;
                case NEQUAL_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVNE, r0, "#1", 0, 0);
                    break;
                case LEQUAL_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVLE, r0, "#1", 0, 0);
                    break;
                case LESS_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVLT, r0, "#1", 0, 0);
                    break;
                case GREATER_E:
                    instruction_add(CMP, r1, r2, 0, 0);
                    instruction_add(MOVE, r0, "#0", 0, 0);
                    instruction_add(MOVGT, r0, "#1", 0, 0);
                    break;
            }
            instruction_add(PUSH, r0, NULL, 0, 0);
            break;
    }

    tracePrint ( "Ending EXPRESSION of type %s\n", (char*) root->expression_type.text);
}
Exemplo n.º 3
0
void gen_EXPRESSION ( node_t *root, int scopedepth )
{
	/*
	 * Expressions:
	 * Handle any nested expressions first, then deal with the
	 * top of the stack according to the kind of expression
	 * (single variables/integers handled in separate switch/cases)
	 */
	tracePrint ( "Starting EXPRESSION of type %s\n", (char*) root->expression_type.text);

	switch(root->expression_type.index) {

	case FUNC_CALL_E:
        {
            if (root->children[1] != NULL) {
                // Push arguments on stack
                gen_default(root->children[1], scopedepth);
            }
            char *func_label = root->function_entry->label;
            instruction_add(CALL, STRDUP(func_label), NULL, 0, 0);
            // There is an issue where, if the parent node does not use the returned result,
            // this will pollute the stack, and offset any new local variables declared.
            // I see no easy way to fix this, and it also doesn't seem to be covered by 
            // the tests.
            instruction_add(PUSH, r0, NULL, 0, 0);
        }
		break;
    case METH_CALL_E:
        {
            if (root->children[2] != NULL) {
                // Push arguments on stack
                gen_default(root->children[2], scopedepth);
            }
            tracePrint( "Pushing THIS\n" );
            root->children[0]->generate(root->children[0], scopedepth);
            char *class_label = root->children[0]->data_type.class_name;
            char *func_label = root->function_entry->label;
            int len = strlen(class_label) + strlen(func_label);
            char *meth_label = malloc(sizeof(char) * (len+1));
            meth_label[0] = 0;
            strcat(meth_label, class_label);
            strcat(meth_label, "_");
            strcat(meth_label, func_label);
            instruction_add(CALL, STRDUP(meth_label), NULL, 0, 0);
            // There is an issue where, if the parent node does not use the returned result,
            // this will pollute the stack, and offset any new local variables declared.
            // I see no easy way to fix this, and it also doesn't seem to be covered by 
            // the tests.
            instruction_add(PUSH, r0, NULL, 0, 0);
        }
        break;
    case NEW_E:
        {
            class_symbol_t *class_entry = root->children[0]->class_entry;
            char class_size[10];
            int32_t class_entry_size = (int32_t)class_entry->size * 8;
            sprintf(class_size, "#%d", class_entry_size);
            instruction_add(MOVE32, STRDUP(class_size), r0, 0, 0);
            instruction_add(PUSH, r0, NULL, 0, 0);
            instruction_add(CALL, STRDUP("malloc"), NULL, 0, 0);
            instruction_add(PUSH, r0, NULL, 0, 0);
        }
        break;
    case CLASS_FIELD_E:
        {
            root->children[0]->generate(root->children[0], scopedepth);
            char stack_offset[10];
            sprintf(stack_offset, "#%d", root->entry->stack_offset);

            instruction_add(POP, r1, NULL, 0, 0);
            instruction_add(MOVE, r2, STRDUP(stack_offset), 0, 0);
            instruction_add3(ADD, r3, r1, r2);
            instruction_add(LOAD, r0, r3, 0, 0);
            instruction_add(PUSH, r0, NULL, 0, 0);
        }
        break;
    case THIS_E:
        {
            instruction_add(LOAD, r1, fp, 0, 8);
            instruction_add(PUSH, r1, NULL, 0, 0);
        }
        break;
    default:
        gen_default(root, scopedepth);
    }

    switch (root->expression_type.index) {

    case ADD_E:
    case OR_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add3(ADD, r0, r1, r2);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case SUB_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add3(SUB, r0, r1, r2);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case MUL_E:
    case AND_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add3(MUL, r0, r1, r2);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case DIV_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add3(DIV, r0, r1, r2);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case UMINUS_E:
        instruction_add(MOVE, r1, STRDUP("#0"), 0, 0);
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add3(SUB, r0, r1, r2);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case EQUAL_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVEQ, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case NEQUAL_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#1"), 0, 0);
        instruction_add(MOVEQ, r0, STRDUP("#0"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case GEQUAL_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVGE, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case LEQUAL_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVLE, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case LESS_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVLT, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case GREATER_E:
        instruction_add(POP, r2, NULL, 0, 0);
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, r2, 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVGT, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;
    case NOT_E:
        instruction_add(POP, r1, NULL, 0, 0);
        instruction_add(CMP, r1, STRDUP("#0"), 0, 0);
        instruction_add(MOVE, r0, STRDUP("#0"), 0, 0);
        instruction_add(MOVEQ, r0, STRDUP("#1"), 0, 0);
        instruction_add(PUSH, r0, NULL, 0, 0);
        break;

	}

	tracePrint ( "Ending EXPRESSION of type %s\n", (char*) root->expression_type.text);
}
Exemplo n.º 4
0
void gen_EXPRESSION ( node_t *root, int scopedepth )
{
	/*
	 * Expressions:
	 * Handle any nested expressions first, then deal with the
	 * top of the stack according to the kind of expression
	 * (single variables/integers handled in separate switch/cases)
	 */
	tracePrint ( "Starting EXPRESSION of type %s\n", (char*) root->expression_type.text);

	int size;
	char size_string[100];
	switch(root->expression_type.index){

		case FUNC_CALL_E:
			ge(root,scopedepth);
			break;

			/* Add cases for other expressions here */
		case UMINUS_E:
			// Generate the child
			root->children[0]->generate(root->children[0], scopedepth);
			// Fetching the operand from stack
			instruction_add(POP, r0, NULL, 0, 0);
			instruction_add(MOVE, r1, "#-1", 0, 0);
			instruction_add3(MUL, r0, r0, r1);
			instruction_add(PUSH, r0, NULL, 0, 0);
			break;

		case METH_CALL_E:
			// Caller saves registers on stack.
			// Assuming that there might be something in registers r1-r3
			// Assuming that r0 are used to handle different inputs and outputs, including function result.
			instruction_add(PUSH, r3, NULL, 0,0);
			instruction_add(PUSH, r2, NULL, 0,0);
			instruction_add(PUSH, r1, NULL, 0,0);
		
			// Caller pushes parameters on stack.
			// Must find number of parameters, and push each value to stack
			// When parameters, second child-node is a variable-list instead of NULL. Children of that node contain the parameters values
			int i;
			if (root->children[2]!=NULL){
			
				for (i=0; i<root->children[2]->n_children; i++){
					// Load parameter number i into register r0 by using the generate-method for that node (usually variable or constant)
					// r0 will automatically be pushed by either gen_CONSTANT or gen_VARIABLE
					root->children[2]->children[i]->generate(root->children[2]->children[i], scopedepth);
				
				}
			}
			
			// IMPORTANT: Difference from func_call is also that the object (value is address on heap) is pushed as final argument
			// Loading object as variable into r0 and pushing r0 in stack, by generate
			root->children[0]->generate(root->children[0], scopedepth);
			
			//Performing method call from correct class:
			//function_symbol_t* entry = root->children[1]->function_entry;
			symbol_t* p1 = root->children[0]->entry;
			data_type_t p2 = p1->type;
			int len2 = strlen(p2.class_name);
			
			char *temp2 = (char*) malloc(sizeof(char) * (len2 + 3));
			temp2[0] = 0;
			//temp3 = test.type->class_name;
			//temp3= root->children[0]->entry.type->class_name;
			strcat(temp2, p2.class_name);
			strcat(temp2, "_");
			strcat(temp2, root->children[1]->label);

			instruction_add(CALL, STRDUP(temp2), NULL, 0, 0 );
			free(temp2);
			
			// Poping THIS as argument from the stack
			instruction_add(POP, "r8", NULL, 0,0); 
			// Callee jumps back to caller, and pops return address. Caller removes parameters, restores registers, uses result.
			// Using r0 for result storing from the function
			if (root->children[2]!=NULL){
				for (i=0; i<root->children[2]->n_children; i++){
					// Poping parameters from stack, by loading into r8, that is otherwise never used. This includes the objects heap parameter
					instruction_add(POP, "r8", NULL, 0,0);
				}
			}
			
			// Restoring original registers
			instruction_add(POP, r1, NULL, 0,0);
			instruction_add(POP, r2, NULL, 0,0);
			instruction_add(POP, r3, NULL, 0,0);
		
			// NOTE: Have to hack in order to make sure printing works when including functions straight in print statement
			// by setting data_type
			root->data_type = root->function_entry->return_type;
			if (root->data_type.base_type!=VOID_TYPE){
				// Adding result in r0 to stack as return result
				instruction_add(PUSH, r0, NULL, 0,0);
			}
			
			
			break;

			// Binary expressions:
		case ADD_E: case SUB_E: case MUL_E: case DIV_E: case AND_E: case OR_E:
		case EQUAL_E: case NEQUAL_E: case LEQUAL_E: case GEQUAL_E: case LESS_E: case GREATER_E:

			// The two operands are in the two child-nodes. They must be generated.
			root->children[0]->generate(root->children[0], scopedepth);
			root->children[1]->generate(root->children[1], scopedepth);
			// Fetching the operands from stack
			instruction_add(POP, r2, NULL, 0,0);
			instruction_add(POP, r1, NULL, 0,0);
			// Calculating, and pushing to stack

      // Now the current operation itself:
			switch(root->expression_type.index){

				// Arithmetic and logical expressions:
				case ADD_E: case OR_E:
					instruction_add3(ADD, r0, r1, r2);
					break;

				case SUB_E:
					instruction_add3(SUB, r0, r1, r2);
					break;

				case MUL_E: case AND_E:
					instruction_add3(MUL, r0, r1, r2);
					break;

				case DIV_E:
					instruction_add3(DIV, r0, r1, r2); 
					break;

					// Comparison expressions:

				case GREATER_E:
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVGT, r0, "#1", 0,0);
					break;

				case LESS_E: 
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVLT, r0, "#1", 0,0);
					break;

				case EQUAL_E:
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVEQ, r0, "#1", 0,0);
					break;

				case NEQUAL_E:
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVNE, r0, "#1", 0,0);
					break;

				case GEQUAL_E:
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVGE, r0, "#1", 0,0); 
					break;

				case LEQUAL_E:
					instruction_add(MOVE, r0, "#0", 0,0);
					instruction_add(CMP, r1, r2, 0,0);
					instruction_add(MOVLE, r0, "#1", 0,0);
					break;

			}

			// Pushing to stack:
			instruction_add(PUSH, r0, NULL, 0, 0);

			break;

		case CLASS_FIELD_E:
			// Fetching address value from child 1, pushing to top of stack:
			root->children[0]->generate(root->children[0], scopedepth);
			// Now poping from stack into r0:
			instruction_add(POP, r1, NULL, 0,0);
			// Now loading from heap, based on address from child 1 and offset from child 2:
			instruction_add(LOAD, r0, r1, 0, root->children[1]->entry->stack_offset);
			// Pushing class field access result to stac:
			instruction_add(PUSH, r0, NULL, 0,0);


			break;

		case THIS_E: //TODO: Double check that this works, double check that the value at class position in stack indeed is the address, or if it needs to be fetched using node field
			instruction_add(LOAD, r0, fp, 0, 8);
			instruction_add(PUSH, r0, NULL, 0, 0);
			break;

		case NEW_E:
			size = root->children[0]->class_entry->size;
			snprintf(size_string, 100, "#%d", size); //Max 99 digits

			instruction_add(MOVE, r0, STRDUP(size_string), 0, 0);
			instruction_add(PUSH, r0, NULL, 0, 0); //Pushing constant to stack, in case of print statement

			instruction_add(CALL, STRDUP("malloc"), NULL, 0, 0);
			instruction_add(POP, r1, NULL, 0, 0);
			//instruction_add(STORE, r0, sp, 0, 8);
			instruction_add(PUSH, r0, NULL, 0, 0);
			break;
	}

	tracePrint ( "Ending EXPRESSION of type %s\n", (char*) root->expression_type.text);
}