示例#1
0
void gen_PROGRAM ( node_t *root, int scopedepth)
{
    /* Output the data segment */
    if( outputStage == 12 )
        strings_output ( stderr );
    instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

    tracePrint("Starting PROGRAM\n");

    gen_default(root, scopedepth);//RECUR();

    TEXT_DEBUG_FUNC_ARM();
    TEXT_HEAD_ARM();

    gp(root,scopedepth);


    tracePrint("End PROGRAM\n");

    TEXT_TAIL_ARM();

    if( outputStage == 12 )
        instructions_print ( stderr );
    instructions_finalize ();
}
示例#2
0
void gen_PROGRAM ( node_t *root, int scopedepth)
{
	/* Output the data segment */
	if( outputStage == 12 )
		strings_output ( stderr );
	instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

	tracePrint("Starting PROGRAM\n");

	gen_default(root, scopedepth);//RECUR();

	TEXT_DEBUG_FUNC_ARM();
	TEXT_HEAD_ARM();
	
	/* Call the first defined function */

	int last_child = root->n_children - 1;

	if (root->children[last_child] != NULL) {
		char *func_label = root->children[last_child]->children[0]->function_entry->label;
		instruction_add( CALL, STRDUP(func_label), NULL, 0, 0);
    }
	

	tracePrint("End PROGRAM\n");

	TEXT_TAIL_ARM();
	
	if( outputStage == 12 )
		instructions_print ( stderr );
	instructions_finalize ();
}
示例#3
0
void generate ( FILE *stream, node_t *root )
{
	int length = 0;
    int elegant_solution;
    if ( root == NULL )
        return;

    switch ( root->type.index )
    {
        case PROGRAM:
            /* Output the data segment */
            strings_output ( stream );
            instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

            RECUR();
            TEXT_HEAD();

            instruction_add(CALL, root->children[0]->children[0]->children[0]->entry->label, NULL, 0, 0);

            TEXT_TAIL();

            instructions_print ( stream );
            instructions_finalize ();
			
            break;

        case FUNCTION:
            /*
             * Function definitions:
             * Set up/take down activation record for the function, return value
             */

            //Entering new scope, 'depth' is the depth of the current scope
            depth++;

          
            int len = strlen(root->children[0]->entry->label);
			
			//Generating the string needed for the label instruction
			func_name = (char*) malloc(sizeof(char)*len);
			strncpy(func_name, root->children[0]->entry->label, len);
			
            char *temp = (char*) malloc(sizeof(char) * (len + 3));
            temp[0] = '_';
            for(int c = 0; c < len; c++){
                temp[c+1] = root->children[0]->entry->label[c];
            }
            temp[len + 1] = ':';
            temp[len + 2] = 0;

            //Generate the label for the function, and the code to update the base ptr
            instruction_add(STRING, temp, NULL, 0, 0);
            instruction_add(PUSH, ebp, NULL, 0,0);
            instruction_add(MOVE, esp, ebp, 0,0);

            //Generating code for the functions body
            //The body is the last child, the other children are the name of the function
            //the arguments etc
            generate(stream, root->children[root->n_children - 1]);

            //Generating code to restore the base ptr, and to return
            instruction_add(LEAVE, NULL, NULL, 0,0);
            instruction_add(RET, NULL, NULL, 0,0);
			
			free(func_name);
			
			
            //Leaving the scope, decreasing depth
            depth--;
            break;

        case BLOCK:
            /*
             * Blocks:
             * Set up/take down activation record, no return value
             */

            //Entering new scope
            depth++;

            //Setting up the new activation record
            instruction_add(PUSH, ebp, NULL, 0,0);
            instruction_add(MOVE, esp, ebp, 0,0);

            //Generating code for the body of the block
            RECUR();

            //Restoring the old activation record
            instruction_add(LEAVE, NULL, NULL, 0,0);

            //Leaving scope
            depth--;
            break;

        case DECLARATION:
            /*
             * Declarations:
             * Add space on local stack
             */

            //The declarations first child is a VARIABLE_LIST, the number of children
            //of the VARIABLE_LIST is the number of variables declared. A 0 is pushed on
            //the stack for each
            for(uint32_t c = 0; c < root->children[0]->n_children; c++){
                instruction_add(PUSH, STRDUP("$0"), NULL, 0,0);
            }
            break;

        case PRINT_LIST:
            /*
             * Print lists:
             * Emit the list of print items, followed by newline (0x0A)
             */

            //Generate code for all the PRINT_ITEMs
            RECUR();

            //Print a newline, push the newline, call 'putchar', and pop the argument
            //(overwriting the value returned from putchar...)
            instruction_add(PUSH, STRDUP("$0x0A"), NULL, 0, 0);
            instruction_add(SYSCALL, STRDUP("putchar"), NULL, 0,0);
            instruction_add(POP, eax, NULL, 0,0);
            break;

        case PRINT_ITEM:
            /*
             * Items in print lists:
             * Determine what kind of value (string literal or expression)
             * and set up a suitable call to printf
             */

            //Checking type of value, (of the child of the PRINT_ITEM,
            //which is what is going to be printed
            if(root->children[0]->type.index == TEXT){
                //String, need to push '$.STRINGx' where x is the number of the string
                //The number can be found in the nodes data field, and must be transformed
                //to a string, and concatenated with the '$.STRING' part
                int32_t t = *((int32_t*)root->children[0]->data);
                char int_part[3]; //can have more than 999 strings...
                sprintf(int_part, "%d", t);
                char str_part[9] = "$.STRING";
                strcat(str_part, int_part);

                //Generating the instructions, pushing the argument of printf
                //(the string), calling printf, and removing the argument from
                //the stack (overwriting the returnvalue from printf)
                instruction_add(PUSH, STRDUP(str_part), NULL, 0,0);
                instruction_add(SYSCALL, STRDUP("printf"), NULL, 0,0);
                instruction_add(POP, eax,NULL,0,0);
            }
            else{
                //If the PRINT_ITEMs child isn't a string, it's an expression
                //The expression is evaluated, and its result, which is an integer
                //is printed

                //Evaluating the expression, the result is placed at the top of the stack
                RECUR();

                //Pushing the .INTEGER constant, which will be the second argument to printf,
                //and cause the first argument, which is the result of the expression, and is
                //allready on the stack to be printed as an integer
                instruction_add(PUSH, STRDUP("$.INTEGER"), NULL, 0,0);
                instruction_add(SYSCALL, STRDUP("printf"), NULL,0,0);

                //Poping both the arguments to printf
                instruction_add(POP, eax, NULL, 0,0);
                instruction_add(POP, eax, NULL, 0,0);
            }


            break;

        case EXPRESSION:
            /*
             * 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)
             */


            switch (root->n_children){
                case 1:
                    //One child, and some data, this is the -exp expression
                    if(root->data != NULL){
                        //Computing the exp part of -exp, the result is placed on the top of the stack
                        RECUR();

                        //Negating the exp by computing 0 - exp
                        instruction_add(POP, ebx, NULL, 0,0);
                        instruction_add(MOVE, STRDUP("$0"), eax, 0,0);
                        instruction_add(SUB, ebx, eax, 0,0);

                        //Pushing the result on the stack
                        instruction_add(PUSH, eax, NULL, 0,0);
                    }
                    else{
                        //One child, and no data, this is variables
                        //They are handeled later
                        RECUR();
                    }
                    break;

                case 2:
                    //Two children and no data, a function (call, not defenition)
                    if(*(char*)(root->data) == 'F'){
                        //Generate the code for the second child, the arguments, this will place them on the stack
                        generate(stream, root->children[1]);

                        //The call instruction
                        instruction_add(CALL, STRDUP(root->children[0]->entry->label), NULL, 0,0);

                        //Removing the arguments, changing the stack pointer directly, rather than poping
                        //since the arguments aren't needed
                        if(root->children[1] != NULL){
                          for(int c = 0; c < root->children[1]->n_children; c++){
                            instruction_add(ADD, STRDUP("$4"), esp, 0,0);
                          }
                        }

                        //Pushing the returnvalue from the function on the stack
                        instruction_add(PUSH, eax, NULL, 0, 0);
                        break;
                    }


                    //Two children and data, this is the arithmetic expressions
                    //The two children are evaluated first, which places their values
                    //at the top of the stack. More precisely, the result of the second
                    //subexpression will be placed at the top of the stack, the result of
                    //the first on the position below it
                    RECUR();
                    if(strlen((char*)root->data) == 1){
                        switch (*(char*)root->data){

                            // Addition and subtraction is handeled equally
                            // The arguments are placed in the eax and ebx registers
                            // they are added/subtracted, and the result is pushed on the stack
                            case '+':
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(ADD, ebx, eax, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '-':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(SUB, ebx, eax, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;

                                //With multiplication/division it's also necessary to sign extend the
                                //arguments, using the CLTD instruction, the MUL/DIV instructions only need
                                //one argument, the other one is eax
                            case '*':
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(CLTD, NULL, NULL, 0,0);
                                instruction_add(MUL, ebx, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '/':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CLTD, NULL, NULL, 0,0);
                                instruction_add(DIV, ebx, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '>':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETG, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '<':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETL, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                        }

                    }
                    else{
                        switch (*(char*)root->data){
                            case '>':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETGE, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '<':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETLE, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '=':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETE, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                            case '!':
                                instruction_add(POP, ebx, NULL, 0,0);
                                instruction_add(POP, eax, NULL, 0,0);
                                instruction_add(CMP, ebx, eax, 0,0);
                                instruction_add(SETNE, al, NULL, 0,0);
                                instruction_add(CBW, NULL, NULL, 0,0);
                                instruction_add(CWDE, NULL, NULL, 0,0);
                                instruction_add(PUSH, eax, NULL, 0,0);
                                break;
                        }
                    }
            }


            break;

        case VARIABLE:
            /*
             * Occurrences of variables: (declarations have their own case)
             * - Find the variable's stack offset
             * - If var is not local, unwind the stack to its correct base
             */

            //Finding the scope of the variable. If the difference is 0, it is
            //defined in this scope, if it is 1, the previous one and so on
            depth_difference = depth - root->entry->depth;

            //The offset of the variable is relative to its ebp. The current ebp is saved
            //on the stack, and the needed one retrived
            instruction_add(PUSH, ebp, NULL, 0,0);

            //The ebp points to the previous ebp, which points to the ebp before it and so on.
            //The ideal instruction to use would be 'movl (%ebp) %ebp', but that can't be done
            //with this framework. Rather than changing the framework, the following hack is used:
            //
            //The constant 4 and the contents of ebp is added and placed in eax, then the
            //the value pointed to by eax with an offset of -4, that is -4(%eax), is placed in ebp
            //since eax is ebp + 4, -4(%eax) is really (%ebp)
            for(int c = 0; c < depth_difference; c++){
                instruction_add(MOVE, STRDUP("$4"), eax, 0,0);
                instruction_add(ADD, ebp, eax, 0,0);
                instruction_add(MOVE, eax, ebp, -4,0);
            }

            //The offset of the vaiable (from its ebp)
            int32_t offset = root->entry->stack_offset;

            //The value of the variable is placed in eax, the right ebp is used, because of 
            //the system above
            instruction_add(MOVE, ebp, eax, offset, 0);

            //The current ebp is restored
            instruction_add(POP, ebp, NULL, 0,0);

            //The value of the variable is placed on the stack (since it's a kind of expression)
            instruction_add(PUSH, eax, NULL, 0,0);

            break;

        case INTEGER:
            /*
             * Integers: constants which can just be put on stack
             */

            //We can't have a label followed by a declaration, so this is needed...
            elegant_solution = 0;

            //The value of the integer is fetched and converted to a string
            char temp1[10]; //ints are 4 bytes, so this is enough
            int32_t t = *((int32_t*)root->data);
            sprintf(temp1, "%d", t);
            char temp2[11] = "$";
            strcat(temp2, temp1);

            //The value is pushed on the stack
            instruction_add(PUSH, STRDUP(temp2), NULL, 0,0);
            break;

        case ASSIGNMENT_STATEMENT:
            /*
             * Assignments:
             * Right hand side is an expression, find left hand side on stack
             * (unwinding if necessary)
             */

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

            //Using same scheme as above
            depth_difference = depth - root->children[0]->entry->depth;

            instruction_add(PUSH, ebp, NULL, 0,0);
            for(int c = 0; c < depth_difference; c++){
                instruction_add(MOVE, STRDUP("$4"), eax, 0,0);
                instruction_add(ADD, ebp, eax, 0,0);
                instruction_add(MOVE, eax, ebp, -4,0);
            }

            int32_t offset_2 = root->children[0]->entry->stack_offset;

            //Putting the current ebp in ebx
            instruction_add(POP, ebx, NULL, 0,0);

            //Putting the result of the expression in eax
            instruction_add(POP, eax, NULL, 0,0);

            //Putting the result of the expression in the variable (ebp is the ebp of the variable)
            instruction_add(MOVE, eax, ebp, 0, offset_2);

            //Restoring the current ebp
            instruction_add(MOVE, ebx, ebp, 0, 0);
            break;

        case RETURN_STATEMENT:
            /*
             * Return statements:
             * Evaluate the expression and put it in EAX
             */
            RECUR();
            instruction_add(POP, eax, NULL, 0,0);

            for ( int u=0; u<depth-1; u++ ){
                instruction_add ( LEAVE, NULL, NULL, 0, 0 );
            }
            instruction_add ( RET, eax, NULL, 0, 0 );

            break;
            
        case WHILE_STATEMENT: {
				//Increment the number of while loops. 
				n_while++;
				
				//Create the start label for the while-loop.
				len = strlen(func_name);
				char start_label[100];
				snprintf(start_label, 100, "%s%s", func_name, "_while_");
				snprintf(start_label, 100, "%s%d", start_label, n_while);
				//Start label with added "_" for the jump.
				char jump_start_label[100];
				snprintf(jump_start_label, 100, "_%s", start_label);
				
				//End label
				char end_label[100];
				snprintf(end_label, 100, "%s%s", start_label, "_end");
				//End label with added "_" for the jump.
				char jump_end_label[100];
				snprintf(jump_end_label, 100, "_%s", end_label);
				
				instruction_add(LABEL, STRDUP(start_label), NULL, 0, 0);
				
				//Evaluate the expression
				generate(stream, root->children[0]);
				//Pop the result to eax
				instruction_add(POP, eax, NULL, 0, 0);
				//Compare and jump to end_label if eax equals zero.
				instruction_add(CMP, STRDUP("$0"), eax, 0, 0);
				instruction_add(JUMPEQ, STRDUP(jump_end_label), NULL, 0, 0);
				//Generate the statement instructions.
				generate(stream, root->children[1]);
				//Jump to start label
				instruction_add(JUMP, STRDUP(jump_start_label), NULL, 0, 0);
				//Add end label. 
				instruction_add(LABEL, STRDUP(end_label), NULL, 0, 0);
			}
            break;

        case FOR_STATEMENT: {
				//Increment the number of the for loop.
				n_for++;
				/** LABELS **/
				//Create the start label for the for loop. 
				len = strlen(func_name);
				char start_label[100];
				snprintf(start_label, 100, "%s%s", func_name, "_for_");
				snprintf(start_label, 100, "%s%d", STRDUP(start_label), n_for);
				//Create the jump label with "_" in front.
				char jump_start_label[100];
				snprintf(jump_start_label, 100, "_%s", start_label);
				//Create the end label if the condition is false.
				char end_label[100];
				snprintf(end_label, 100, "%s%s", start_label, "_end");
				//Create the jump end label, adding "_" in fron of end label.
				char jump_end_label[100];
				snprintf(jump_end_label, 100, "_%s", end_label);
				
				/** SET COUNTER TO START VALUE **/
				generate(stream, root->children[0]);
				
				
				/** START LABEL **/
				instruction_add(LABEL, STRDUP(start_label), NULL, 0, 0);
				
				//The nodes that represent the counter and the end value expression, respectively. 
				node_t *counter = root->children[0]->children[0];
				node_t *endValue = root->children[1];
				/** Test if counter >= endValue. If so, jump to end **/

				generate(stream, counter);
				generate(stream, endValue);
				instruction_add(POP, ebx, NULL, 0, 0);
				instruction_add(POP, eax, NULL, 0, 0);
				
				instruction_add(CMP, ebx, eax, 0,0);
                instruction_add(SETGE, al, NULL, 0,0);
                instruction_add(CBW, NULL, NULL, 0,0);
                instruction_add(CWDE, NULL, NULL, 0,0);
				instruction_add(CMP, STRDUP("$1"), eax, 0, 0);
				instruction_add(JUMPEQ, STRDUP(jump_end_label), NULL, 0, 0);
				//Loop-body
				generate(stream, root->children[2]);
				
				/**Increment counter **/
				depth_difference = depth - counter->entry->depth;

				instruction_add(PUSH, ebp, NULL, 0,0);
				for(int c = 0; c < depth_difference; c++){
					instruction_add(MOVE, STRDUP("$4"), eax, 0,0);
					instruction_add(ADD, ebp, eax, 0,0);
					instruction_add(MOVE, eax, ebp, -4,0);
				}

				int32_t offset_2 = counter->entry->stack_offset;

				//Putting the current ebp in ebx
				instruction_add(POP, ebx, NULL, 0,0);

				//Putting the result of the expression in the variable (ebp is the ebp of the variable)
				instruction_add(ADD, STRDUP("$1"), ebp, 0, offset_2);

				//Restoring the current ebp
				instruction_add(MOVE, ebx, ebp, 0, 0);
				
				/** Jump to begining **/
				instruction_add(JUMP, STRDUP(jump_start_label), NULL, 0, 0);
				
				//Add end label.
				instruction_add(LABEL, STRDUP(end_label), NULL, 0, 0);
				
				
				
			}
            break;
            
        case IF_STATEMENT: { 
				n_if = n_if+1;
        		len = strlen(func_name);
				//Label for the end of the if statement. 
				char end_label[100];
				snprintf(end_label, 100, "%s%s%d", func_name, "_endOfIf_", n_if);
				
				//Need to add "_" when jumping to label.
				char jump_end_label[100];
				snprintf(jump_end_label, 100, "_%s", end_label);
				
				if (root->n_children == 2) {
					//Evaluate expression and pop result to eax and check if zero.
					generate(stream, root->children[0]);
					instruction_add(POP, eax, NULL, 0, 0);
					instruction_add(CMP, STRDUP("$0"), eax, 0, 0);
					//Jump to end if expression is zero.
					instruction_add(JUMPEQ, STRDUP(jump_end_label), NULL, 0, 0);
					//Generate the statement
					generate(stream, root->children[1]);
					//Add end label.
					
				}
				else {
					//Else label
					char else_label[100];
					snprintf(else_label, 100, "%s%s%d", func_name, "_else_", n_if);
					//Evaluate expression and pop it to eax. Jmp if zero.
					generate(stream, root->children[0]);
					instruction_add(POP, eax, NULL, 0, 0);
					instruction_add(CMP, STRDUP("$0"), eax, 0, 0);
					//Need to add "_" before the label when jumping
					char jump_else_label[100];
					snprintf(jump_else_label, 100, "_%s", else_label);
					instruction_add(JUMPEQ, STRDUP(jump_else_label), NULL, 0, 0);
					//Execute the "true statement".
					generate(stream, root->children[1]);
					//Jump to end of the if-statement.
					instruction_add(JUMP, STRDUP(jump_end_label), NULL, 0, 0);
					//Add the else label.
					instruction_add(LABEL, STRDUP(else_label), NULL, 0, 0);
					//Execute the else statement.
					generate(stream, root->children[2]);
					
				}
				instruction_add(LABEL, STRDUP(end_label), NULL, 0, 0);
			}
            break;

        case NULL_STATEMENT:
        		RECUR();
            break;

        default:
            /* Everything else can just continue through the tree */
            RECUR();
            break;
    }
}
示例#4
0
void generate ( FILE *stream, node_t *root )
{
    //Check if we've reached a return statement earlier. If we have we shall not procede.
    if (reachedReturnStatement == 1) return;
    int var_offset;
    int var_depth;
    int diff;
    const int BUFFER_LENGTH = 100;
    char buffer[BUFFER_LENGTH];
    int elegant_solution;
    if ( root == NULL )
        return;
    switch ( root->type.index )
    {

    case PROGRAM:
        /* Output the data segment */
        strings_output ( stream );
        instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

        RECUR();
        TEXT_HEAD();
        /* TODO: Insert a call to the first defined function here */
        instruction_add(CALL, STRDUP((char*)root->children[0]->children[0]->children[0]->data), NULL, 0, 0);

        TEXT_TAIL();
        instructions_print ( stream );
        instructions_finalize ();
        break;

    case FUNCTION:
        /*
         * Function definitions:
         * Set up/take down activation record for the function, return value
         */
        instruction_add(LABEL, STRDUP((char*)root->children[0]->entry->label), NULL, 0, 0);
        instruction_add(PUSH, ebp, NULL, 0, 0);
        instruction_add(MOVE, esp, ebp, 0, 0);
        depth++;
        generate(stream, root->children[2]);
        depth--;
        //We're done with this function, have to reset the reachedReturnStatement value to 0.
        reachedReturnStatement = 0;
        instruction_add(LEAVE, NULL, NULL, 0, 0);
        instruction_add(RET, NULL, NULL, 0, 0);
        break;

    case BLOCK:
        /*
         * Blocks:
         * Set up/take down activation record, no return value
         */
        instruction_add(PUSH, ebp, NULL, 0, 0);
        instruction_add(MOVE, esp, ebp, 0, 0);
        depth++;
        RECUR();
        depth--;
        instruction_add(MOVE, ebp, esp, 0, 0);
        instruction_add(POP, ebp, NULL, 0, 0);

        break;

    case DECLARATION:
        /*
         * Declarations:
         * Add space on local stack
         */
        //Moves the stack pointer down 4 bytes for each variable that is to be declared.
        snprintf(buffer, BUFFER_LENGTH, "$%d", (root->children[0]->n_children)*4);
        instruction_add(SUB, STRDUP(buffer), esp, 0, 0);

        break;

    case PRINT_LIST:
        /*
         * Print lists:
         * Emit the list of print items, followed by newline (0x0A)
         */
        //Continues down the tree to the print_items.
        RECUR();

        //Add new line.
        instruction_add(PUSH, STRDUP("$0x0A"), NULL, 0, 0);
        instruction_add(SYSCALL, STRDUP("putchar"), NULL, 0, 0);
        instruction_add(ADD, STRDUP("$4"), esp, 0, 0);
        break;

    case PRINT_ITEM:
        /*
         * Items in print lists:
         * Determine what kind of value (string literal or expression)
         * and set up a suitable call to printf
         */
        //Set up a suitable call for strings to printf.
        if (root->children[0]->type.index == TEXT) {
            snprintf(buffer, BUFFER_LENGTH, "$.STRING%d", *((int*)root->children[0]->data));
            instruction_add(PUSH, STRDUP(buffer), NULL, 0, 0);
            instruction_add(SYSCALL, STRDUP("printf"), NULL, 0, 0);
            instruction_add(ADD, STRDUP("$4"), esp, 0, 0);

        }
        //Set up a suitable call for integers to printf.
        else {
            generate(stream, root->children[0]);
            instruction_add(PUSH, STRDUP("$.INTEGER"), NULL, 0, 0);
            instruction_add(SYSCALL, STRDUP("printf"), NULL, 0, 0);
            instruction_add(ADD, STRDUP("$8"), esp, 0, 0);
        }
        break;

    case EXPRESSION:
        /*
         * 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)
         */

        evaluate_expression(stream, root);

        break;

    case VARIABLE:
        /*
         * Occurrences of variables: (declarations have their own case)
         * - Find the variable's stack offset
         * - If var is not local, unwind the stack to its correct base
         */
        //Variables depth and offset.
        var_offset = root->entry->stack_offset;
        var_depth = root->entry->depth;
        diff = depth - var_depth;

        //Uses ebx to find the correct frame.
        instruction_add(MOVE, ebp, ebx, 0, 0);
        for (int i = 0; i < diff; i++) {
            instruction_add(MOVE, STRDUP("(%ebx)"), ebx, 0, 0);
        }
        //Pushes the value of the variable on the stack.
        instruction_add(PUSH, ebx, NULL, var_offset, 0);
        break;

    case INTEGER:
        /*
         * Integers: constants which can just be put on stack
         */
        //Creates the correct string for the integer, and pushes it on the stack.
        snprintf(buffer, BUFFER_LENGTH, "$%d", *((int*)root->data));
        instruction_add(PUSH, STRDUP(buffer), NULL, 0, 0);
        break;

    case ASSIGNMENT_STATEMENT:
        /*
         * Assignments:
         * Right hand side is an expression, find left hand side on stack
         * (unwinding if necessary)
         */
        //Evaluates the expression on the right side. Its value will be on top of stack afterwards, so pop it.
        generate(stream, root->children[1]);
        instruction_add(POP, eax, NULL, 0, 0);


        var_offset = root->children[0]->entry->stack_offset;
        var_depth = root->children[0]->entry->depth;
        diff = depth - var_depth;

        //Puts the adress to the next frame in ebx, and unwind until we find the variable's location.
        instruction_add(MOVE, ebp, ebx, 0, 0);
        for (int i = 0; i < diff; i++) {
            instruction_add(MOVE, STRDUP("(%ebx)"), ebx, 0, 0);
        }
        //Put the expression value in the location of the variable.
        instruction_add(MOVE, eax, ebx, 0, var_offset);
        break;

    case RETURN_STATEMENT:
        /*
         * Return statements:
         * Evaluate the expression and put it in EAX
         */
        //Evalute the expression. Its value will be on stack afterwards, so pop it.
        RECUR();
        instruction_add(POP, eax, NULL, 0, 0);
        //Signal that we have reached a return statement. No more instructions should be added for this
        //procedure.
        reachedReturnStatement = 1;
        break;

    default:
        /* Everything else can just continue through the tree */
        RECUR();
        break;
    }
}
示例#5
0
void generate ( FILE *stream, node_t *root )
{
    char *char_buffer;
    int elegant_solution;
    if ( root == NULL )
        return;

    switch ( root->type.index )
    {
        case PROGRAM:
            /* Output the data segment */
            strings_output ( stream );
            instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

            RECUR();
            TEXT_HEAD();

            /*
             * Calls the name of the first function, not pretty, but it works.
             */
            instruction_add(CALL, STRDUP(root->children[0]->children[0]->children[0]->data), NULL, 0, 0);

            TEXT_TAIL();

            instructions_print ( stream );
            instructions_finalize ();
            break;

        case FUNCTION:
            /*
             * Function definitions:
             * Set up/take down activation record for the function, return value
             */

            depth++;

            instruction_add(LABEL, STRDUP(root->children[0]->data), NULL, 0, 0);
            /* Callee saves old EBP on stack */
            instruction_add(PUSH, ebp, NULL, 0, 0);
            /* Callee sets new EBP to top of stack. */
            instruction_add(MOVE, esp, ebp, 0, 0);

            /* Callee executes function (overwriting registers if necessary.) */
            generate(stream, root->children[2]);

            /*
             * Callee sets ESP to its EBP
             * Callee sets restores old EBP
             * Callee jumps back to caller, and pops return address.
             *
             * This part wouldn't be needed if every function had to RETURN
             * something, but from what I can see in the grammar, it's
             * legal to not return something. Functions that don't return
             * something may cause strange things to happen depending on the
             * implementation.
             */
            instruction_add(LEAVE, NULL, NULL, 0, 0);
            instruction_add(RET, NULL, NULL, 0, 0);

            depth--;

            break;

        case BLOCK:
            /*
             * Blocks:
             * Set up/take down activation record, no return value
             */

            depth++;

            /* Like a function, only that we don't have any return address. */
            instruction_add(PUSH, ebp, NULL, 0, 0);
            instruction_add(MOVE, esp, ebp, 0, 0);

            RECUR();

            /* Mom always told me to clean up after myself. */
            instruction_add(LEAVE, NULL, NULL, 0, 0);

            depth--;

            break;

        case DECLARATION:
            /*
             * Declarations:
             * Add space on local stack
             */

            /*
             * n_children is positive, so 12 bytes is enough to store $, an
             * int (10 digits) as well as the 0-byte.
             */
            char_buffer = malloc(sizeof(*char_buffer) * 12);
            sprintf(char_buffer, "$%d", 4 * root->children[0]->n_children);

            /*
             * Clever little thing, growing the stack with 4 bytes for each
             * local variable that is to be added, no pushing or initialising
             * needed. Not very maintainable, though.
             */
            instruction_add(SUB, STRDUP(char_buffer), esp, 0, 0);

            break;

        case PRINT_LIST:
            /*
             * Print lists:
             * Emit the list of print items, followed by newline (0x0A)
             */

            /* Print all the PRINT_ITEMs */
            RECUR();

            /*
             * Put a newline out there after the contents have been printed in
             * order to follow the spec.
             */
            instruction_add(PUSH, STRDUP("$0x0a"), NULL, 0, 0);
            instruction_add(SYSCALL, STRDUP("putchar"), NULL, 0, 0);

            break;

        case PRINT_ITEM:
            /*
             * Items in print lists:
             * Determine what kind of value (string literal or expression)
             * and set up a suitable call to printf
             */

            if (root->children[0]->type.index == TEXT) {
                /* Text-elemtens, just print the appropriate string. */
                char_buffer = malloc(sizeof(*char_buffer) * 19);
                sprintf(char_buffer, "$.STRING%d", *(int*)root->children[0]->data);
                instruction_add(PUSH, char_buffer, NULL, 0, 0);
            } else {
                /* A variable, add it's value to the stack. */
                RECUR();
                instruction_add(PUSH, STRDUP("$.INTEGER"), NULL, 0, 0);
            }

            /* printf whatever we pushed to the stack. */
            instruction_add(SYSCALL, STRDUP("printf"), NULL, 0, 0);

            break;

        case EXPRESSION:
            /*
             * 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)
             */

            /*
             * Handle functions first as I find them a special case even though
             * the comments tell me to RECUR first.
             */
            if (root->data != NULL && *(char*)root->data == 'F') {
                /* Caller pushes parameters on stack. */
                generate(stream, root->children[1]);
                /*
                 * Caller pushes return address on stack.
                 * Caller jumps to called function address.
                 */
                instruction_add(CALL, root->children[0]->data, NULL, 0, 0);

                /*
                 * Remove arguments from stack. The same as adding local
                 * variables, really, except that we shrink the stack instead.
                 * See DECLARATION-case for further description of the
                 * procedure.
                 */
                if (root->children[1] != NULL) {
                    char_buffer = malloc(sizeof(*char_buffer) * 12);
                    sprintf(char_buffer, "$%d", 4 * root->children[1]->n_children);
                    instruction_add(ADD, char_buffer, esp, 0, 0);
                }

                /* Push the return value to the stack. */
                instruction_add(PUSH, eax, NULL, 0, 0);
            } else {
                RECUR();

                if (root->n_children == 1 && root->data != NULL && *(char*) root->data == '-') {
                    /* Unary minus, simple operation. */
                    instruction_add(POP, ebx, NULL, 0, 0);
                    /*
                     * The recitation didn't mention neg. I still chose to use
                     * it as it was already in generator.c, and I think it's
                     * more pretty than multiplying the number with -1, or
                     * whatever other way there is to do this.
                     */
                    instruction_add(NEG, ebx, NULL, 0, 0);
                    instruction_add(PUSH, ebx, NULL, 0, 0);
                } else if (root->n_children == 2) {
                    /*
                     * Binary operation! ebx contains the rightmost operand,
                     * eax the leftmost.
                     */
                    instruction_add(POP, ebx, NULL, 0, 0);
                    instruction_add(POP, eax, NULL, 0, 0);

                    switch(*(char*)root->data) {
                        case '+':
                            instruction_add(ADD, ebx, eax, 0, 0);
                            break;
                        case '-':
                            instruction_add(SUB, ebx, eax, 0, 0);
                            break;
                        case '*':
                            instruction_add(MUL, ebx, NULL, 0, 0);
                            break;
                        case '/':
                            instruction_add(CLTD, NULL, NULL, 0, 0);
                            instruction_add(DIV, ebx, NULL, 0, 0);
                            break;
                        case '<':
                            instruction_add(CMP, ebx, eax, 0, 0);

                            /* '=' as opposed to '\0' */
                            if (*((char*) root->data + 1) == '=') {
                                /* <= */
                                instruction_add(SETLE, al, NULL, 0, 0);
                            } else {
                                instruction_add(SETL, al, NULL, 0, 0);
                            }

                            instruction_add(CBW, NULL, NULL, 0, 0);
                            instruction_add(CWDE, NULL, NULL, 0, 0);
                            break;
                        case '>':
                            instruction_add(CMP, ebx, eax, 0, 0);

                            if (*((char*) root->data + 1) != '\0' && *((char*) root->data + 1) == '=') {
                                /* >= */
                                instruction_add(SETGE, al, NULL, 0, 0);
                            } else {
                                instruction_add(SETG, al, NULL, 0, 0);
                            }

                            instruction_add(CBW, NULL, NULL, 0, 0);
                            instruction_add(CWDE, NULL, NULL, 0, 0);
                            break;
                        case '=':
                            /* == */
                            instruction_add(CMP, ebx, eax, 0, 0);
                            instruction_add(SETE, al, NULL, 0, 0);
                            instruction_add(CBW, NULL, NULL, 0, 0);
                            instruction_add(CWDE, NULL, NULL, 0, 0);
                            break;
                        case '!':
                            /* != */
                            instruction_add(CMP, ebx, eax, 0, 0);
                            instruction_add(SETNE, al, NULL, 0, 0);
                            instruction_add(CBW, NULL, NULL, 0, 0);
                            instruction_add(CWDE, NULL, NULL, 0, 0);
                            break;
                    }
                    /* Push the result back on the stack. */
                    instruction_add(PUSH, eax, NULL, 0, 0);
                }
            }

            break;

        case VARIABLE:
            /*
             * Occurrences of variables: (declarations have their own case)
             * - Find the variable's stack offset
             * - If var is not local, unwind the stack to its correct base
             */

            /*
             * Here we want to push the value of a variable.
             *
             * The "if" is not really needed, but it decreases the amount of
             * instructions needed by one in cases where the variable is local.
             */
            if (depth == root->entry->depth) {
                instruction_add(PUSH, ebp, NULL, root->entry->stack_offset, 0);
            } else {
                instruction_add(MOVE, ebp, ecx, 0, 0);

                for (int i = 0; i < (depth - root->entry->depth); i++) {
                    /* Set ecx to the value pointed to by ecx. */
                    instruction_add(MOVE, STRDUP("(%ecx)"), ecx, 0, 0);
                }

                instruction_add(PUSH, ecx, NULL, root->entry->stack_offset, 0);
            }

            break;

        case INTEGER:
            /*
             * Integers: constants which can just be put on stack
             */

            /*
             * We want to push the integer to the stack, that's how we do
             * calculations around here.
             *
             * Here the integers may be negative, so we need another byte for
             * the buffer.
             */
            char_buffer = malloc(sizeof(*char_buffer) * 13);
            sprintf(char_buffer, "$%d", *(int*)root->data);
            instruction_add(PUSH, char_buffer, NULL, 0, 0);

            break;

        case ASSIGNMENT_STATEMENT:
            /*
             * Assignments:
             * Right hand side is an expression, find left hand side on stack
             * (unwinding if necessary)
             */

            /*
             * Get the value of the right-hand side expression at the top of
             * the stack, then into eax.
             */
            generate(stream, root->children[1]);
            instruction_add(POP, eax, NULL, 0, 0);

            /*
             * Get the left-hand side variable's offset, and store eax at that
             * location. See VARIABLE-case for comments on unwinding.
             */
            if (depth == root->children[0]->entry->depth) {
                instruction_add(MOVE, eax, ebp, 0, root->children[0]->entry->stack_offset);
            } else {
                instruction_add(MOVE, ebp, ecx, 0, 0);

                for (int i = 0; i < (depth - root->children[0]->entry->depth); i++) {
                    instruction_add(MOVE, STRDUP("(%ecx)"), ecx, 0, 0);
                }

                instruction_add(MOVE, eax, ecx, 0, root->children[0]->entry->stack_offset);
            }

            break;

        case RETURN_STATEMENT:
            /*
             * Return statements:
             * Evaluate the expression and put it in EAX
             */

            /* Get the expression's value at the top of the stack. */
            RECUR();

            /* And into eax, the return register. */
            instruction_add(POP, eax, NULL, 0, 0);

            /* One leave for every scope. */
            for (int i = 1; i < depth; i++) {
                instruction_add(LEAVE, NULL, NULL, 0, 0);
            }

            instruction_add(RET, NULL, NULL, 0, 0);
            break;

        default:
            /* Everything else can just continue through the tree */
            RECUR();
            break;
    }
}
示例#6
0
文件: vslc.c 项目: cristeahub/komptek
int
main ( int argc, char **argv )
{
	outputStage = 12;

    options ( argc, argv );

    symtab_init ();
    
    /* In order to only scan the tokens we call yylex() directly */
    if ( outputStage == 1 ) {
    	do { } while ( yylex() ); // "Token files"
        exit(0);
    }
    
    /* The parser calls yylex(), match the rules and builds the abstract syntax tree */
    // "BuildTree files"
    yyparse();
    if ( outputStage == 2 ) { 
        exit(0); // Exit if we are only printing this stages debug information. "BuildTree files"
    }
    
    /* Print the abstract syntax tree */
    if ( outputStage == 3 ) {
        node_print ( stderr, root, 0 ); // "Tree files"
        exit(0);
    }

    //simplify_tree ( root );
    /* Assign nodes functions according to their type; Handout first time only? */
    assignFunctionsToNodes( root );
    /* Simplify the abstract syntax tree */
    root->simplify( root, 0 );
    
    if ( outputStage == 4 ) { 
        exit(0); // Exit if we are only printing this stages debug information. "Build Simple Tree files"
    }

    /* Print the abstract syntax tree after simplification "Final Simple Tree files" */
    if ( outputStage == 5 ) {
        node_print ( stderr, root, 0 );
        exit(0);
    }

    //bind_names ( root );
    root->bind_names( root, 0);
    if ( outputStage == 6 || outputStage == 7) {
        exit(0); // Exit if we are only printing this stages debug information. "Scopes&String files" and "Symbol table files"
    }
    
    /* Print the .data (strings) segment of the assembly file */
    if ( outputStage == 8) {
        strings_output(stderr);
        exit(0);
    }
    
    /* Print the entries and string indexes in the node tree "Entries files" */
    if ( outputStage == 9) {
        node_print_entries ( stderr, root, 0 );
        exit(0);
    }
    
    root->typecheck(root);
    if (outputStage == 10) {
    	exit(0);
    }


    /* Parsing and semantics are ok, redirect stdout to file (if requested) */
    if ( outfile != NULL )
    {
        if ( freopen ( outfile, "w", stdout ) == NULL )
        {
            fprintf ( stderr, "Could not open output file '%s'\n", outfile );
            exit ( EXIT_FAILURE );
        }
        free ( outfile );
    }

	root->generate(root, 1);
	/*
	if(outputStage > 10 )
    	generate ( NULL, NULL, root ); // Output nothing, for later debugging stages.
    else if(outputStage == 10 )
    	generate ( NULL, stderr, root ); // Output only the traversal process.
    else if(outputStage == -1 )
    	generate ( stderr, NULL, root ); // Output the asm as no debug text is made.
	*/
	
    //destroy_subtree ( stderr, root );
    
    if ( outputStage == 11 ) {
    	destroy_subtree ( stderr, root );
        exit(0);
    } else
    	destroy_subtree ( NULL, root );
    
    symtab_finalize();
    
    yylex_destroy(); // Free internal data structures of the scanner.

    exit ( EXIT_SUCCESS );
}
示例#7
0
文件: generator.c 项目: sondrele/NTNU
void generate ( FILE *stream, node_t *root )
{
	int elegant_solution;
	if ( root == NULL )
		return;

	switch ( root->type.index )
	{
		case PROGRAM: {
			/* Output the data segment */
			strings_output ( stream );
			instruction_add ( STRING, STRDUP( ".text" ), NULL, 0, 0 );

			RECUR ();
			TEXT_HEAD ();
			/* TODO: Insert a call to the first defined function here */
			node_t *main_func = root->children[0]->children[0];
			instruction_add ( CALL, STRDUP( (char *) main_func->children[0]->data ),
					NULL, 0, 0);
			TEXT_TAIL ();

			instructions_print ( stream );
			instructions_finalize ();
			break;
		}
		case FUNCTION: {
			/*
			 * Function definitions:
			 * Set up/take down activation record for the function, return value
			 */
			depth += 1;
			instruction_add ( LABEL, STRDUP( root->children[0]->data ), NULL, 0, 0 );
			instruction_add ( PUSH, ebp, NULL, 0, 0 );
			instruction_add ( MOVE, esp, ebp, 0, 0 );
			// Generate for the children, except for the BLOCK-statement
			generate ( stream, root->children[2]->children[0] );
			generate ( stream, root->children[2]->children[1] );
			instruction_add ( LEAVE, NULL, NULL, 0, 0 );
			instruction_add ( RET, NULL, NULL, 0, 0 );
			depth -= 1;
			break;
		}
		case BLOCK: {
			/*
			 * Blocks:
			 * Set up/take down activation record, no return value
			 */
			depth += 1;
			instruction_add ( PUSH, ebp, NULL, 0, 0 );
			instruction_add ( MOVE, esp, ebp, 0, 0 );
			generate ( stream, root->children[0] );
			// This is done in order to avoid executing any statements in a STATEMENT_LIST,
			// that is occuring after a RETURN_STATEMENT 
			node_t *statement_list_n = root->children[1];
			for ( int i = 0; i < statement_list_n->n_children; i++ ) {
				generate ( stream, statement_list_n->children[i] );
				if ( statement_list_n->children[i]->type.index == RETURN_STATEMENT )
					break;
			}
			// Push a dummy value to the stack, so LEAVE works properly
			instruction_add ( PUSH, STRDUP( "$0" ), NULL, 0, 0 );
			instruction_add ( LEAVE, NULL, NULL, 0, 0 );
			depth -= 1;
			break;
		}
		case DECLARATION: {
			/*
			 * Declarations:
			 * Add space on local stack
			 */
			int offset = 0;
			for ( int i = 0; i < root->children[0]->n_children; i++ ) {
				offset -= 4;
				instruction_add ( PUSH, esp, NULL, offset, 0 );
			}
			break;
		}
		case PRINT_LIST: {
			/*
			 * Print lists:
			 * Emit the list of print items, followed by newline (0x0A)
			 */
			instruction_add ( PUSH, ecx, NULL, 0, 0 );
			RECUR ();
			instruction_add ( PUSH, STRDUP( "$10" ), NULL, 0, 0 );
			instruction_add ( SYSCALL, STRDUP( "putchar" ), NULL, 0, 0 );
			instruction_add ( ADD, STRDUP( "$4" ), esp, 0, 0 );
			instruction_add ( POP, ecx, NULL, 0, 0 );
			break;
		}
		case PRINT_ITEM: {
			/*
			 * Items in print lists:
			 * Determine what kind of value (string literal or expression)
			 * and set up a suitable call to printf
			 */
			if ( root->children[0]->type.index == TEXT ) {
				char str[30];
				sprintf ( str, "$.STRING%d", *(int *)root->children[0]->data );
				instruction_add ( PUSH, STRDUP( str ), NULL, 0, 0 );
				instruction_add ( SYSCALL, STRDUP( "printf" ), NULL, 0, 0 );
				instruction_add ( ADD, STRDUP( "$4" ), esp, 0, 0 );
			} else {
				// Add expression to top of stack, for use in printf
				generate ( stream, root->children[0] );
				instruction_add ( PUSH, STRDUP( "$.INTEGER" ), NULL, 0, 0 );
				instruction_add ( SYSCALL, STRDUP( "printf" ), NULL, 0, 0 );
				instruction_add ( ADD, STRDUP( "$8" ), esp, 0, 0 );
			}
			break;
		}
		case EXPRESSION: {
			/*
			 * 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)
			 */
			// The expression is a function call
			if ( root->n_children == 2 && ( root->children[1] == NULL
					|| root->children[1]->type.index == EXPRESSION_LIST ) ) {
				// Push parameters on stack
				generate ( stream, root->children[1] );
				instruction_add ( CALL, STRDUP( (char *) root->children[0]->data ),
					NULL, 0, 0);
				// The evaluated expression to the stack
				instruction_add ( PUSH, eax, NULL, 0, 0 );
			} else if ( root->n_children == 2) {
				RECUR ();
				instruction_add ( POP, ebx, NULL, 0, 0 );
				instruction_add ( POP, eax, NULL, 0, 0 );
				char *data = (char *) root->data;
				switch ( data[0] ) {
					case '+':
						instruction_add ( ADD, ebx, eax, 0, 0 );
						break;
					case '-':
						instruction_add ( SUB, ebx, eax, 0, 0 );
						break;
					case '*':
						instruction_add ( MUL, ebx, NULL, 0, 0 );
						break;
					case '/':
						instruction_add ( CLTD, NULL, NULL, 0, 0 );
						instruction_add ( DIV, ebx, NULL, 0, 0 );
						break;
					// The following cases is a bit repetative, I know
					// Maybe gcc will optimize it a bit? ;-)
					case '=':
						instruction_add ( CMP, ebx, eax, 0, 0 );
						instruction_add ( SETE, al, NULL, 0, 0 );
						instruction_add ( CBW, NULL, NULL, 0, 0 );
						instruction_add ( CWDE, NULL, NULL, 0, 0 );
						break;
					case '!':
						instruction_add ( CMP, ebx, eax, 0, 0 );
						instruction_add ( SETNE, al, NULL, 0, 0 );
						instruction_add ( CBW, NULL, NULL, 0, 0 );
						instruction_add ( CWDE, NULL, NULL, 0, 0 );
						break;
					case '>':
						instruction_add ( CMP, ebx, eax, 0, 0 );
						if ( strlen( data ) == 2 )
							instruction_add ( SETGE, al, NULL, 0, 0 );
						else
							instruction_add ( SETG, al, NULL, 0, 0 );
						instruction_add ( CBW, NULL, NULL, 0, 0 );
						instruction_add ( CWDE, NULL, NULL, 0, 0 );
						break;
					case '<':
						instruction_add ( CMP, ebx, eax, 0, 0 );
						if ( strlen( data ) == 2 )
							instruction_add ( SETLE, al, NULL, 0, 0 );
						else
							instruction_add ( SETL, al, NULL, 0, 0 );
						instruction_add ( CBW, NULL, NULL, 0, 0 );
						instruction_add ( CWDE, NULL, NULL, 0, 0 );
						break;
				}
				instruction_add ( PUSH, eax, NULL, 0, 0 );
			} else if ( root->data != NULL && *(char *)root->data == '-' ) {
				// Unary minus
				RECUR ();
				instruction_add ( POP, eax, NULL, 0, 0 );
				instruction_add ( NEG, eax, NULL, 0, 0 );
				instruction_add ( PUSH, eax, NULL, 0, 0 );
			}
			break;
		}
		case VARIABLE: {
			/*
			 * Occurrences of variables: (declarations have their own case)
			 * - Find the variable's stack offset
			 * - If var is not local, unwind the stack to its correct base
			 */
			int stack_offset = root->entry->stack_offset;
			// If the variable is at right deapth, or it is a function argument, PUSH
			// the value of variable to the stack
			if ( depth == root->entry->depth  
					|| stack_offset > 0 && root->entry->depth == (depth-1) ) {
				instruction_add ( PUSH, ebp, NULL, stack_offset, 0 );
			} else {
				// Else unwind
				instruction_add ( MOVE, ebp, ebx, 0, 0 );
				// If the variable is an argument, the deapth, i.e. 'i', is decreased
				// by 1
				int i = stack_offset > 0 ? -1 : 0;
				for ( i += depth-1; i >= root->entry->depth; i-- ) {
					instruction_add ( MOVE, STRDUP("(%ebx)"), ebx, 0, 0 );
				}
				instruction_add ( PUSH, ebx, NULL, stack_offset, 0 );
			}
			break;
		}
		case ASSIGNMENT_STATEMENT: {
			/*
			 * Assignments:
			 * Right hand side is an expression, find left hand side on stack
			 * (unwinding if necessary)
			 */
			// This behaves almost the same as the VARIABLE case
			generate ( stream, root->children[1] );
			root->entry = root->children[0]->entry;
			int stack_offset = root->entry->stack_offset;
			if ( depth == root->entry->depth ) {
				instruction_add ( POP, ebp, NULL, stack_offset, 0 );
			} else {
				instruction_add ( MOVE, ebp, ebx, 0, 0 );
				for ( int i = depth-1; i >= root->entry->depth; i-- ) {
					instruction_add ( MOVE, STRDUP("(%ebx)"), ebx, 0, 0 );
				}
				instruction_add ( POP, ebx, NULL, stack_offset, 0 );
			}
			break;
		}
		case INTEGER: {
			/*
			 * Integers: constants which can just be put on stack
			 */
			char str[30];
			sprintf ( str, "$%d", *(int *)root->data );
			instruction_add ( PUSH, STRDUP( str ), NULL, 0, 0 );

			break;
		}
		case RETURN_STATEMENT: {
			/*
			 * Return statements:
			 * Evaluate the expression and put it in EAX
			 */
			RECUR ();
			instruction_add ( POP, eax, NULL, 0, 0 );
			break;
		}
		case WHILE_STATEMENT: {
            char whilestart[30];
            char _whilestart[30];
            char whileend[30];
            char _whileend[30];
            sprintf ( whilestart, "whilestart%d", while_label );
            sprintf ( _whilestart, "_whilestart%d", while_label );
            sprintf ( whileend, "whileend%d", while_label );
            sprintf ( _whileend, "_whileend%d", while_label++ );

            instruction_add ( LABEL, STRDUP( whilestart ), NULL, 0, 0 );
    		generate ( stream, root->children[0] );
            instruction_add ( CMPZERO, eax, NULL, 0, 0 );
            instruction_add ( JUMPZERO,  STRDUP( _whileend ), NULL, 0, 0 );
            generate ( stream, root->children[1] );
            instruction_add ( JUMP, STRDUP( _whilestart ), NULL, 0, 0 );
            instruction_add ( LABEL, STRDUP( whileend ), NULL, 0, 0 );
            break;
        }
        case FOR_STATEMENT: {
            char forstart[30];
            char _forstart[30];
            char forend[30];
            char _forend[30];
            sprintf ( forstart, "forstart%d", for_label );
            sprintf ( _forstart, "_forstart%d", for_label++ );

            // Initialize ecx, i.e. the loop counter
            generate ( stream, root->children[0] );
            instruction_add ( PUSH, eax, NULL, 0, 0 );
            instruction_add ( MOVE, eax, edi, 0, 0 );
            generate ( stream, root->children[1] );
            instruction_add ( POP, eax, NULL, 0,0 ); 
            instruction_add ( POP, ebx, NULL, 0,0 );
            instruction_add ( SUB, ebx, eax, 0,0 );
            instruction_add ( PUSH, eax, NULL, 0,0 );
            instruction_add ( POP, ecx, NULL, 0, 0 );
            
            // Start loop
            instruction_add ( LABEL, STRDUP( forstart ), NULL, 0, 0 );
            generate ( stream, root->children[2] );

            // Increment counter
            instruction_add ( ADD, STRDUP( "$1" ), edi, 0, 0 );
            instruction_add ( PUSH, edi, NULL, 0, 0 );
            depth_difference = depth - root->children[0]->children[0]->entry->depth;
            instruction_add(PUSH, ebp, NULL, 0,0);
            for(int c = 0; c < depth_difference; c++){
                instruction_add(MOVE, STRDUP("$4"), eax, 0,0);
                instruction_add(ADD, ebp, eax, 0,0);
                instruction_add(MOVE, eax, ebp, -4,0);
            }
            int32_t offset_2 = root->children[0]->children[0]->entry->stack_offset;
            //Putting the current ebp in ebx
            instruction_add(POP, ebx, NULL, 0,0);
            //Putting the result of the expression in eax
            instruction_add(POP, eax, NULL, 0,0);
            //Putting the result of the expression in the variable (ebp is the ebp of the variable)
            instruction_add(MOVE, eax, ebp, 0, offset_2);
            //Restoring the current ebp
            instruction_add(MOVE, ebx, ebp, 0, 0);

            // Loop
            instruction_add ( LOOP, STRDUP( _forstart ), NULL, 0, 0 );
            //instruction_add ( JUMPZERO, STRDUP( "TEST" ), NULL, 0, 0 );
            break;
        }
        case IF_STATEMENT: {
            char ifend[30];
            char _ifend[30];
            char ifelse[30];
            char _ifelse[30];
            sprintf ( ifend, "ifend%d", if_label );
            sprintf ( _ifend, "_ifend%d", if_label );
            sprintf ( ifelse, "ifelse%d", if_label );
            sprintf ( _ifelse, "_ifelse%d", if_label++ );
            // IF-THEN-FI
            if ( root->n_children == 2 ) {
                char str[30];
                node_t *expr = root->children[0];
                sprintf ( str, "expr: n:%d", expr->n_children );
                instruction_add ( JUMPZERO, STRDUP(str), NULL, 0, 0 );
                generate ( stream, root->children[0] );
                instruction_add ( CMPZERO, eax, NULL, 0, 0 );
                instruction_add ( JUMPZERO,  STRDUP( _ifend ), NULL, 0, 0 );
                generate ( stream, root->children[1] );
                instruction_add ( LABEL, STRDUP( ifend ), NULL, 0, 0 );
            } // IF-THEN-ELSE-FI
            else {
                generate ( stream, root->children[0] );
                instruction_add ( CMPZERO, eax, NULL, 0, 0 );
                instruction_add ( JUMPZERO,  STRDUP( _ifelse ), NULL, 0, 0 );
                generate ( stream, root->children[1] );
                instruction_add ( JUMP, STRDUP( _ifend ), NULL, 0, 0 );
                instruction_add ( LABEL, STRDUP( ifelse ), NULL, 0, 0 );
                generate ( stream, root->children[2] );
                instruction_add ( JUMP, STRDUP( _ifend ), NULL, 0, 0 );
                instruction_add ( LABEL, STRDUP( ifend ), NULL, 0, 0 );
            }
            break;
        }
		default:
			/* Everything else can just continue through the tree */
			RECUR();
			break;
	}
}