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 (); }
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 (); }
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"); }
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"); }
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; }
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"); }
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"); }
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"); }
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); }
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; }
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; }
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); }
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"); }
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); }
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); }