Exemplo n.º 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();
	
	/* 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 ();
}
Exemplo n.º 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();

    gp(root,scopedepth);


    tracePrint("End PROGRAM\n");

    TEXT_TAIL_ARM();

    if( outputStage == 12 )
        instructions_print ( stderr );
    instructions_finalize ();
}
Exemplo n.º 3
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.º 4
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){
		// Fetching address value from child 1, pushing to top of stack:
		root->children[0]->children[0]->generate(root->children[0]->children[0], scopedepth);
		// Now popping THIS (a.k.a. the objects address value) from stack into r2:
		instruction_add(POP, r2, NULL, 0,0);
		// Now popping result from expression into r1:
		instruction_add(POP, r1, NULL, 0,0);
		// Now storing to the address on the heap, based on address from child 1 and offset from child 2:
		instruction_add(STORE, r1, r2, 0, root->children[0]->children[1]->entry->stack_offset);
	}
	// or a variable, handled in previous assignment
	else{
		ga(root,scopedepth);
	}

	tracePrint ( "End ASSIGNMENT_STATEMENT\n");
}
Exemplo n.º 5
0
void traceExit(CELL * result, CELL * cell, CELL * pCell, CELL * args)
{
if(traceFlag & (TRACE_IN_ENTRY | TRACE_IN_EXIT | TRACE_SIGNAL | TRACE_SIGINT | TRACE_TIMER)) return;

if(traceFlag == TRACE_PRINT_EVAL)
    {
    tracePrint("exit", result);
    return;
    }

traceFlag |= TRACE_IN_EXIT;

#ifdef DEBUGGER
if(traceFlag & TRACE_DEBUG_NEXT)
    {
    if(currentLevel >= recursionCount)
        traceFlag &= ~TRACE_DEBUG_NEXT;
    else 
        {
        traceFlag &= ~TRACE_IN_EXIT;
        return;
        }
    }

if( (pCell->type == CELL_LAMBDA || pCell->type == CELL_FEXPR)
        && args->type == CELL_SYMBOL)
    {
    if((UINT)recursionCount == *(debugStack + debugStackIdx - 2) )
        {
        debugStackIdx -= 2;
        if(debugStackIdx > 0)
            currentFunc = (SYMBOL *)*(debugStack + debugStackIdx - 1);
        if(debugStackIdx == 0)
            traceFlag &= ~TRACE_DEBUG_NEXT;
        }
    }

if(debugPrintFunction(cell))
    {
    varPrintf(OUT_CONSOLE, "\nRESULT: ");
    printCell(result, TRUE, OUT_CONSOLE);
    varPrintf(OUT_CONSOLE, "\n");

    if(debugStackIdx > 0)
        {
        getDebuggerInput(DEBUG_EXIT);
        if(!traceFlag) return;
        }
    }

if(traceFlag & TRACE_DEBUG_NEXT)
    currentLevel = recursionCount;
#endif /* DEBUGGER */

traceFlag &= ~TRACE_IN_EXIT;
}
Exemplo n.º 6
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){

    }
    // or a variable, handled in previous assignment
    else{
        ga(root,scopedepth);
    }

    tracePrint ( "End ASSIGNMENT_STATEMENT\n");
}
Exemplo n.º 7
0
void gen_IF_STATEMENT ( node_t *root, int scopedepth )
{
    tracePrint("Starting IF_STATEMENT\n");

    if_count++;
    int our_count = if_count;

    // Expand If-expression
    node_t *cond = root->children[0];
    cond->generate(cond, scopedepth);

    char tmp_if_end[20];
    char tmp_if_else[20];
    sprintf(tmp_if_end, "_if_end_%d", if_count);
    sprintf(tmp_if_else, "_if_else_%d", if_count);

    // Test truth value
    instruction_add(POP, r1, NULL, 0, 0);
    instruction_add(CMP, r1, "#0", 0, 0);

    node_t *statement_if = root->children[1];
    if (root->n_children == 2) { // If-end statement
        // If code
        instruction_add(JUMPZERO, STRDUP(tmp_if_end), NULL, 0, 0);
        statement_if->generate(statement_if, scopedepth);
    } else { // If-else-end statement
        // If code
        instruction_add(JUMPZERO, STRDUP(tmp_if_else), NULL, 0, 0);
        statement_if->generate(statement_if, scopedepth);
        instruction_add(JUMP, STRDUP(tmp_if_end), NULL, 0, 0);

        // Else code
        instruction_add(LABEL, STRDUP(tmp_if_else + 1), NULL, 0, 0);
        node_t *statement_else = root->children[2];
        statement_else->generate(statement_else, scopedepth);
    }

    // End label
    instruction_add(LABEL, STRDUP(tmp_if_end + 1), NULL, 0, 0);

    tracePrint("End IF_STATEMENT\n");
}
Exemplo n.º 8
0
void gen_WHILE_STATEMENT ( node_t *root, int scopedepth )
{
    tracePrint("Starting WHILE_STATEMENT\n");

    while_count++;
    int our_count = while_count;

    char tmp_while_start[20];
    char tmp_while_end[20];
    sprintf(tmp_while_start, "_while_start_%d", our_count);
    sprintf(tmp_while_end, "_while_end_%d", our_count);

    // Set start label
    instruction_add(LABEL, STRDUP(tmp_while_start + 1), NULL, 0, 0);

    // Expand while-expression
    node_t *cond = root->children[0];
    cond->generate(cond, scopedepth);

    // Test truth value, jump to end if zero
    instruction_add(POP, r1, NULL, 0, 0);
    instruction_add(CMP, r1, "#0", 0, 0);
    instruction_add(JUMPZERO, STRDUP(tmp_while_end), NULL, 0, 0);

    // Execute while-loop statement body
    node_t *while_body = root->children[1];
    while_body->generate(while_body, scopedepth);

    // Return to top of while loop)
    instruction_add(JUMP, STRDUP(tmp_while_start), NULL, 0, 0);
    
    // Set end label
    instruction_add(LABEL, STRDUP(tmp_while_end + 1), NULL, 0 ,0);

    tracePrint("End WHILE_STATEMENT\n");
}
Exemplo n.º 9
0
void
traceRegAround()
{
   if (!gRegTraceState || gRegTraceIndex < 0) {
      debugPrint("Need to use traceRegStart first.");
      return;
   }

   int start = gRegTraceIndex - 5;
   int end = gRegTraceIndex + 4;

   auto tracer = gRegTraceState->tracer;
   auto tracerSize = static_cast<int>(tracer->trace.size());

   if (start < 0) {
      start = 0;
   }
   if (end > tracerSize) {
      end = tracerSize;
   }

   tracePrint(gRegTraceState, start, end - start);
}
Exemplo n.º 10
0
link RBinsert(link h, Item item, int sw)
// Program 13.6 coded to be a bit clearer and make mutually exclusive
// cases obvious.  Also includes tracing.  See 2320 notes.  BPW
// h is present node in search down tree.
// Returns root of modified subtree.
// item is the Item to be inserted.
// sw == 1 <=> h is to the right of its parent.
{
Key v = key(item);
link before;  // Used to trigger printing of an intermediate tree

tracePrint("Down",h);
if (h == z)
  return NEW(item, z, z, 1);  // Attach red leaf

if ((h->l->red) && (h->r->red))      // Flip colors before searching down
{
  tracePrint("Color flip",h);
  h->red = 1;
  h->l->red = 0;
  h->r->red = 0;
  if (trace==2)
    STprintTree();
}

if (less(v, key(h->item))) 
{ 
  tracePrint("Insert left",h);
  before=h->l;
  h->l = RBinsert(h->l, item, 0);    // Insert in left subtree
  if (trace==2 && before!=h->l)      // Has a rotation occurred?
    STprintTree();
  if (h->l->red)
    if (h->red)
      if (sw)
      {
        tracePrint("Case ~1",h);
        h = rotR(h);                 // Set up case ~2 after return
      }
      else
        ;
    else if (h->l->l->red)
    {
      tracePrint("Case 2",h);
      h = rotR(h);
      h->red = 0;
      h->r->red = 1;
    }
}
else
{
  tracePrint("Insert right",h);
  before=h->r;
  h->r = RBinsert(h->r, item, 1);    // Insert in right subtree
  if (trace==2 && before!=h->r)      // Has a rotation occurred?
    STprintTree();
  if (h->r->red)
    if (h->red)
      if (!sw)
      {
        tracePrint("Case 1",h);
        h = rotL(h);                 // Set up case 2 after return
      }
      else
        ;
    else if (h->r->r->red)
    {
      tracePrint("Case ~2",h);
      h = rotL(h);
      h->red = 0;
      h->l->red = 1;
    }
}

fixRank(h); //fix the rank after rotating
tracePrint("Up",h);
return h;
}
Exemplo n.º 11
0
void traceEntry(CELL * cell, CELL * pCell, CELL * args)
{
if(traceFlag & (TRACE_IN_ENTRY | TRACE_IN_EXIT | TRACE_DEBUG_NEXT)) return;
traceFlag |= TRACE_IN_ENTRY;

#ifdef DEBUGGER
int defaultFuncFlag = FALSE;
#endif

if(traceFlag & TRACE_SIGNAL)
    {
    traceFlag &= ~TRACE_SIGNAL;
    executeSymbol(symHandler[currentSignal - 1], stuffInteger(currentSignal), NULL);
    traceFlag &= ~TRACE_IN_ENTRY;
    return;
    }

if(traceFlag & TRACE_SIGINT)
    {
    traceFlag &= ~TRACE_SIGINT;
    longjmp(errorJump, ERR_USER_RESET);
    }
    
if(traceFlag & TRACE_TIMER)
    {
    traceFlag &= ~TRACE_TIMER;
    executeSymbol(timerEvent, NULL, NULL);
    traceFlag &= ~TRACE_IN_ENTRY;
    return;
    }

if(traceFlag & TRACE_PRINT_EVAL)
    {
    if(cell->type == CELL_EXPRESSION) tracePrint("entry", cell);
    traceFlag &= ~TRACE_IN_ENTRY;
    return;
    }

#ifdef DEBUGGER
if(debugStackIdx > 1)
    {
    if(debugPrintFunction(cell))
        getDebuggerInput(DEBUG_ENTRY);
    if(!traceFlag) return;
    }

if(traceFlag & TRACE_DEBUG_NEXT)
    {
    traceFlag &= ~TRACE_IN_ENTRY;
    return;
    }

if(pCell->type == CELL_CONTEXT)
    {
    defaultFuncFlag = TRUE;
    currentFunc = translateCreateSymbol(
            ((SYMBOL*)pCell->contents)->name,
            CELL_NIL,
            (SYMBOL*)pCell->contents,
            TRUE);

    pCell = (CELL *)currentFunc->contents;
    }

if((pCell->type == CELL_LAMBDA || pCell->type == CELL_FEXPR)
    && args->type == CELL_SYMBOL)
    {
    if(debugStackIdx == 0) /* startup */
        traceFlag &= ~TRACE_DEBUG_NEXT;
    
    if(!defaultFuncFlag)
        currentFunc = (SYMBOL *)args->contents; 
    pushDebugStack(recursionCount);
    pushDebugStack(currentFunc);
    }
#endif /* no_DEBUG */

traceFlag &= ~TRACE_IN_ENTRY;
}
Exemplo n.º 12
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.º 13
0
void gen_PRINT_STATEMENT(node_t* root, int scopedepth)
{
    tracePrint("Starting PRINT_STATEMENT\n");

    for(int i = 0; i < root->children[0]->n_children; i++){

        root->children[0]->children[i]->generate(root->children[0]->children[i], scopedepth);

        //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
        base_data_type_t t = root->children[0]->children[i]->data_type.base_type;
        switch(t)
        {
            case INT_TYPE:
                instruction_add(STRING, STRDUP("\tmovw	r0, #:lower16:.INTEGER"), NULL, 0,0);
                instruction_add(STRING, STRDUP("\tmovt	r0, #:upper16:.INTEGER"), NULL, 0,0);
                instruction_add(POP, r1, NULL, 0,0);
                break;

            case FLOAT_TYPE:
                instruction_add(LOADS, sp, s0, 0,0);
                instruction_add(CVTSD, s0, d0, 0,0);
                instruction_add(STRING, STRDUP("\tfmrrd	r2, r3, d0"), NULL, 0,0);
                instruction_add(STRING, STRDUP("\tmovw	r0, #:lower16:.FLOAT"), NULL, 0,0);
                instruction_add(STRING, STRDUP("\tmovt	r0, #:upper16:.FLOAT"), NULL, 0,0);

                // And now the tricky part... 8-byte stack alignment :(
                // We have at least 4-byte alignment always.
                // Check if its only 4-byte aligned right now by anding that bit in the stack-pointer.
                // Store the answer in r5, and set the zero flag.
                instruction_add(STRING, STRDUP("\tandS	r5, sp, #4"), NULL, 0,0);
                // Now use the zero flag as a condition to optionally change the stack-pointer
                instruction_add(STRING, STRDUP("\tpushNE	{r5}"), NULL, 0,0);
                break;

            case BOOL_TYPE:
                instruction_add(STRING, STRDUP("\tmovw	r0, #:lower16:.INTEGER"), NULL, 0,0);
                instruction_add(STRING, STRDUP("\tmovt	r0, #:upper16:.INTEGER"), NULL, 0,0);
                instruction_add(POP, r1, NULL, 0,0);
                break;

            case STRING_TYPE:
                instruction_add(POP, r0, NULL, 0,0);
                break;

            default:
                instruction_add(PUSH, STRDUP("$.INTEGER"), NULL, 0,0);
                fprintf(stderr, "WARNING: attempting to print something not int, float or bool\n");
                break;
        }

        instruction_add(SYSCALL, STRDUP("printf"), NULL,0,0);

        // Undo stack alignment.
        if(t == FLOAT_TYPE) {
            // Redo the zero flag test on r5, as it will give the same answer as the first test on sp.
            instruction_add(STRING, STRDUP("\tandS	r5, #4"), NULL, 0,0);
            // Conditionally remove the alignment. 
            instruction_add(STRING, STRDUP("\tpopNE	{r5}"), NULL, 0,0);
        }
    }

    instruction_add(MOVE32, STRDUP("#0x0A"), r0, 0,0);
    instruction_add(SYSCALL, STRDUP("putchar"), NULL, 0,0);

    tracePrint("Ending PRINT_STATEMENT\n");
}
Exemplo n.º 14
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.º 15
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);
}